@messagevisor/catalog 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/index-Cx9rnVIG.js +73 -0
- package/dist/index.html +1 -1
- package/lib/node/index.d.ts +3 -0
- package/lib/node/index.js +573 -311
- package/lib/node/index.js.map +1 -1
- package/package.json +2 -2
- package/src/api.spec.ts +46 -1
- package/src/api.ts +29 -1
- package/src/node/index.spec.ts +369 -50
- package/src/node/index.ts +443 -66
- package/src/pages/EntityDetailPage.tsx +15 -4
- package/src/types.ts +1 -0
- package/dist/assets/index-BJS9aW0t.js +0 -73
package/src/node/index.spec.ts
CHANGED
|
@@ -46,6 +46,25 @@ async function pathExists(root: string, relativePath: string) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
function stripAnsi(value: string) {
|
|
50
|
+
return value.replace(/\x1b\[[0-9;]*m/g, "").replace(/%s/g, "");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function captureConsoleLog(callback: () => Promise<void>) {
|
|
54
|
+
const logs: string[] = [];
|
|
55
|
+
const spy = jest.spyOn(console, "log").mockImplementation((...args: unknown[]) => {
|
|
56
|
+
logs.push(args.map(String).join(" "));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
await callback();
|
|
61
|
+
} finally {
|
|
62
|
+
spy.mockRestore();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return stripAnsi(logs.join("\n"));
|
|
66
|
+
}
|
|
67
|
+
|
|
49
68
|
async function createProject() {
|
|
50
69
|
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), "messagevisor-catalog-"));
|
|
51
70
|
const interpolationModulePath = path.join(
|
|
@@ -230,14 +249,6 @@ describe("catalog", function () {
|
|
|
230
249
|
const manifest = await readJson<any>(root, "catalog-out/data/manifest.json");
|
|
231
250
|
const index = await readJson<any>(root, "catalog-out/data/root/index.json");
|
|
232
251
|
const locale = await readJson<any>(root, "catalog-out/data/root/entities/locale/en-US.json");
|
|
233
|
-
const localeDuplicates = await readJson<any>(
|
|
234
|
-
root,
|
|
235
|
-
"catalog-out/data/root/duplicates/locales/en-US.json",
|
|
236
|
-
);
|
|
237
|
-
const emptyLocaleDuplicates = await readJson<any>(
|
|
238
|
-
root,
|
|
239
|
-
"catalog-out/data/root/duplicates/locales/nl.json",
|
|
240
|
-
);
|
|
241
252
|
const message = await readJson<any>(
|
|
242
253
|
root,
|
|
243
254
|
"catalog-out/data/root/entities/message/common.welcome.json",
|
|
@@ -253,11 +264,20 @@ describe("catalog", function () {
|
|
|
253
264
|
expect(manifest.sets).toBe(false);
|
|
254
265
|
expect(manifest.router).toBe("browser");
|
|
255
266
|
expect(manifest.dev).toBeUndefined();
|
|
256
|
-
expect(manifest.features).toEqual({ translationSearch: false });
|
|
267
|
+
expect(manifest.features).toEqual({ translationSearch: false, duplicates: false });
|
|
257
268
|
expect(manifest.paths.root).toBe("data/root/index.json");
|
|
258
269
|
await expect(pathExists(root, "catalog-out/data/root/translations/77656c.json")).resolves.toBe(
|
|
259
270
|
false,
|
|
260
271
|
);
|
|
272
|
+
await expect(
|
|
273
|
+
pathExists(root, "catalog-out/data/root/duplicates/locales/en-US.json"),
|
|
274
|
+
).resolves.toBe(false);
|
|
275
|
+
await expect(
|
|
276
|
+
pathExists(root, "catalog-out/data/root/history/message/common.welcome/page-1.json"),
|
|
277
|
+
).resolves.toBe(false);
|
|
278
|
+
await expect(
|
|
279
|
+
pathExists(root, "catalog-out/data/root/history/message/common.draft/page-1.json"),
|
|
280
|
+
).resolves.toBe(false);
|
|
261
281
|
expect(index.counts.message).toBe(2);
|
|
262
282
|
expect(
|
|
263
283
|
index.entities.message.find((entry: any) => entry.key === "common.welcome").targets,
|
|
@@ -321,31 +341,6 @@ describe("catalog", function () {
|
|
|
321
341
|
]),
|
|
322
342
|
);
|
|
323
343
|
expect(locale.targetFormats.web.number.money.minimumFractionDigits).toBe(2);
|
|
324
|
-
expect(localeDuplicates).toEqual({
|
|
325
|
-
locale: "en-US",
|
|
326
|
-
summary: {
|
|
327
|
-
duplicateValues: 1,
|
|
328
|
-
duplicateMessageKeys: 2,
|
|
329
|
-
},
|
|
330
|
-
duplicateValues: [
|
|
331
|
-
{
|
|
332
|
-
value: "Welcome",
|
|
333
|
-
messageKeys: ["common.draft", "common.welcome"],
|
|
334
|
-
sources: [
|
|
335
|
-
{ messageKey: "common.draft", locale: "en" },
|
|
336
|
-
{ messageKey: "common.welcome", locale: "en" },
|
|
337
|
-
],
|
|
338
|
-
},
|
|
339
|
-
],
|
|
340
|
-
});
|
|
341
|
-
expect(emptyLocaleDuplicates).toEqual({
|
|
342
|
-
locale: "nl",
|
|
343
|
-
summary: {
|
|
344
|
-
duplicateValues: 0,
|
|
345
|
-
duplicateMessageKeys: 0,
|
|
346
|
-
},
|
|
347
|
-
duplicateValues: [],
|
|
348
|
-
});
|
|
349
344
|
expect(target.formatRowsByLocale["en-US"]).toEqual(
|
|
350
345
|
expect.arrayContaining([
|
|
351
346
|
expect.objectContaining({
|
|
@@ -403,6 +398,56 @@ describe("catalog", function () {
|
|
|
403
398
|
expect(history.entries).toEqual([]);
|
|
404
399
|
});
|
|
405
400
|
|
|
401
|
+
it("exports locale duplicate reports only when opted in", async function () {
|
|
402
|
+
const root = await createProject();
|
|
403
|
+
roots.push(root);
|
|
404
|
+
const projectConfig = getProjectConfig(root);
|
|
405
|
+
const datasource = new Datasource(projectConfig, root);
|
|
406
|
+
|
|
407
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
408
|
+
outDir: "catalog-out",
|
|
409
|
+
copyAssets: false,
|
|
410
|
+
withDuplicates: true,
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const manifest = await readJson<any>(root, "catalog-out/data/manifest.json");
|
|
414
|
+
const localeDuplicates = await readJson<any>(
|
|
415
|
+
root,
|
|
416
|
+
"catalog-out/data/root/duplicates/locales/en-US.json",
|
|
417
|
+
);
|
|
418
|
+
const emptyLocaleDuplicates = await readJson<any>(
|
|
419
|
+
root,
|
|
420
|
+
"catalog-out/data/root/duplicates/locales/nl.json",
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
expect(manifest.features).toEqual({ translationSearch: false, duplicates: true });
|
|
424
|
+
expect(localeDuplicates).toEqual({
|
|
425
|
+
locale: "en-US",
|
|
426
|
+
summary: {
|
|
427
|
+
duplicateValues: 1,
|
|
428
|
+
duplicateMessageKeys: 2,
|
|
429
|
+
},
|
|
430
|
+
duplicateValues: [
|
|
431
|
+
{
|
|
432
|
+
value: "Welcome",
|
|
433
|
+
messageKeys: ["common.draft", "common.welcome"],
|
|
434
|
+
sources: [
|
|
435
|
+
{ messageKey: "common.draft", locale: "en" },
|
|
436
|
+
{ messageKey: "common.welcome", locale: "en" },
|
|
437
|
+
],
|
|
438
|
+
},
|
|
439
|
+
],
|
|
440
|
+
});
|
|
441
|
+
expect(emptyLocaleDuplicates).toEqual({
|
|
442
|
+
locale: "nl",
|
|
443
|
+
summary: {
|
|
444
|
+
duplicateValues: 0,
|
|
445
|
+
duplicateMessageKeys: 0,
|
|
446
|
+
},
|
|
447
|
+
duplicateValues: [],
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
406
451
|
it("exports translation search shards only when opted in", async function () {
|
|
407
452
|
const root = await createProject();
|
|
408
453
|
roots.push(root);
|
|
@@ -418,11 +463,121 @@ describe("catalog", function () {
|
|
|
418
463
|
const manifest = await readJson<any>(root, "catalog-out/data/manifest.json");
|
|
419
464
|
const shard = await readJson<any>(root, "catalog-out/data/root/translations/77656c.json");
|
|
420
465
|
|
|
421
|
-
expect(manifest.features).toEqual({ translationSearch: true });
|
|
466
|
+
expect(manifest.features).toEqual({ translationSearch: true, duplicates: false });
|
|
422
467
|
expect(shard["common.welcome"]).toEqual(expect.arrayContaining(["welcome", "welcome pro"]));
|
|
423
468
|
expect(shard["common.draft"]).toEqual(["welcome"]);
|
|
424
469
|
});
|
|
425
470
|
|
|
471
|
+
it("prints progress output for default catalog export", async function () {
|
|
472
|
+
const root = await createProject();
|
|
473
|
+
roots.push(root);
|
|
474
|
+
const projectConfig = getProjectConfig(root);
|
|
475
|
+
const datasource = new Datasource(projectConfig, root);
|
|
476
|
+
|
|
477
|
+
const output = await captureConsoleLog(async () => {
|
|
478
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
479
|
+
outDir: "catalog-out",
|
|
480
|
+
copyAssets: false,
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
expect(output).toContain("Generating Messagevisor catalog");
|
|
485
|
+
expect(output).toContain("Output: catalog-out");
|
|
486
|
+
expect(output).toContain("Router: browser");
|
|
487
|
+
expect(output).toContain("Features: none");
|
|
488
|
+
expect(output).toContain("Preparing output directory");
|
|
489
|
+
expect(output).toContain("Reading Git history");
|
|
490
|
+
expect(output).toContain("Discovering project sets");
|
|
491
|
+
expect(output).toContain("Writing project history");
|
|
492
|
+
expect(output).toContain("Root catalog");
|
|
493
|
+
expect(output).toContain("Processing entities");
|
|
494
|
+
expect(output).toContain("Writing messages");
|
|
495
|
+
expect(output).toContain("Writing message details");
|
|
496
|
+
expect(output).toContain("Writing message history pages");
|
|
497
|
+
expect(output).toContain("Writing manifest");
|
|
498
|
+
expect(output).toContain("Catalog exported to catalog-out");
|
|
499
|
+
expect(output).toContain("Time:");
|
|
500
|
+
expect(output).not.toContain("Scanning duplicate translations");
|
|
501
|
+
expect(output).not.toContain("Building translation search shards");
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it("prints optional catalog progress only when feature work is enabled", async function () {
|
|
505
|
+
const root = await createProject();
|
|
506
|
+
roots.push(root);
|
|
507
|
+
const projectConfig = getProjectConfig(root);
|
|
508
|
+
const datasource = new Datasource(projectConfig, root);
|
|
509
|
+
|
|
510
|
+
const output = await captureConsoleLog(async () => {
|
|
511
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
512
|
+
outDir: "catalog-out",
|
|
513
|
+
copyAssets: false,
|
|
514
|
+
withDuplicates: true,
|
|
515
|
+
withTranslationSearch: true,
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
expect(output).toContain("Features: translation search, duplicates");
|
|
520
|
+
expect(output).toContain("Scanning duplicate translations");
|
|
521
|
+
expect(output).toContain("Writing duplicate reports");
|
|
522
|
+
expect(output).toContain("Building translation search shards");
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
it("exports many messages deterministically without empty history files", async function () {
|
|
526
|
+
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), "messagevisor-catalog-"));
|
|
527
|
+
roots.push(root);
|
|
528
|
+
|
|
529
|
+
await writeFile(root, "messagevisor.config.js", "module.exports = {};\n");
|
|
530
|
+
await writeFile(root, "locales/en.yml", "description: English\n");
|
|
531
|
+
|
|
532
|
+
const messageCount = 1200;
|
|
533
|
+
await Promise.all(
|
|
534
|
+
Array.from({ length: messageCount }, (_, index) => {
|
|
535
|
+
const key = String(index).padStart(4, "0");
|
|
536
|
+
return writeFile(
|
|
537
|
+
root,
|
|
538
|
+
`messages/bulk/${key}.yml`,
|
|
539
|
+
`description: Bulk ${key}\ntranslations:\n en: Bulk ${key}\n`,
|
|
540
|
+
);
|
|
541
|
+
}),
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
const projectConfig = getProjectConfig(root);
|
|
545
|
+
const datasource = new Datasource(projectConfig, root);
|
|
546
|
+
|
|
547
|
+
const output = await captureConsoleLog(async () => {
|
|
548
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
549
|
+
outDir: "catalog-out",
|
|
550
|
+
copyAssets: false,
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
const index = await readJson<any>(root, "catalog-out/data/root/index.json");
|
|
555
|
+
const firstMessage = await readJson<any>(
|
|
556
|
+
root,
|
|
557
|
+
"catalog-out/data/root/entities/message/bulk.0000.json",
|
|
558
|
+
);
|
|
559
|
+
const lastMessage = await readJson<any>(
|
|
560
|
+
root,
|
|
561
|
+
"catalog-out/data/root/entities/message/bulk.1199.json",
|
|
562
|
+
);
|
|
563
|
+
|
|
564
|
+
expect(index.counts.message).toBe(messageCount);
|
|
565
|
+
expect(index.entities.message.slice(0, 3).map((entry: any) => entry.key)).toEqual([
|
|
566
|
+
"bulk.0000",
|
|
567
|
+
"bulk.0001",
|
|
568
|
+
"bulk.0002",
|
|
569
|
+
]);
|
|
570
|
+
expect(firstMessage.sourcePath).toBe("messages/bulk/0000.yml");
|
|
571
|
+
expect(lastMessage.translations).toEqual([
|
|
572
|
+
{ locale: "en", value: "Bulk 1199", source: "direct" },
|
|
573
|
+
]);
|
|
574
|
+
await expect(
|
|
575
|
+
pathExists(root, "catalog-out/data/root/history/message/bulk.0000/page-1.json"),
|
|
576
|
+
).resolves.toBe(false);
|
|
577
|
+
expect(output).toContain("1200 messages");
|
|
578
|
+
expect(output).toContain("1200 empty histories skipped");
|
|
579
|
+
});
|
|
580
|
+
|
|
426
581
|
it("streams Git history into project, entity, and last-modified catalog data", async function () {
|
|
427
582
|
const root = await createProject();
|
|
428
583
|
roots.push(root);
|
|
@@ -492,9 +647,12 @@ describe("catalog", function () {
|
|
|
492
647
|
]),
|
|
493
648
|
);
|
|
494
649
|
expect(messageHistory.entries).toHaveLength(2);
|
|
495
|
-
expect(
|
|
496
|
-
|
|
497
|
-
);
|
|
650
|
+
expect(messageHistory.entries[0].entities).toEqual([
|
|
651
|
+
{ type: "message", key: "common.welcome" },
|
|
652
|
+
]);
|
|
653
|
+
expect(spacedMessageHistory.entries[0].entities).toEqual([
|
|
654
|
+
{ type: "message", key: "common.with space" },
|
|
655
|
+
]);
|
|
498
656
|
expect(message.lastModified).toMatchObject({
|
|
499
657
|
author: "Catalog Tester",
|
|
500
658
|
commit: projectHistory.entries[0].commit,
|
|
@@ -506,6 +664,67 @@ describe("catalog", function () {
|
|
|
506
664
|
});
|
|
507
665
|
});
|
|
508
666
|
|
|
667
|
+
it("keeps large commit entity lists out of per-entity history files", async function () {
|
|
668
|
+
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), "messagevisor-catalog-"));
|
|
669
|
+
roots.push(root);
|
|
670
|
+
|
|
671
|
+
await writeFile(root, "messagevisor.config.js", "module.exports = {};\n");
|
|
672
|
+
await writeFile(root, "locales/en.yml", "description: English\n");
|
|
673
|
+
|
|
674
|
+
const messageCount = 1200;
|
|
675
|
+
await Promise.all(
|
|
676
|
+
Array.from({ length: messageCount }, (_, index) => {
|
|
677
|
+
const key = String(index).padStart(4, "0");
|
|
678
|
+
return writeFile(
|
|
679
|
+
root,
|
|
680
|
+
`messages/bulk/${key}.yml`,
|
|
681
|
+
`description: Bulk ${key}\ntranslations:\n en: Bulk ${key}\n`,
|
|
682
|
+
);
|
|
683
|
+
}),
|
|
684
|
+
);
|
|
685
|
+
|
|
686
|
+
git(root, ["init"]);
|
|
687
|
+
git(root, ["add", "."]);
|
|
688
|
+
gitCommit(root, "large message import");
|
|
689
|
+
|
|
690
|
+
const projectConfig = getProjectConfig(root);
|
|
691
|
+
const datasource = new Datasource(projectConfig, root);
|
|
692
|
+
|
|
693
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
694
|
+
outDir: "catalog-out",
|
|
695
|
+
copyAssets: false,
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const projectHistory = await readJson<any>(
|
|
699
|
+
root,
|
|
700
|
+
"catalog-out/data/project/history/page-1.json",
|
|
701
|
+
);
|
|
702
|
+
const firstMessageHistory = await readJson<any>(
|
|
703
|
+
root,
|
|
704
|
+
"catalog-out/data/root/history/message/bulk.0000/page-1.json",
|
|
705
|
+
);
|
|
706
|
+
const lastMessageHistory = await readJson<any>(
|
|
707
|
+
root,
|
|
708
|
+
"catalog-out/data/root/history/message/bulk.1199/page-1.json",
|
|
709
|
+
);
|
|
710
|
+
|
|
711
|
+
expect(projectHistory.entries[0].entities).toHaveLength(messageCount + 1);
|
|
712
|
+
expect(projectHistory.entries[0].entities).toEqual(
|
|
713
|
+
expect.arrayContaining([
|
|
714
|
+
{ type: "locale", key: "en" },
|
|
715
|
+
{ type: "message", key: "bulk.0000" },
|
|
716
|
+
{ type: "message", key: "bulk.1199" },
|
|
717
|
+
]),
|
|
718
|
+
);
|
|
719
|
+
expect(firstMessageHistory.entries[0]).toMatchObject({
|
|
720
|
+
commit: projectHistory.entries[0].commit,
|
|
721
|
+
author: projectHistory.entries[0].author,
|
|
722
|
+
timestamp: projectHistory.entries[0].timestamp,
|
|
723
|
+
entities: [{ type: "message", key: "bulk.0000" }],
|
|
724
|
+
});
|
|
725
|
+
expect(lastMessageHistory.entries[0].entities).toEqual([{ type: "message", key: "bulk.1199" }]);
|
|
726
|
+
});
|
|
727
|
+
|
|
509
728
|
it("exports branch-aware repository links and hash router mode when requested", async function () {
|
|
510
729
|
const root = await createProject();
|
|
511
730
|
roots.push(root);
|
|
@@ -700,22 +919,41 @@ describe("catalog", function () {
|
|
|
700
919
|
const admin = await readJson<any>(root, "catalog-out/data/sets/admin/index.json");
|
|
701
920
|
|
|
702
921
|
expect(manifest.sets).toBe(true);
|
|
703
|
-
expect(manifest.features).toEqual({ translationSearch: false });
|
|
922
|
+
expect(manifest.features).toEqual({ translationSearch: false, duplicates: false });
|
|
704
923
|
expect(manifest.setKeys).toEqual(["admin", "storefront"]);
|
|
705
924
|
await expect(
|
|
706
925
|
pathExists(root, "catalog-out/data/sets/storefront/translations/73746f.json"),
|
|
707
926
|
).resolves.toBe(false);
|
|
927
|
+
await expect(
|
|
928
|
+
pathExists(root, "catalog-out/data/sets/storefront/duplicates/locales/en.json"),
|
|
929
|
+
).resolves.toBe(false);
|
|
930
|
+
|
|
931
|
+
expect(storefront.counts.message).toBe(2);
|
|
932
|
+
expect(admin.counts.message).toBe(2);
|
|
933
|
+
await expect(
|
|
934
|
+
readJson<any>(root, "catalog-out/data/sets/storefront/entities/message/common.welcome.json"),
|
|
935
|
+
).resolves.toMatchObject({
|
|
936
|
+
key: "common.welcome",
|
|
937
|
+
entity: { translations: { en: "storefront" } },
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
941
|
+
outDir: "catalog-with-duplicates",
|
|
942
|
+
copyAssets: false,
|
|
943
|
+
withDuplicates: true,
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
const optInManifest = await readJson<any>(root, "catalog-with-duplicates/data/manifest.json");
|
|
708
947
|
const storefrontDuplicates = await readJson<any>(
|
|
709
948
|
root,
|
|
710
|
-
"catalog-
|
|
949
|
+
"catalog-with-duplicates/data/sets/storefront/duplicates/locales/en.json",
|
|
711
950
|
);
|
|
712
951
|
const adminDuplicates = await readJson<any>(
|
|
713
952
|
root,
|
|
714
|
-
"catalog-
|
|
953
|
+
"catalog-with-duplicates/data/sets/admin/duplicates/locales/en.json",
|
|
715
954
|
);
|
|
716
955
|
|
|
717
|
-
expect(
|
|
718
|
-
expect(admin.counts.message).toBe(2);
|
|
956
|
+
expect(optInManifest.features).toEqual({ translationSearch: false, duplicates: true });
|
|
719
957
|
expect(storefrontDuplicates.duplicateValues).toEqual([
|
|
720
958
|
{
|
|
721
959
|
value: "storefront",
|
|
@@ -736,12 +974,38 @@ describe("catalog", function () {
|
|
|
736
974
|
],
|
|
737
975
|
},
|
|
738
976
|
]);
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
977
|
+
});
|
|
978
|
+
|
|
979
|
+
it("prints set names while exporting set project catalogs", async function () {
|
|
980
|
+
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), "messagevisor-catalog-"));
|
|
981
|
+
roots.push(root);
|
|
982
|
+
|
|
983
|
+
await writeFile(root, "messagevisor.config.js", "module.exports = { sets: true };\n");
|
|
984
|
+
|
|
985
|
+
for (const set of ["storefront", "admin"]) {
|
|
986
|
+
await writeFile(root, `sets/${set}/locales/en.yml`, "description: English\n");
|
|
987
|
+
await writeFile(
|
|
988
|
+
root,
|
|
989
|
+
`sets/${set}/messages/common/welcome.yml`,
|
|
990
|
+
`description: Welcome\ntranslations:\n en: ${set}\n`,
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
const projectConfig = getProjectConfig(root);
|
|
995
|
+
const datasource = new Datasource(projectConfig, root);
|
|
996
|
+
|
|
997
|
+
const output = await captureConsoleLog(async () => {
|
|
998
|
+
await catalogApi.exportCatalog(root, projectConfig, datasource, {
|
|
999
|
+
outDir: "catalog-out",
|
|
1000
|
+
copyAssets: false,
|
|
1001
|
+
});
|
|
744
1002
|
});
|
|
1003
|
+
|
|
1004
|
+
expect(output).toContain("Sets: enabled");
|
|
1005
|
+
expect(output).toContain("Discovering project sets");
|
|
1006
|
+
expect(output).toContain('Set "admin"');
|
|
1007
|
+
expect(output).toContain('Set "storefront"');
|
|
1008
|
+
expect(output).toContain("Processing entities");
|
|
745
1009
|
});
|
|
746
1010
|
|
|
747
1011
|
it("exports set translation search shards when opted in", async function () {
|
|
@@ -778,7 +1042,7 @@ describe("catalog", function () {
|
|
|
778
1042
|
"catalog-out/data/sets/admin/translations/61646d.json",
|
|
779
1043
|
);
|
|
780
1044
|
|
|
781
|
-
expect(manifest.features).toEqual({ translationSearch: true });
|
|
1045
|
+
expect(manifest.features).toEqual({ translationSearch: true, duplicates: false });
|
|
782
1046
|
expect(storefrontShard).toEqual({ "common.welcome": ["storefront"] });
|
|
783
1047
|
expect(adminShard).toEqual({ "common.welcome": ["admin"] });
|
|
784
1048
|
});
|
|
@@ -988,6 +1252,19 @@ describe("catalog plugin", function () {
|
|
|
988
1252
|
);
|
|
989
1253
|
});
|
|
990
1254
|
|
|
1255
|
+
it("forwards duplicates option for dev catalog mode", async function () {
|
|
1256
|
+
const { handler } = createPlugin();
|
|
1257
|
+
|
|
1258
|
+
await handler({ _: ["catalog"], withDuplicates: true });
|
|
1259
|
+
|
|
1260
|
+
expect(exportMock).toHaveBeenLastCalledWith(
|
|
1261
|
+
expect.any(String),
|
|
1262
|
+
expect.any(Object),
|
|
1263
|
+
expect.any(Object),
|
|
1264
|
+
expect.objectContaining({ withDuplicates: true, dev: true }),
|
|
1265
|
+
);
|
|
1266
|
+
});
|
|
1267
|
+
|
|
991
1268
|
it("forwards translation search option for export subcommand", async function () {
|
|
992
1269
|
const { handler } = createPlugin();
|
|
993
1270
|
|
|
@@ -1005,16 +1282,45 @@ describe("catalog plugin", function () {
|
|
|
1005
1282
|
);
|
|
1006
1283
|
});
|
|
1007
1284
|
|
|
1285
|
+
it("forwards duplicates option for export subcommand", async function () {
|
|
1286
|
+
const { handler } = createPlugin();
|
|
1287
|
+
|
|
1288
|
+
await handler({
|
|
1289
|
+
_: ["catalog", "export"],
|
|
1290
|
+
subcommand: "export",
|
|
1291
|
+
"with-duplicates": true,
|
|
1292
|
+
});
|
|
1293
|
+
|
|
1294
|
+
expect(exportMock).toHaveBeenLastCalledWith(
|
|
1295
|
+
expect.any(String),
|
|
1296
|
+
expect.any(Object),
|
|
1297
|
+
expect.any(Object),
|
|
1298
|
+
expect.objectContaining({ withDuplicates: true }),
|
|
1299
|
+
);
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1008
1302
|
it("forwards long and short port options for serve subcommand", async function () {
|
|
1009
1303
|
const { handler } = createPlugin();
|
|
1010
1304
|
|
|
1011
|
-
await handler({
|
|
1305
|
+
await handler({
|
|
1306
|
+
_: ["catalog", "serve"],
|
|
1307
|
+
subcommand: "serve",
|
|
1308
|
+
port: 3103,
|
|
1309
|
+
"with-duplicates": true,
|
|
1310
|
+
"with-translation-search": true,
|
|
1311
|
+
});
|
|
1012
1312
|
expect(serveMock).toHaveBeenLastCalledWith(
|
|
1013
1313
|
expect.any(String),
|
|
1014
1314
|
expect.any(Object),
|
|
1015
1315
|
expect.any(Object),
|
|
1016
1316
|
expect.not.objectContaining({ withTranslationSearch: true }),
|
|
1017
1317
|
);
|
|
1318
|
+
expect(serveMock).toHaveBeenLastCalledWith(
|
|
1319
|
+
expect.any(String),
|
|
1320
|
+
expect.any(Object),
|
|
1321
|
+
expect.any(Object),
|
|
1322
|
+
expect.not.objectContaining({ withDuplicates: true }),
|
|
1323
|
+
);
|
|
1018
1324
|
expect(serveMock).toHaveBeenLastCalledWith(
|
|
1019
1325
|
expect.any(String),
|
|
1020
1326
|
expect.any(Object),
|
|
@@ -1043,4 +1349,17 @@ describe("catalog plugin", function () {
|
|
|
1043
1349
|
expect.objectContaining({ port: undefined }),
|
|
1044
1350
|
);
|
|
1045
1351
|
});
|
|
1352
|
+
|
|
1353
|
+
it("does not print catalog generation progress for serve subcommand", async function () {
|
|
1354
|
+
const { handler } = createPlugin();
|
|
1355
|
+
|
|
1356
|
+
const output = await captureConsoleLog(async () => {
|
|
1357
|
+
await handler({ _: ["catalog", "serve"], subcommand: "serve" });
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
expect(output).not.toContain("Generating Messagevisor catalog");
|
|
1361
|
+
expect(output).not.toContain("Processing entities");
|
|
1362
|
+
expect(serveMock).toHaveBeenCalledTimes(1);
|
|
1363
|
+
expect(exportMock).not.toHaveBeenCalled();
|
|
1364
|
+
});
|
|
1046
1365
|
});
|