Skip to content

Commit a4e185c

Browse files
authored
Merge pull request #106 from contentstack/enhc/DX-6002
DX - 6002: request publish details on taxonomy list export
2 parents 3a87a46 + de3413c commit a4e185c

2 files changed

Lines changed: 143 additions & 2 deletions

File tree

packages/contentstack-export/src/export/modules/taxonomies.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ export default class ExportTaxonomies extends BaseClass {
2222
private isLocaleBasedExportSupported: boolean = true; // Flag to track if locale-based export is supported
2323
private qs: {
2424
include_count: boolean;
25+
include_publish_details: boolean;
2526
skip: number;
2627
asc?: string;
2728
limit: number;
2829
locale?: string;
2930
branch?: string;
3031
include_fallback?: boolean;
3132
fallback_locale?: string;
33+
query?: Record<string, unknown>;
3234
};
3335
public taxonomiesFolderPath: string;
3436
private localesFilePath: string;
@@ -38,7 +40,12 @@ export default class ExportTaxonomies extends BaseClass {
3840
this.taxonomies = {};
3941
this.taxonomiesByLocale = {};
4042
this.taxonomiesConfig = exportConfig.modules.taxonomies;
41-
this.qs = { include_count: true, limit: this.taxonomiesConfig.limit || 100, skip: 0 };
43+
this.qs = {
44+
include_count: true,
45+
include_publish_details: true,
46+
limit: this.taxonomiesConfig.limit || 100,
47+
skip: 0,
48+
};
4249

4350
this.applyQueryFilters(this.qs, 'taxonomies');
4451
this.exportConfig.context.module = MODULE_CONTEXTS.TAXONOMIES;

packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@ describe('ExportTaxonomies', () => {
6666
taxonomies: {
6767
dirName: 'taxonomies',
6868
fileName: 'taxonomies.json',
69-
invalidKeys: [],
69+
invalidKeys: [
70+
'updated_at',
71+
'created_by',
72+
'updated_by',
73+
'stackHeaders',
74+
'urlPath',
75+
'created_at',
76+
],
7077
limit: 100,
7178
},
7279
locales: {
@@ -107,6 +114,118 @@ describe('ExportTaxonomies', () => {
107114
sinon.restore();
108115
});
109116

117+
describe('include_publish_details (list query)', () => {
118+
it('should set include_publish_details true on taxonomy list query params', () => {
119+
const qs = (exportTaxonomies as any).qs;
120+
expect(qs.include_publish_details).to.equal(true);
121+
expect(qs.include_count).to.equal(true);
122+
});
123+
124+
it('should pass include_publish_details true to taxonomy().query from fetchTaxonomies', async () => {
125+
const querySpy = sinon.stub().returns({
126+
find: sinon.stub().resolves({
127+
items: [{ uid: 'taxonomy-1', name: 'Cat' }],
128+
count: 1,
129+
}),
130+
});
131+
mockStackClient.taxonomy.returns({ query: querySpy });
132+
133+
await exportTaxonomies.fetchTaxonomies();
134+
135+
expect(querySpy.called).to.be.true;
136+
expect(querySpy.firstCall.args[0]).to.have.property('include_publish_details', true);
137+
});
138+
139+
it('should pass include_publish_details on every pagination request', async () => {
140+
let callCount = 0;
141+
const querySpy = sinon.stub().returns({
142+
find: sinon.stub().callsFake(() => {
143+
callCount++;
144+
if (callCount === 1) {
145+
return Promise.resolve({
146+
items: Array(100).fill(null).map((_, i) => ({ uid: `taxonomy-${i}`, name: 'Test' })),
147+
count: 150,
148+
});
149+
}
150+
return Promise.resolve({
151+
items: Array(50).fill(null).map((_, i) => ({ uid: `taxonomy-${100 + i}`, name: 'Test' })),
152+
count: 150,
153+
});
154+
}),
155+
});
156+
mockStackClient.taxonomy.returns({ query: querySpy });
157+
158+
await exportTaxonomies.fetchTaxonomies();
159+
160+
expect(callCount).to.be.greaterThan(1);
161+
querySpy.getCalls().forEach((call) => {
162+
expect(call.args[0]).to.have.property('include_publish_details', true);
163+
});
164+
});
165+
166+
it('should pass include_publish_details when fetching with locale code', async () => {
167+
const querySpy = sinon.stub().returns({
168+
find: sinon.stub().resolves({
169+
items: [{ uid: 'taxonomy-1', name: 'Cat', locale: 'en-us' }],
170+
count: 1,
171+
}),
172+
});
173+
mockStackClient.taxonomy.returns({ query: querySpy });
174+
175+
await exportTaxonomies.fetchTaxonomies('fr-fr');
176+
177+
expect(querySpy.called).to.be.true;
178+
expect(querySpy.firstCall.args[0]).to.include({
179+
include_publish_details: true,
180+
locale: 'fr-fr',
181+
});
182+
});
183+
184+
it('should include include_publish_details on initializeExport count query', async () => {
185+
const querySpy = sinon.stub().returns({
186+
find: sinon.stub().resolves({ items: [{ uid: 'taxonomy-1', name: 'Cat' }], count: 1 }),
187+
});
188+
mockStackClient.taxonomy.returns({ query: querySpy });
189+
190+
const stubDetermine = sinon.stub(exportTaxonomies as any, 'determineExportStrategy').resolves();
191+
const stubFetchAll = sinon.stub(exportTaxonomies as any, 'fetchAllTaxonomies').resolves();
192+
const stubExportAll = sinon.stub(exportTaxonomies as any, 'exportAllTaxonomies').resolves(1);
193+
const stubWriteMeta = sinon.stub(exportTaxonomies, 'writeTaxonomiesMetadata').resolves();
194+
const stubGetLocales = sinon.stub(exportTaxonomies, 'getLocalesToExport').returns(['en-us']);
195+
196+
await exportTaxonomies.start();
197+
198+
expect(querySpy.called).to.be.true;
199+
expect(querySpy.firstCall.args[0]).to.have.property('include_publish_details', true);
200+
expect(querySpy.firstCall.args[0]).to.have.property('limit', 1);
201+
202+
stubDetermine.restore();
203+
stubFetchAll.restore();
204+
stubExportAll.restore();
205+
stubWriteMeta.restore();
206+
stubGetLocales.restore();
207+
});
208+
209+
it('should merge exportConfig query.modules.taxonomies without removing root include_publish_details', () => {
210+
const cfg = {
211+
...mockExportConfig,
212+
query: {
213+
modules: {
214+
taxonomies: { branch: 'main' },
215+
},
216+
},
217+
} as any;
218+
const instance = new ExportTaxonomies({
219+
exportConfig: cfg,
220+
stackAPIClient: mockStackClient,
221+
moduleName: 'taxonomies',
222+
});
223+
const qs = (instance as any).qs;
224+
expect(qs.include_publish_details).to.equal(true);
225+
expect(qs.query).to.deep.equal({ branch: 'main' });
226+
});
227+
});
228+
110229
describe('Constructor', () => {
111230
it('should initialize with correct parameters', () => {
112231
expect(exportTaxonomies).to.be.instanceOf(ExportTaxonomies);
@@ -323,6 +442,21 @@ describe('ExportTaxonomies', () => {
323442
expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(0);
324443
});
325444

445+
it('should retain publish_details when not listed in invalidKeys', () => {
446+
const publishDetails = [{ environment: 'bltEnv1', time: '2026-04-21T12:00:00.000Z', user: 'bltUser1' }];
447+
const taxonomies = [
448+
{
449+
uid: 'taxonomy-pub',
450+
name: 'Pub',
451+
publish_details: publishDetails,
452+
},
453+
];
454+
455+
exportTaxonomies.sanitizeTaxonomiesAttribs(taxonomies);
456+
457+
expect(exportTaxonomies.taxonomies['taxonomy-pub'].publish_details).to.deep.equal(publishDetails);
458+
});
459+
326460
// const taxonomies = [
327461
// { uid: 'taxonomy-1', name: 'Category' },
328462
// { uid: 'taxonomy-2', name: 'Tag' }

0 commit comments

Comments
 (0)