Skip to content
13 changes: 11 additions & 2 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,14 @@ fileignoreconfig:
- filename: src/adapters/github.test.ts
checksum: b3d3d3a3c14adde103152d2ac4e1c4b7121a5f7533a87c3cc600f6d25fb59d1b
- filename: src/adapters/file-upload.test.ts
checksum: 962fd8b45578914926d20857ddc3d1bc2fa19e8b192c6dfdc03d214ae1898b59
version: "1.0"
allowed_patterns:
- "--(disable|enable)-cs-auth is passed"
Comment thread
dhruv-parekh-cs marked this conversation as resolved.
- filename: src/adapters/file-upload.ts
allowed_patterns:
- "const \\{ formFieldKey, formFieldValue \\} of fields"
- "formData\\.append\\(formFieldKey, formFieldValue\\)"
- "headers: \\{ key: string; value: string \\}\\[\\]"
- "headers\\?\\.reduce\\(\\(acc, \\{ key, value \\}\\)"
Comment thread
dhruv-parekh-cs marked this conversation as resolved.
- "\\(\\{ key, value \\}\\) => \\(\\{ key, value \\}\\)\\)"
- "const \\{ token, apiKey \\} = configHandler\\.get"
version: "1.0"
23 changes: 8 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@rollup/plugin-typescript": "^12.1.2",
"@types/express": "^4.17.21",
"@types/express-serve-static-core": "^4.17.34",
"adm-zip": "^0.5.18",
"adm-zip": "^0.6.0",
"chalk": "^4.1.2",
"cross-fetch": "^4.1.0",
"dotenv": "^16.4.7",
Expand All @@ -46,7 +46,6 @@
},
"devDependencies": {
"@oclif/test": "^4.1.3",
"@types/adm-zip": "^0.5.7",
"@types/chai": "^4.3.20",
"@types/ini": "^1.3.34",
"@types/jest": "^29.5.14",
Expand Down Expand Up @@ -115,7 +114,7 @@
"@eslint/eslintrc": {
"ajv": "^6.12.6"
},
"qs": "^6.15.2",
"qs": "^6.16.0",
"tmp": "^0.2.4",
"fast-uri": "^3.1.6",
"js-yaml": "^4.3.1",
Expand Down
62 changes: 62 additions & 0 deletions src/adapters/file-upload.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import AdmZip from 'adm-zip';
import { fileUploadAdapter as cliUtilitiesJestMock } from '../test/mocks/cli-utilities';
import FileUpload from './file-upload';
import BaseClass from './base-class';
import { cliux } from '@contentstack/cli-utilities';
import { DeploymentStatus } from '../types/launch';
import { getFileList } from '../util/fs';

jest.mock('@contentstack/cli-utilities', () => cliUtilitiesJestMock);
jest.mock('../util/fs', () => ({ getFileList: jest.fn() }));

// adm-zip defines its methods as own properties on each instance, not on the prototype,
// so the constructor is mocked rather than spied on. esModuleInterop resolves the source's
// default import to `.default`, hence the __esModule shape.
const writeZipPromiseMock = jest.fn();
jest.mock('adm-zip', () => ({
__esModule: true,
default: jest.fn().mockImplementation(() => ({
addLocalFile: jest.fn(),
addLocalFolder: jest.fn(),
writeZipPromise: writeZipPromiseMock,
})),
}));

describe('FileUpload Adapter', () => {
let logMock: jest.Mock;
Expand Down Expand Up @@ -827,5 +843,51 @@ describe('FileUpload Adapter', () => {
handleEnvImportFlowMock.mockRestore();
});
});

describe('archive', () => {
const createInstance = () =>
new FileUpload({
config: {
projectBasePath: '/tmp/launch-project',
Comment thread
dhruv-parekh-cs marked this conversation as resolved.
fileUploadConfig: { exclude: [] },
},
log: logMock,
exit: exitMock,
} as any);

beforeEach(() => {
(getFileList as jest.Mock).mockResolvedValue([]);
// the suite-wide afterEach calls jest.resetAllMocks(), which strips the
// constructor implementation registered in the jest.mock factory above.
(AdmZip as unknown as jest.Mock).mockImplementation(() => ({
addLocalFile: jest.fn(),
addLocalFolder: jest.fn(),
writeZipPromise: writeZipPromiseMock,
}));
});

it('should log the failure once and exit when zipping rejects', async () => {
writeZipPromiseMock.mockRejectedValue(new Error('disk full'));
const fileUploadInstance = createInstance();

await expect(fileUploadInstance.archive()).rejects.toThrow('1');

expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock).toHaveBeenCalledWith('Zipping project process failed! Please try again.');
expect(exitMock).toHaveBeenCalledWith(1);
});

it('should return the zip details and not exit when zipping resolves', async () => {
writeZipPromiseMock.mockResolvedValue(undefined);
const fileUploadInstance = createInstance();

const result = await fileUploadInstance.archive();

expect(result.projectName).toBe('launch-project');
expect(result.zipName).toMatch(/^\d+_launch-project\.zip$/);
expect(exitMock).not.toHaveBeenCalled();
expect(logMock).not.toHaveBeenCalled();
});
});
});

9 changes: 3 additions & 6 deletions src/adapters/file-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,9 @@ export default class FileUpload extends BaseClass {
}
}

const status = await zip.writeZipPromise(zipPath).catch(() => {
this.log('Zipping project process failed! Please try again.');
this.exit(1);
});

if (!status) {
try {
await zip.writeZipPromise(zipPath);
} catch {
this.log('Zipping project process failed! Please try again.');
this.exit(1);
}
Expand Down
Loading