Skip to content

Commit f8ac0d1

Browse files
committed
chore: fixed unit test cases
1 parent 8f53ebf commit f8ac0d1

13 files changed

Lines changed: 9886 additions & 10679 deletions

File tree

.github/workflows/unit-test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,7 @@ jobs:
8686
- name: Run tests for Contentstack Bulk Operations
8787
working-directory: ./packages/contentstack-bulk-operations
8888
run: npm test
89+
90+
- name: Run tests for Contentstack Variants
91+
working-directory: ./packages/contentstack-variants
92+
run: npm run test

.talismanrc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
fileignoreconfig:
22
- filename: pnpm-lock.yaml
3-
checksum: 2b0f2461ea1bb240a9210b9cf99dc403a756199712b7270f9792a590480451bd
3+
checksum: 6af0841bbfd8d541cfd748941ffcfa5d040fcd3708e49dc8c23eae69685b3b05
4+
- filename: packages/contentstack-variants/test/unit/import/experiences.test.ts
5+
checksum: 6142418bafea6454a72b313d933deb494ce4ea1d8cead7ef918c10e283c2c603
6+
- filename: packages/contentstack-variants/test/unit/export/variant-entries.test.ts
7+
checksum: e150faeefa7b3586b70a6f454c1f68efe05526f582977dba28243b1e47606a42
8+
- filename: packages/contentstack-variants/test/unit/export/experiences.test.ts
9+
checksum: eb9c989dd14373a90e8866ba3350245d3c06e8ba43cfebb24f40c1106b2e6b95
10+
- filename: packages/contentstack-variants/test/unit/utils/personalization-api-adapter.test.ts
11+
checksum: d729c9586d3a19e321d79e490790b9d0aa345f81917376199d962de68317fae1
12+
- filename: packages/contentstack-variants/test/unit/import/variant-entries.test.ts
13+
checksum: bdcd7df1ee9a835ea0fecde7731184097cc397100e58df22b5e6381f6a67e62a
414
version: '1.0'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const path = require('path');
2+
3+
process.env.TS_NODE_PROJECT = path.resolve('tsconfig.json');
4+
process.env.TS_NODE_TRANSPILE_ONLY = 'true';
5+
process.env.NODE_ENV = 'test';
6+
7+
global.oclif = global.oclif || {};
8+
global.oclif.columns = 80;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { expect } from 'chai';
2+
import { ExportExperiences, ExportConfig } from '../../../src';
3+
4+
const makeExportConfig = (branchName?: string): ExportConfig =>
5+
({
6+
modules: {
7+
personalize: {
8+
baseURL: { na: 'https://personalize.na-api.contentstack.com' },
9+
dirName: 'personalize',
10+
},
11+
},
12+
region: { name: 'na', cma: 'https://api.contentstack.io' },
13+
project_id: 'TEST-PROJECT-001',
14+
apiKey: 'TEST-STACK-API-KEY',
15+
exportDir: '/tmp/test-export',
16+
context: {},
17+
...(branchName ? { branchName } : {}),
18+
} as unknown as ExportConfig);
19+
20+
describe('ExportExperiences — branch header', () => {
21+
describe('constructor (cmaConfig headers)', () => {
22+
it('includes branch header in cmaConfig.headers when branchName is set', () => {
23+
const instance = new ExportExperiences(makeExportConfig('feature-branch'));
24+
expect((instance as any).adapterConfig.cmaConfig.headers.branch).to.equal('feature-branch');
25+
});
26+
27+
it('does NOT include branch header in cmaConfig.headers when branchName is absent', () => {
28+
const instance = new ExportExperiences(makeExportConfig());
29+
expect((instance as any).adapterConfig.cmaConfig.headers.branch).to.be.undefined;
30+
});
31+
32+
it('always includes api_key in cmaConfig.headers regardless of branchName', () => {
33+
const instance = new ExportExperiences(makeExportConfig('staging'));
34+
expect((instance as any).adapterConfig.cmaConfig.headers.api_key).to.equal('TEST-STACK-API-KEY');
35+
});
36+
37+
it('sets correct cmaConfig baseURL from region', () => {
38+
const instance = new ExportExperiences(makeExportConfig('dev'));
39+
expect((instance as any).adapterConfig.cmaConfig.baseURL).to.equal('https://api.contentstack.io/v3');
40+
});
41+
42+
it('branch header value matches branchName exactly', () => {
43+
const instance = new ExportExperiences(makeExportConfig('eu-branch-2025'));
44+
expect((instance as any).adapterConfig.cmaConfig.headers.branch).to.equal('eu-branch-2025');
45+
});
46+
47+
it('cmaConfig.headers has only api_key when branchName is not set', () => {
48+
const instance = new ExportExperiences(makeExportConfig());
49+
const headers = (instance as any).adapterConfig.cmaConfig.headers;
50+
expect(Object.keys(headers)).to.deep.equal(['api_key']);
51+
});
52+
53+
it('cmaConfig.headers has api_key and branch when branchName is set', () => {
54+
const instance = new ExportExperiences(makeExportConfig('main'));
55+
const headers = (instance as any).adapterConfig.cmaConfig.headers;
56+
expect(headers).to.deep.equal({ api_key: 'TEST-STACK-API-KEY', branch: 'main' });
57+
});
58+
});
59+
});
Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { expect } from '@oclif/test';
1+
import sinon from 'sinon';
2+
import { expect } from 'chai';
23
import { FsUtility } from '@contentstack/cli-utilities';
3-
import { fancy } from '@contentstack/cli-dev-dependencies';
44

