Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MWPW-161575: Unit tests added for DA FB #3405

Merged
merged 3 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading