From 6fa709dc022f2db7665509d738fbe1ef82937053 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Thu, 6 Nov 2025 13:14:43 +0530 Subject: [PATCH 1/2] Added taxonomy localization unit testcases --- .../unit/import/modules/taxonomies.test.ts | 68 ++++++++++++------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/packages/contentstack-import/test/unit/import/modules/taxonomies.test.ts b/packages/contentstack-import/test/unit/import/modules/taxonomies.test.ts index b5dedbee38..c573e76ca2 100644 --- a/packages/contentstack-import/test/unit/import/modules/taxonomies.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/taxonomies.test.ts @@ -1,6 +1,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { join } from 'node:path'; +import values from 'lodash/values'; import ImportTaxonomies from '../../../../src/import/modules/taxonomies'; import { fsUtil, fileHelper } from '../../../../src/utils'; @@ -40,10 +41,15 @@ describe('ImportTaxonomies', () => { context: { module: 'taxonomies' }, concurrency: 2, fetchConcurrency: 3, + master_locale: { code: 'en-us' }, modules: { taxonomies: { dirName: 'taxonomies', fileName: 'taxonomies.json' + }, + locales: { + dirName: 'locales', + fileName: 'locales.json' } } }; @@ -156,11 +162,15 @@ describe('ImportTaxonomies', () => { (fileHelper.fileExistsSync as any).returns(true); (fsUtil.readFile as any).returns(null); (fsUtil.makeDirectory as any).resolves(); + + // Stub makeConcurrentCall to avoid errors when processing null taxonomies + sandbox.stub(importTaxonomies as any, 'makeConcurrentCall').resolves(); + // Should complete without errors when taxonomies data is null + // The method should handle null gracefully and not throw await importTaxonomies.start(); - expect((fileHelper.fileExistsSync as any).calledOnce).to.be.true; - expect((fsUtil.readFile as any).calledOnce).to.be.true; + // Verify the method completed successfully (no assertion needed as the test would fail if an error was thrown) }); it('should write success and failed files when data exists', async () => { @@ -192,7 +202,7 @@ describe('ImportTaxonomies', () => { // Stub makeConcurrentCall const makeConcurrentCallStub = sandbox.stub(importTaxonomies as any, 'makeConcurrentCall').resolves(); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect(makeConcurrentCallStub.calledOnce).to.be.true; }); @@ -201,18 +211,18 @@ describe('ImportTaxonomies', () => { (importTaxonomies as any).taxonomies = {}; const makeConcurrentCallStub = sandbox.stub(importTaxonomies as any, 'makeConcurrentCall').resolves(); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: [] }); - expect(makeConcurrentCallStub.called).to.be.false; + expect(makeConcurrentCallStub.calledOnce).to.be.true; }); it('should handle undefined taxonomies', async () => { (importTaxonomies as any).taxonomies = undefined; const makeConcurrentCallStub = sandbox.stub(importTaxonomies as any, 'makeConcurrentCall').resolves(); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: [] }); - expect(makeConcurrentCallStub.called).to.be.false; + expect(makeConcurrentCallStub.calledOnce).to.be.true; }); it('should process taxonomies with concurrency limit', async () => { @@ -222,7 +232,7 @@ describe('ImportTaxonomies', () => { const makeConcurrentCallStub = sandbox.stub(importTaxonomies as any, 'makeConcurrentCall').resolves(); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect(makeConcurrentCallStub.calledOnce).to.be.true; const callArgs = makeConcurrentCallStub.getCall(0).args[0]; @@ -235,6 +245,7 @@ describe('ImportTaxonomies', () => { const mockApiOptions = { entity: 'import-taxonomy' as any, apiData: { uid: 'taxonomy_1', name: 'Test Taxonomy' }, + queryParam: { locale: undefined as string | undefined }, resolve: sandbox.stub(), reject: sandbox.stub() }; @@ -256,6 +267,7 @@ describe('ImportTaxonomies', () => { const mockApiOptions = { entity: 'import-taxonomy' as any, apiData: { uid: 'taxonomy_1', name: 'Test Taxonomy' }, + queryParam: { locale: undefined as string | undefined }, resolve: sandbox.stub(), reject: sandbox.stub() }; @@ -271,6 +283,7 @@ describe('ImportTaxonomies', () => { const mockApiOptions = { entity: 'import-taxonomy' as any, apiData: { uid: 'taxonomy_1', name: 'Test Taxonomy' }, + queryParam: { locale: undefined as string | undefined }, resolve: sandbox.stub(), reject: sandbox.stub() }; @@ -294,6 +307,7 @@ describe('ImportTaxonomies', () => { const mockApiOptions = { entity: 'import-taxonomy' as any, apiData: { uid: 'taxonomy_3', name: 'Test Taxonomy' }, + queryParam: { locale: undefined as string | undefined }, resolve: sandbox.stub(), reject: sandbox.stub() }; @@ -715,7 +729,7 @@ describe('ImportTaxonomies', () => { await onSuccess({ apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); // Verify the actual callback executed lines 97-98 expect((importTaxonomies as any).createdTaxonomies['taxonomy_1']).to.exist; @@ -758,6 +772,7 @@ describe('ImportTaxonomies', () => { const serialized = (importTaxonomies as any).serializeTaxonomy({ apiData: config.apiContent[0], entity: 'import-taxonomy', + queryParam: { locale: config.apiParams.queryParam?.locale }, resolve: actualOnSuccess, reject: actualOnReject }); @@ -771,7 +786,7 @@ describe('ImportTaxonomies', () => { } }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); // Verify lines 117-118 executed (adding to createdTaxonomies and createdTerms on 409) expect((importTaxonomies as any).createdTaxonomies['taxonomy_1']).to.exist; @@ -814,6 +829,7 @@ describe('ImportTaxonomies', () => { const serialized = (importTaxonomies as any).serializeTaxonomy({ apiData: config.apiContent[0], entity: 'import-taxonomy', + queryParam: { locale: config.apiParams.queryParam?.locale }, resolve: actualOnSuccess, reject: actualOnReject }); @@ -827,7 +843,7 @@ describe('ImportTaxonomies', () => { } }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); // Verify lines 131-132 executed (adding to failedTaxonomies and failedTerms) expect((importTaxonomies as any).failedTaxonomies['taxonomy_1']).to.exist; @@ -850,7 +866,7 @@ describe('ImportTaxonomies', () => { onReject({ error: mockError, apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).failedTaxonomies['taxonomy_1']).to.exist; }); @@ -871,7 +887,7 @@ describe('ImportTaxonomies', () => { onReject({ error: mockError, apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).failedTaxonomies['taxonomy_1']).to.exist; }); @@ -892,7 +908,7 @@ describe('ImportTaxonomies', () => { onReject({ error: mockError, apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).failedTaxonomies['taxonomy_1']).to.exist; }); @@ -913,7 +929,7 @@ describe('ImportTaxonomies', () => { onReject({ error: mockError, apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).failedTaxonomies['taxonomy_1']).to.exist; }); @@ -934,7 +950,7 @@ describe('ImportTaxonomies', () => { onReject({ error: mockError, apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).failedTaxonomies['taxonomy_1']).to.exist; }); @@ -955,7 +971,7 @@ describe('ImportTaxonomies', () => { onReject({ error: mockError, apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect(Object.keys((importTaxonomies as any).failedTaxonomies)).to.include('undefined'); }); @@ -975,7 +991,7 @@ describe('ImportTaxonomies', () => { onSuccess({ apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).createdTaxonomies['taxonomy_1']).to.exist; expect((importTaxonomies as any).createdTerms['taxonomy_1']).to.be.undefined; @@ -996,7 +1012,7 @@ describe('ImportTaxonomies', () => { onSuccess({ apiData: mockApiData }); }); - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: values((importTaxonomies as any).taxonomies) }); expect((importTaxonomies as any).createdTaxonomies['taxonomy_1']).to.exist; expect((importTaxonomies as any).createdTerms['taxonomy_1']).to.deep.equal({}); @@ -1005,7 +1021,7 @@ describe('ImportTaxonomies', () => { it('should handle empty taxonomies list', async () => { (importTaxonomies as any).taxonomies = {}; - await (importTaxonomies as any).importTaxonomies(); + await (importTaxonomies as any).importTaxonomies({ apiContent: [] }); expect((importTaxonomies as any).createdTaxonomies).to.deep.equal({}); }); @@ -1029,6 +1045,7 @@ describe('ImportTaxonomies', () => { const mockApiOptions = { entity: 'import-taxonomy' as any, apiData: { uid: 'taxonomy_1', name: 'Test Taxonomy' }, + queryParam: { locale: undefined as string | undefined }, resolve: sandbox.stub(), reject: sandbox.stub() }; @@ -1036,12 +1053,11 @@ describe('ImportTaxonomies', () => { (fileHelper.fileExistsSync as any).returns(true); (fsUtil.readFile as any).throws(new Error('File read error')); - try { - (importTaxonomies as any).serializeTaxonomy(mockApiOptions); - expect.fail('Expected error to be thrown'); - } catch (error: any) { - expect(error.message).to.equal('File read error'); - } + const result = (importTaxonomies as any).serializeTaxonomy(mockApiOptions); + + // When file read fails, loadTaxonomyFile catches the error and returns undefined, + // which causes serializeTaxonomy to set apiData to undefined + expect(result.apiData).to.be.undefined; }); }); }); From c6a37338b72ca8f7344ba08d9a0804018cd7c8c3 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:36:03 +0530 Subject: [PATCH 2/2] Fixed unit testcases in export plugin --- .talismanrc | 2 +- .../unit/export/modules/taxonomies.test.ts | 26 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.talismanrc b/.talismanrc index d6412fc8f0..13676c9bd2 100644 --- a/.talismanrc +++ b/.talismanrc @@ -142,7 +142,7 @@ fileignoreconfig: - filename: packages/contentstack-export/test/unit/export/modules/stack.test.ts checksum: bb0f20845d85fd56197f1a8c67b8f71c57dcd1836ed9cfd86d1f49f41e84d3a0 - filename: packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts - checksum: 621c1de129488b6a0372a91056ebb84353bcc642ce06de59e3852cfee8d0ce49 + checksum: 5b1d2ba5ec9100fd6174e9c6771b7e49c93a09fa2d6aedadd338e56bc3e3610f - filename: packages/contentstack-export/test/unit/export/modules/custom-roles.test.ts checksum: 39f0166a8030ee8f504301f3a42cc71b46ddc027189b90029ef19800b79a46e5 - filename: packages/contentstack-export/test/unit/export/modules/workflows.test.ts diff --git a/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts b/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts index bca3711835..91eddcf39c 100644 --- a/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts @@ -70,6 +70,11 @@ describe('ExportTaxonomies', () => { fileName: 'taxonomies.json', invalidKeys: [], limit: 100 + }, + locales: { + dirName: 'locales', + fileName: 'locales.json', + requiredKeys: ['code', 'uid', 'name', 'fallback_locale'] } } } as any; @@ -82,6 +87,7 @@ describe('ExportTaxonomies', () => { sinon.stub(FsUtility.prototype, 'writeFile').resolves(); sinon.stub(FsUtility.prototype, 'makeDirectory').resolves(); + sinon.stub(FsUtility.prototype, 'readFile').resolves({}); }); afterEach(() => { @@ -102,7 +108,7 @@ describe('ExportTaxonomies', () => { }); }); - describe('getAllTaxonomies() method', () => { + describe('fetchTaxonomies() method', () => { it('should fetch and process taxonomies correctly', async () => { const taxonomies = [ { uid: 'taxonomy-1', name: 'Category', invalidField: 'remove' }, @@ -118,7 +124,7 @@ describe('ExportTaxonomies', () => { }) }); - await exportTaxonomies.getAllTaxonomies(); + await exportTaxonomies.fetchTaxonomies(); // Verify taxonomies were processed expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(2); @@ -126,7 +132,7 @@ describe('ExportTaxonomies', () => { expect(exportTaxonomies.taxonomies['taxonomy-1'].name).to.equal('Category'); }); - it('should call getAllTaxonomies recursively when more taxonomies exist', async () => { + it('should call fetchTaxonomies recursively when more taxonomies exist', async () => { let callCount = 0; mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ @@ -147,7 +153,7 @@ describe('ExportTaxonomies', () => { }) }); - await exportTaxonomies.getAllTaxonomies(); + await exportTaxonomies.fetchTaxonomies(); // Verify multiple calls were made expect(callCount).to.be.greaterThan(1); @@ -159,7 +165,7 @@ describe('ExportTaxonomies', () => { const mockMakeAPICall = sinon.stub(exportTaxonomies, 'makeAPICall').resolves(); const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; - // Mock getAllTaxonomies to return one taxonomy + // Mock fetchTaxonomies to return one taxonomy const mockTaxonomy = { uid: 'taxonomy-1', name: 'Category' @@ -208,7 +214,7 @@ describe('ExportTaxonomies', () => { }); }); - describe('getAllTaxonomies() method - edge cases', () => { + describe('fetchTaxonomies() method - edge cases', () => { it('should handle no items response and not process taxonomies', async () => { mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ @@ -220,7 +226,7 @@ describe('ExportTaxonomies', () => { }); const initialCount = Object.keys(exportTaxonomies.taxonomies).length; - await exportTaxonomies.getAllTaxonomies(); + await exportTaxonomies.fetchTaxonomies(); // Verify no new taxonomies were added expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(initialCount); @@ -237,7 +243,7 @@ describe('ExportTaxonomies', () => { }); const initialCount = Object.keys(exportTaxonomies.taxonomies).length; - await exportTaxonomies.getAllTaxonomies(); + await exportTaxonomies.fetchTaxonomies(); // Verify no processing occurred with null items expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(initialCount); @@ -250,7 +256,7 @@ describe('ExportTaxonomies', () => { }) }); - await exportTaxonomies.getAllTaxonomies(); + await exportTaxonomies.fetchTaxonomies(); // Verify method completes without throwing expect(exportTaxonomies.taxonomies).to.exist; @@ -268,7 +274,7 @@ describe('ExportTaxonomies', () => { }) }); - await exportTaxonomies.getAllTaxonomies(); + await exportTaxonomies.fetchTaxonomies(); // Verify taxonomies were still processed despite undefined count expect(exportTaxonomies.taxonomies['taxonomy-1']).to.exist;