55
import exportConf from '../mock/export-config.json';
66
import { Export, ExportConfig, VariantHttpClient, VariantsOption } from '../../../src';
@@ -14,80 +14,96 @@ describe('Variant Entries Export', () => {
1414
entries: [{ uid: 'E-UID-1', title: 'Entry 1' }],
1515
};
1616

17-
const test = fancy
18-
.stdout({ print: process.env.PRINT === 'true' || false })
19-
.stub(FsUtility.prototype, 'completeFile', () => {})
20-
.stub(FsUtility.prototype, 'writeIntoFile', () => {})
21-
.stub(FsUtility.prototype, 'createFolderIfNotExist', () => {});
22-
2317
beforeEach(() => {
2418
config = exportConf as unknown as ExportConfig;
2519
});
2620

21+
afterEach(() => sinon.restore());
22+
2723
describe('path construction', () => {
28-
test.it('should use exportDir as base path (no branch segment in path)', () => {
29-
const configWithExportDir = {
30-
...config,
31-
exportDir: '/base/export',
32-
branchName: 'dev',
33-
} as ExportConfig;
34-
const instance = new Export.VariantEntries(configWithExportDir);
24+
it('should use exportDir as base path (no branch segment in path)', () => {
25+
const instance = new Export.VariantEntries({
26+
...config, exportDir: '/base/export', branchName: 'dev',
27+
} as ExportConfig);
3528
expect(instance.entriesDirPath).to.not.include('dev');
3629
expect(instance.entriesDirPath).to.include('entries');
3730
});
3831
});
3932

33+
describe('branch header', () => {
34+
const getHeaders = (instance: any) => instance.variantInstance.adapterConfig.headers;
35+
36+
it('sets branch header in adapter headers when branchName is configured', () => {
37+
const instance = new Export.VariantEntries({
38+
...config, apiKey: 'TEST-KEY', branchName: 'feature-branch', org_uid: 'TEST-ORG', project_id: 'TEST-PROJECT',
39+
} as ExportConfig);
40+
expect(getHeaders(instance).branch).to.equal('feature-branch');
41+
});
42+
43+
it('branch header is undefined when branchName is not set', () => {
44+
const instance = new Export.VariantEntries({
45+
...config, apiKey: 'TEST-KEY', org_uid: 'TEST-ORG', project_id: 'TEST-PROJECT',
46+
} as ExportConfig);
47+
expect(getHeaders(instance).branch).to.be.undefined;
48+
});
49+
50+
it('always sets api_key in adapter headers', () => {
51+
const instance = new Export.VariantEntries({
52+
...config, apiKey: 'TEST-STACK-API-KEY', branchName: 'staging', org_uid: 'TEST-ORG', project_id: 'TEST-PROJECT',
53+
} as ExportConfig);
54+
expect(getHeaders(instance).api_key).to.equal('TEST-STACK-API-KEY');
55+
});
56+
57+
it('branch header value matches branchName exactly', () => {
58+
const instance = new Export.VariantEntries({
59+
...config, apiKey: 'TEST-KEY', branchName: 'eu-release-2025', org_uid: 'TEST-ORG', project_id: 'TEST-PROJECT',
60+
} as ExportConfig);
61+
expect(getHeaders(instance).branch).to.equal('eu-release-2025');
62+
});
63+
});
64+
4065
describe('exportVariantEntry method', () => {
41-
test
42-
.stub(VariantHttpClient.prototype, 'variantEntries', async () => {})
43-
.spy(VariantHttpClient.prototype, 'variantEntries')
44-
.spy(FsUtility.prototype, 'completeFile')
45-
.spy(FsUtility.prototype, 'createFolderIfNotExist')
46-
.it('should call export variant entry method (API call)', async ({ spy }) => {
47-
let entryVariantInstace = new Export.VariantEntries(config);
48-
await entryVariantInstace.exportVariantEntry(exportEntryData);
49-
50-
expect(spy.variantEntries.callCount).to.be.equals(1);
51-
expect(spy.completeFile.callCount).to.be.equals(1);
52-
expect(spy.createFolderIfNotExist.callCount).to.be.equals(1);
53-
expect(spy.completeFile.alwaysCalledWith(true)).to.be.true;
66+
beforeEach(() => {
67+
sinon.stub(VariantHttpClient.prototype, 'init').resolves();
68+
});
69+
70+
it('should call variantEntries once per entry', async () => {
71+
const variantEntriesStub = sinon.stub(VariantHttpClient.prototype, 'variantEntries' as any).resolves();
72+
sinon.stub(FsUtility.prototype, 'completeFile' as any);
73+
sinon.stub(FsUtility.prototype, 'writeIntoFile' as any);
74+
75+
const instance = new Export.VariantEntries(config);
76+
await instance.exportVariantEntry(exportEntryData);
77+
78+
expect(variantEntriesStub.callCount).to.equal(1);
79+
expect(variantEntriesStub.firstCall.args[0]).to.include({ entry_uid: 'E-UID-1', locale: 'en-us' });
80+
});
81+
82+
it('should write data in files when callback is invoked with entries', async () => {
83+
sinon.stub(VariantHttpClient.prototype, 'variantEntries' as any).callsFake(async (opts: VariantsOption) => {
84+
if (opts.callback) opts.callback([{ uid: 'E-UID-1', title: 'Entry 1' }]);
5485
});
86+
const writeIntoFileStub = sinon.stub(FsUtility.prototype, 'writeIntoFile' as any);
5587

56-
test
57-
.stub(VariantHttpClient.prototype, 'variantEntries', async (...args: any) => {
58-
const { callback } = args[0] as VariantsOption;
59-
if (callback) {
60-
callback([{ uid: 'E-UID-1', title: 'Entry 1' }]);
61-
}
62-
})
63-
.spy(FsUtility.prototype, 'writeIntoFile')
64-
.it('should write data in files (As chunk)', async ({ spy }) => {
65-
let entryVariantInstace = new Export.VariantEntries(config);
66-
await entryVariantInstace.exportVariantEntry(exportEntryData);
67-
68-
expect(spy.writeIntoFile.callCount).to.be.equals(1);
69-
expect(spy.writeIntoFile.alwaysCalledWith([{ uid: 'E-UID-1', title: 'Entry 1' }])).to.be.true;
88+
const instance = new Export.VariantEntries(config);
89+
await instance.exportVariantEntry(exportEntryData);
90+
91+
expect(writeIntoFileStub.callCount).to.equal(1);
92+
expect(writeIntoFileStub.alwaysCalledWith([{ uid: 'E-UID-1', title: 'Entry 1' }])).to.be.true;
93+
});
94+
95+
it('should skip write when callback returns empty array; default chunk size to 1MB', async () => {
96+
const variantEntriesStub = sinon.stub(VariantHttpClient.prototype, 'variantEntries' as any).callsFake(async (opts: VariantsOption) => {
97+
if (opts.callback) opts.callback([]);
7098
});
99+
const writeIntoFileStub = sinon.stub(FsUtility.prototype, 'writeIntoFile' as any);
71100

72-
test
73-
.stub(VariantHttpClient.prototype, 'variantEntries', async (...args: any) => {
74-
const { callback } = args[0] as VariantsOption;
75-
if (callback) {
76-
callback([]); // NOTE API callback with empty response
77-
}
78-
})
79-
.spy(FsUtility.prototype, 'writeIntoFile')
80-
.spy(VariantHttpClient.prototype, 'variantEntries')
81-
.it(
82-
'should skip write data in files (Empty data check validation), should set default file chunk 1MB if chunk size is not passed in config',
83-
async ({ spy }) => {
84-
config.modules.variantEntry.chunkFileSize = null as any;
85-
let entryVariantInstace = new Export.VariantEntries(config, () => {});
86-
await entryVariantInstace.exportVariantEntry(exportEntryData);
87-
88-
expect(spy.writeIntoFile.callCount).to.be.equals(0);
89-
expect(spy.variantEntries.callCount).to.be.equals(1);
90-
},
91-
);
101+
config.modules.variantEntry.chunkFileSize = null as any;
102+
const instance = new Export.VariantEntries(config, () => {});
103+
await instance.exportVariantEntry(exportEntryData);
104+
105+
expect(writeIntoFileStub.callCount).to.equal(0);
106+
expect(variantEntriesStub.callCount).to.equal(1);
107+
});
92108
});
93109
});

0 commit comments

Comments
 (0)