Skip to content

Commit

Permalink
MWPW-161575: Unit tests added for DA FB (#3405)
Browse files Browse the repository at this point in the history
* bulk action unit tests

* promote class unit tests

* fg utils unit tests updated
  • Loading branch information
sukamat authored Dec 23, 2024
1 parent f6e0797 commit 347d163
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 4 deletions.
75 changes: 75 additions & 0 deletions test/tools/floodbox/bulk-action.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { expect } from '@esm-bundle/chai';
import sinon from 'sinon';
import previewOrPublishPaths, { BulkAction } from '../../../tools/floodbox/bulk-action.js';
import RequestHandler from '../../../tools/floodbox/request-handler.js';

describe('BulkAction', () => {
const org = 'testOrg';
const repo = 'testRepo';
const callback = sinon.spy();
const paths = ['/testOrg/testRepo/content/test1.html', '/testOrg/testRepo/content/test2.html'];
const action = 'publish';
let daFetchStub;
let delayStub;

beforeEach(() => {
daFetchStub = sinon.stub(RequestHandler.prototype, 'daFetch');
delayStub = sinon.stub(BulkAction, 'delay').resolves();
callback.resetHistory();
});

afterEach(() => {
daFetchStub.restore();
delayStub.restore();
});

it('should successfully process all paths in batches', async () => {
daFetchStub.resolves({ ok: true, status: 200 });

await previewOrPublishPaths({ org, repo, paths, action, callback });

sinon.assert.callCount(daFetchStub, paths.length);
sinon.assert.callCount(callback, paths.length);
sinon.assert.calledWithMatch(callback, { statusCode: 200 });
});

it('should handle failed requests and call callback with error', async () => {
daFetchStub.onFirstCall().resolves({ ok: false, status: 500 });
daFetchStub.onSecondCall().resolves({ ok: true, status: 200 });

await previewOrPublishPaths({ org, repo, paths, action, callback });

sinon.assert.callCount(daFetchStub, paths.length);
sinon.assert.calledWithMatch(callback, { statusCode: 500, errorMsg: `Failed to ${action}` });
});

it('should clean up paths correctly', async () => {
const cleanedPaths = paths.map((path) => BulkAction.cleanUpPath(path));
expect(cleanedPaths).to.eql(['/content/test1', '/content/test2']);
});

it('should delay between batches', async () => {
daFetchStub.resolves({ ok: true, status: 200 });

const longPaths = Array(25).fill('/testOrg/testRepo/content/test1.html');
await previewOrPublishPaths({ org, repo, paths: longPaths, action, callback });

sinon.assert.calledOnce(delayStub);
});

it('should handle delete requests', async () => {
daFetchStub.resolves({ ok: true, status: 200 });

await previewOrPublishPaths({
org, repo, paths, action: 'delete', callback, isDelete: true,
});

sinon.assert.callCount(daFetchStub, paths.length);

const args = [
'https://admin.hlx.page/delete/testOrg/testRepo/main/content/test1',
{ method: 'DELETE' },
];
sinon.assert.calledWithMatch(daFetchStub.firstCall, args[0], args[1]);
});
});
18 changes: 17 additions & 1 deletion test/tools/floodbox/floodgate/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from '@esm-bundle/chai';
import { validatePaths } from '../../../../tools/floodbox/floodgate/utils.js';
import { getValidFloodgate, validatePaths } from '../../../../tools/floodbox/floodgate/utils.js';

describe('validatePaths', () => {
it('returns valid true with correct org and repo for valid paths', () => {
Expand Down Expand Up @@ -44,3 +44,19 @@ describe('validatePaths', () => {
expect(result).to.eql({ valid: false, org: '', repo: '' });
});
});

describe('getValidFloodgate', () => {
it('should return a milo-floodgate element with correct properties', async () => {
// fake DA_SDK response with context and token
const fakeDaSdk = Promise.resolve({
context: { repo: 'fake-repo' },
token: 'fake-token',
});
const cmp = await getValidFloodgate(fakeDaSdk);

expect(cmp).to.be.instanceOf(HTMLElement);
expect(cmp.tagName.toLowerCase()).to.equal('milo-floodgate');
expect(cmp.repo).to.equal('fake-repo');
expect(cmp.token).to.equal('fake-token');
});
});
108 changes: 108 additions & 0 deletions test/tools/floodbox/promote.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import sinon from 'sinon';
import promoteFiles from '../../../tools/floodbox/promote.js';
import RequestHandler from '../../../tools/floodbox/request-handler.js';

describe('Promote', () => {
const accessToken = 'testToken';
const org = 'testOrg';
const repo = 'testRepo-pink';
const expName = 'testExp';
const files = [
{ path: '/testOrg/testRepo-pink/content/test1.html', ext: 'html' },
{ path: '/testOrg/testRepo-pink/content/test2.json', ext: 'json' },
];
const callback = sinon.spy();
let promoteType = 'floodgate';
let daFetchStub;
let uploadContentStub;

beforeEach(() => {
daFetchStub = sinon.stub(RequestHandler.prototype, 'daFetch');
uploadContentStub = sinon.stub(RequestHandler.prototype, 'uploadContent');
callback.resetHistory();
});

afterEach(() => {
daFetchStub.restore();
uploadContentStub.restore();
});

it('should promote files successfully', async () => {
daFetchStub.resolves({ ok: true, text: () => 'file content' });
uploadContentStub.resolves({ statusCode: 200 });

await promoteFiles({
accessToken, org, repo, promoteType, files, callback,
});

sinon.assert.callCount(daFetchStub, files.length);
sinon.assert.callCount(uploadContentStub, files.length);
sinon.assert.callCount(callback, files.length);
sinon.assert.calledWithMatch(callback, { statusCode: 200 });
});

it('should handle fetch errors', async () => {
daFetchStub.resolves({ ok: false, status: 404 });

await promoteFiles({
accessToken, org, repo, promoteType, files, callback,
});

sinon.assert.callCount(daFetchStub, files.length);
sinon.assert.callCount(callback, files.length);
sinon.assert.calledWithMatch(callback, { statusCode: 404, errorMsg: 'Failed to fetch' });
});

it('should handle upload errors', async () => {
daFetchStub.resolves({ ok: true, text: () => 'file content' });
uploadContentStub.resolves({ statusCode: 500, errorMsg: 'Failed to upload file' });

await promoteFiles({
accessToken, org, repo, promoteType, files, callback,
});

sinon.assert.callCount(daFetchStub, files.length);
sinon.assert.callCount(uploadContentStub, files.length);
sinon.assert.callCount(callback, files.length);
sinon.assert.calledWithMatch(callback, { statusCode: 500, errorMsg: 'Failed to upload file' });
});

it('should handle blob content', async () => {
const blob = new Blob(['file content'], { type: 'application/octet-stream' });
daFetchStub.resolves({ ok: true, blob: () => blob });
uploadContentStub.resolves({ statusCode: 200 });

const fileArr = [
{ path: '/testOrg/testRepo-pink/content/image.png', ext: 'png' },
];
await promoteFiles({
accessToken, org, repo, promoteType, files: fileArr, callback,
});

sinon.assert.callCount(daFetchStub, fileArr.length);
sinon.assert.callCount(uploadContentStub, fileArr.length);
sinon.assert.callCount(callback, fileArr.length);
sinon.assert.calledWithMatch(callback, { statusCode: 200 });
});

it('should handle promoteType graybox', async () => {
daFetchStub.resolves({ ok: true, text: () => 'file content' });
uploadContentStub.resolves({ statusCode: 200 });

promoteType = 'graybox';
const gbFiles = [
{ path: '/testOrg/testRepo-graybox/testExp/content/test1.html', ext: 'html' },
{ path: '/testOrg/testRepo-graybox/testExp/content/test2.json', ext: 'json' },
];
await promoteFiles({
accessToken, org, repo: 'testRepo-graybox', expName, promoteType, files: gbFiles, callback,
});

sinon.assert.callCount(daFetchStub, gbFiles.length);
sinon.assert.callCount(uploadContentStub, gbFiles.length);
sinon.assert.callCount(callback, gbFiles.length);
sinon.assert.calledWithMatch(callback, { statusCode: 200 });

sinon.assert.calledWithMatch(uploadContentStub, '/testOrg/testRepo/content/test1.html');
});
});
2 changes: 1 addition & 1 deletion tools/floodbox/bulk-action.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import RequestHandler from './request-handler.js';
const BATCH_SIZE = 25;
const BATCH_DELAY = 2000;

class BulkAction {
export class BulkAction {
constructor({ org, repo, callback }) {
this.org = org;
this.repo = repo;
Expand Down
4 changes: 2 additions & 2 deletions tools/floodbox/floodgate/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ function validatePaths(paths) {
return { valid: true, org, repo };
}

async function getValidFloodgate() {
const { context, token } = await DA_SDK;
async function getValidFloodgate(sdk = DA_SDK) {
const { context, token } = await sdk;
const cmp = document.createElement('milo-floodgate');
cmp.repo = context.repo;
cmp.token = token;
Expand Down

0 comments on commit 347d163

Please sign in to comment.