|
1 | 1 | import { expect } from 'chai'; |
2 | 2 | import sinon from 'sinon'; |
3 | | -import { log, FsUtility } from '@contentstack/cli-utilities'; |
| 3 | +import { FsUtility } from '@contentstack/cli-utilities'; |
4 | 4 | import ExportStack from '../../../../src/export/modules/stack'; |
5 | 5 | import ExportConfig from '../../../../src/types/export-config'; |
6 | 6 |
|
@@ -276,40 +276,166 @@ describe('ExportStack', () => { |
276 | 276 |
|
277 | 277 | expect(locale).to.exist; |
278 | 278 | expect(locale.code).to.equal('en-us'); |
| 279 | + expect(locale.name).to.equal('English (United States)'); |
| 280 | + }); |
| 281 | + |
| 282 | + it('should recursively search for master locale across multiple pages', async () => { |
| 283 | + let callCount = 0; |
| 284 | + const localeStub = { |
| 285 | + query: sinon.stub().returns({ |
| 286 | + find: sinon.stub().callsFake(() => { |
| 287 | + callCount++; |
| 288 | + if (callCount === 1) { |
| 289 | + // First batch without master locale |
| 290 | + return Promise.resolve({ |
| 291 | + items: new Array(100).fill({ uid: 'locale-test', code: 'en', fallback_locale: 'en-us' }), |
| 292 | + count: 150 |
| 293 | + }); |
| 294 | + } else { |
| 295 | + // Second batch with master locale |
| 296 | + return Promise.resolve({ |
| 297 | + items: [{ uid: 'locale-master', code: 'en-us', fallback_locale: null, name: 'English' }], |
| 298 | + count: 150 |
| 299 | + }); |
| 300 | + } |
| 301 | + }) |
| 302 | + }) |
| 303 | + }; |
| 304 | + |
| 305 | + mockStackClient.locale.returns(localeStub); |
| 306 | + const locale = await exportStack.getLocales(); |
| 307 | + |
| 308 | + expect(callCount).to.be.greaterThan(1); |
| 309 | + expect(locale.code).to.equal('en-us'); |
279 | 310 | }); |
280 | 311 |
|
281 | 312 | it('should handle error when fetching locales', async () => { |
282 | | - // Test error handling |
| 313 | + const localeStub = { |
| 314 | + query: sinon.stub().returns({ |
| 315 | + find: sinon.stub().rejects(new Error('API Error')) |
| 316 | + }) |
| 317 | + }; |
| 318 | + |
| 319 | + mockStackClient.locale.returns(localeStub); |
| 320 | + |
| 321 | + try { |
| 322 | + await exportStack.getLocales(); |
| 323 | + expect.fail('Should have thrown an error'); |
| 324 | + } catch (error) { |
| 325 | + expect(error).to.exist; |
| 326 | + } |
| 327 | + }); |
| 328 | + |
| 329 | + it('should handle no items response and skip searching', async () => { |
| 330 | + const localeStub = { |
| 331 | + query: sinon.stub().returns({ |
| 332 | + find: sinon.stub().resolves({ |
| 333 | + items: [], |
| 334 | + count: 0 |
| 335 | + }) |
| 336 | + }) |
| 337 | + }; |
| 338 | + |
| 339 | + mockStackClient.locale.returns(localeStub); |
283 | 340 | const locale = await exportStack.getLocales(); |
284 | 341 |
|
285 | | - expect(locale).to.exist; |
| 342 | + expect(locale).to.be.undefined; |
| 343 | + }); |
| 344 | + |
| 345 | + it('should find master locale in first batch when present', async () => { |
| 346 | + const localeStub = { |
| 347 | + query: sinon.stub().returns({ |
| 348 | + find: sinon.stub().resolves({ |
| 349 | + items: [ |
| 350 | + { uid: 'locale-1', code: 'es-es', fallback_locale: 'en-us' }, |
| 351 | + { uid: 'locale-master', code: 'en-us', fallback_locale: null, name: 'English' } |
| 352 | + ], |
| 353 | + count: 2 |
| 354 | + }) |
| 355 | + }) |
| 356 | + }; |
| 357 | + |
| 358 | + mockStackClient.locale.returns(localeStub); |
| 359 | + const locale = await exportStack.getLocales(); |
| 360 | + |
| 361 | + expect(locale.code).to.equal('en-us'); |
286 | 362 | }); |
287 | 363 | }); |
288 | 364 |
|
289 | 365 | describe('exportStack() method', () => { |
290 | | - it('should export stack successfully', async () => { |
| 366 | + it('should export stack successfully and write to file', async () => { |
| 367 | + const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; |
| 368 | + const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; |
| 369 | + |
291 | 370 | await exportStack.exportStack(); |
292 | 371 |
|
293 | | - // Should complete without error |
| 372 | + expect(writeFileStub.called).to.be.true; |
| 373 | + expect(makeDirectoryStub.called).to.be.true; |
294 | 374 | }); |
295 | 375 |
|
296 | | - it('should handle errors when exporting stack', async () => { |
297 | | - // Should handle error gracefully |
| 376 | + it('should handle errors when exporting stack without throwing', async () => { |
| 377 | + mockStackClient.fetch = sinon.stub().rejects(new Error('Stack fetch failed')); |
| 378 | + |
| 379 | + // Should complete without throwing despite error |
| 380 | + // The assertion is that await doesn't throw |
298 | 381 | await exportStack.exportStack(); |
299 | 382 | }); |
300 | 383 | }); |
301 | 384 |
|
302 | 385 | describe('exportStackSettings() method', () => { |
303 | | - it('should export stack settings successfully', async () => { |
| 386 | + it('should export stack settings successfully and write to file', async () => { |
| 387 | + const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; |
| 388 | + const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; |
| 389 | + |
304 | 390 | await exportStack.exportStackSettings(); |
305 | 391 |
|
306 | | - // Should complete without error |
| 392 | + expect(writeFileStub.called).to.be.true; |
| 393 | + expect(makeDirectoryStub.called).to.be.true; |
307 | 394 | }); |
308 | 395 |
|
309 | | - it('should handle errors when exporting settings', async () => { |
310 | | - // Should handle error gracefully |
| 396 | + it('should handle errors when exporting settings without throwing', async () => { |
| 397 | + mockStackClient.settings = sinon.stub().rejects(new Error('Settings fetch failed')); |
| 398 | + |
| 399 | + // Should complete without throwing despite error |
| 400 | + // The assertion is that await doesn't throw |
311 | 401 | await exportStack.exportStackSettings(); |
312 | 402 | }); |
313 | 403 | }); |
| 404 | + |
| 405 | + describe('start() method', () => { |
| 406 | + it('should export stack when preserveStackVersion is true', async () => { |
| 407 | + const exportStackStub = sinon.stub(exportStack, 'exportStack').resolves({ name: 'test-stack' }); |
| 408 | + const exportStackSettingsStub = sinon.stub(exportStack, 'exportStackSettings').resolves(); |
| 409 | + const getStackStub = sinon.stub(exportStack, 'getStack').resolves({}); |
| 410 | + |
| 411 | + exportStack.exportConfig.preserveStackVersion = true; |
| 412 | + |
| 413 | + await exportStack.start(); |
| 414 | + |
| 415 | + expect(exportStackStub.called).to.be.true; |
| 416 | + |
| 417 | + exportStackStub.restore(); |
| 418 | + exportStackSettingsStub.restore(); |
| 419 | + getStackStub.restore(); |
| 420 | + }); |
| 421 | + |
| 422 | + it('should skip exportStackSettings when management_token is present', async () => { |
| 423 | + const getStackStub = sinon.stub(exportStack, 'getStack').resolves({}); |
| 424 | + const exportStackSettingsSpy = sinon.spy(exportStack, 'exportStackSettings'); |
| 425 | + |
| 426 | + exportStack.exportConfig.management_token = 'some-token'; |
| 427 | + exportStack.exportConfig.preserveStackVersion = false; |
| 428 | + exportStack.exportConfig.master_locale = { code: 'en-us' }; |
| 429 | + exportStack.exportConfig.hasOwnProperty = sinon.stub().returns(true); |
| 430 | + |
| 431 | + await exportStack.start(); |
| 432 | + |
| 433 | + // Verify exportStackSettings was NOT called |
| 434 | + expect(exportStackSettingsSpy.called).to.be.false; |
| 435 | + |
| 436 | + getStackStub.restore(); |
| 437 | + exportStackSettingsSpy.restore(); |
| 438 | + }); |
| 439 | + }); |
314 | 440 | }); |
315 | 441 |
|
0 commit comments