@messagevisor/catalog 0.7.0 → 0.9.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-9TVwIAiT.js +73 -0
- package/dist/assets/index-BgEITLIy.css +1 -0
- package/dist/index.html +2 -2
- package/lib/node/index.d.ts +53 -0
- package/lib/node/index.js +646 -102
- package/lib/node/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/lists/EntityList.tsx +207 -63
- package/src/node/index.spec.ts +104 -1
- package/src/node/index.ts +718 -53
- package/src/pages/EntityDetailPage.tsx +63 -24
- package/dist/assets/index-Cx9rnVIG.js +0 -73
- package/dist/assets/index-DrsX4U8c.css +0 -1
|
@@ -22,6 +22,8 @@ interface EntityListHighlightTerms {
|
|
|
22
22
|
lastModified: string[];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
const LIST_SEARCH_QUERY_DEBOUNCE_MS = 450;
|
|
26
|
+
|
|
25
27
|
function matchesQuery(
|
|
26
28
|
entity: EntitySummary,
|
|
27
29
|
parsed: ParsedQuery,
|
|
@@ -260,6 +262,168 @@ function setSearchParam(searchParams: URLSearchParams, key: string, value?: stri
|
|
|
260
262
|
return next;
|
|
261
263
|
}
|
|
262
264
|
|
|
265
|
+
const EntityListSearchControls = React.memo(function EntityListSearchControls({
|
|
266
|
+
type,
|
|
267
|
+
query,
|
|
268
|
+
firstTargetKey,
|
|
269
|
+
firstLocaleKey,
|
|
270
|
+
translationSearchEnabled,
|
|
271
|
+
onQueryCommit,
|
|
272
|
+
onHintClick,
|
|
273
|
+
}: {
|
|
274
|
+
type: EntityType;
|
|
275
|
+
query: string;
|
|
276
|
+
firstTargetKey: string | undefined;
|
|
277
|
+
firstLocaleKey: string | undefined;
|
|
278
|
+
translationSearchEnabled: boolean;
|
|
279
|
+
onQueryCommit: (value: string) => void;
|
|
280
|
+
onHintClick: (hint: string) => void;
|
|
281
|
+
}) {
|
|
282
|
+
const [inputValue, setInputValue] = React.useState(query);
|
|
283
|
+
const [showHints, setShowHints] = React.useState(false);
|
|
284
|
+
const debounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
285
|
+
const idleRef = React.useRef<number | null>(null);
|
|
286
|
+
const animationFrameRef = React.useRef<number | null>(null);
|
|
287
|
+
const postPaintTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
288
|
+
const hasHintsDefined =
|
|
289
|
+
getQueryHints(type, firstTargetKey, firstLocaleKey, translationSearchEnabled) !== null;
|
|
290
|
+
|
|
291
|
+
const clearPendingCommit = React.useCallback(() => {
|
|
292
|
+
if (debounceRef.current) {
|
|
293
|
+
clearTimeout(debounceRef.current);
|
|
294
|
+
debounceRef.current = null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (idleRef.current !== null && "cancelIdleCallback" in window) {
|
|
298
|
+
window.cancelIdleCallback(idleRef.current);
|
|
299
|
+
idleRef.current = null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (animationFrameRef.current !== null) {
|
|
303
|
+
window.cancelAnimationFrame(animationFrameRef.current);
|
|
304
|
+
animationFrameRef.current = null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (postPaintTimeoutRef.current) {
|
|
308
|
+
clearTimeout(postPaintTimeoutRef.current);
|
|
309
|
+
postPaintTimeoutRef.current = null;
|
|
310
|
+
}
|
|
311
|
+
}, []);
|
|
312
|
+
|
|
313
|
+
const commitAfterBrowserWork = React.useCallback(
|
|
314
|
+
(value: string) => {
|
|
315
|
+
if ("requestIdleCallback" in window) {
|
|
316
|
+
idleRef.current = window.requestIdleCallback(
|
|
317
|
+
() => {
|
|
318
|
+
idleRef.current = null;
|
|
319
|
+
onQueryCommit(value);
|
|
320
|
+
},
|
|
321
|
+
{ timeout: 700 },
|
|
322
|
+
);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
animationFrameRef.current = window.requestAnimationFrame(() => {
|
|
327
|
+
animationFrameRef.current = null;
|
|
328
|
+
postPaintTimeoutRef.current = setTimeout(() => {
|
|
329
|
+
postPaintTimeoutRef.current = null;
|
|
330
|
+
onQueryCommit(value);
|
|
331
|
+
}, 0);
|
|
332
|
+
});
|
|
333
|
+
},
|
|
334
|
+
[onQueryCommit],
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
const scheduleQueryCommit = React.useCallback(
|
|
338
|
+
(value: string) => {
|
|
339
|
+
clearPendingCommit();
|
|
340
|
+
debounceRef.current = setTimeout(() => {
|
|
341
|
+
debounceRef.current = null;
|
|
342
|
+
commitAfterBrowserWork(value);
|
|
343
|
+
}, LIST_SEARCH_QUERY_DEBOUNCE_MS);
|
|
344
|
+
},
|
|
345
|
+
[clearPendingCommit, commitAfterBrowserWork],
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const flushQueryCommit = React.useCallback(
|
|
349
|
+
(value: string) => {
|
|
350
|
+
clearPendingCommit();
|
|
351
|
+
onQueryCommit(value);
|
|
352
|
+
},
|
|
353
|
+
[clearPendingCommit, onQueryCommit],
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
React.useEffect(() => {
|
|
357
|
+
clearPendingCommit();
|
|
358
|
+
setInputValue(query);
|
|
359
|
+
}, [query, clearPendingCommit]);
|
|
360
|
+
|
|
361
|
+
React.useEffect(() => {
|
|
362
|
+
return () => {
|
|
363
|
+
clearPendingCommit();
|
|
364
|
+
};
|
|
365
|
+
}, [clearPendingCommit]);
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<div>
|
|
369
|
+
<div className="relative">
|
|
370
|
+
<Input
|
|
371
|
+
value={inputValue}
|
|
372
|
+
onChange={(event) => {
|
|
373
|
+
const val = event.target.value;
|
|
374
|
+
setInputValue(val);
|
|
375
|
+
scheduleQueryCommit(val);
|
|
376
|
+
}}
|
|
377
|
+
onBlur={(event) => {
|
|
378
|
+
flushQueryCommit(event.target.value);
|
|
379
|
+
}}
|
|
380
|
+
onKeyDown={(event) => {
|
|
381
|
+
if (event.key === "Enter") {
|
|
382
|
+
flushQueryCommit(event.currentTarget.value);
|
|
383
|
+
}
|
|
384
|
+
}}
|
|
385
|
+
placeholder={`Search ${entityLabels[type].plural.toLowerCase()}...`}
|
|
386
|
+
className={hasHintsDefined ? "pr-10" : ""}
|
|
387
|
+
/>
|
|
388
|
+
{hasHintsDefined && (
|
|
389
|
+
<button
|
|
390
|
+
type="button"
|
|
391
|
+
onClick={() => setShowHints((v) => !v)}
|
|
392
|
+
aria-label={showHints ? "Hide advanced search hints" : "Show advanced search hints"}
|
|
393
|
+
className={[
|
|
394
|
+
"absolute right-3 top-1/2 -translate-y-1/2 flex h-5 w-5 items-center justify-center rounded-full border text-xs font-bold transition-colors",
|
|
395
|
+
showHints
|
|
396
|
+
? "border-primary bg-primary/10 text-primary"
|
|
397
|
+
: "border-border bg-surface text-muted hover:border-primary hover:text-primary",
|
|
398
|
+
].join(" ")}
|
|
399
|
+
>
|
|
400
|
+
?
|
|
401
|
+
</button>
|
|
402
|
+
)}
|
|
403
|
+
</div>
|
|
404
|
+
|
|
405
|
+
{/* Animated slide-down hints panel, aligned to input's inner text area */}
|
|
406
|
+
<div
|
|
407
|
+
className={[
|
|
408
|
+
"grid transition-all duration-200 ease-in-out",
|
|
409
|
+
showHints ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
|
|
410
|
+
].join(" ")}
|
|
411
|
+
>
|
|
412
|
+
<div className="overflow-hidden pl-5">
|
|
413
|
+
<QueryHints
|
|
414
|
+
type={type}
|
|
415
|
+
query={query}
|
|
416
|
+
firstTargetKey={firstTargetKey}
|
|
417
|
+
firstLocaleKey={firstLocaleKey}
|
|
418
|
+
translationSearchEnabled={translationSearchEnabled}
|
|
419
|
+
onHintClick={onHintClick}
|
|
420
|
+
/>
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
);
|
|
425
|
+
});
|
|
426
|
+
|
|
263
427
|
// ---- Component ----
|
|
264
428
|
|
|
265
429
|
export function EntityList(props: {
|
|
@@ -271,23 +435,39 @@ export function EntityList(props: {
|
|
|
271
435
|
}) {
|
|
272
436
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
273
437
|
const [showAll, setShowAll] = React.useState(false);
|
|
274
|
-
const [showHints, setShowHints] = React.useState(false);
|
|
275
438
|
const [translationShard, setTranslationShard] = React.useState<TranslationShard | null>(null);
|
|
276
439
|
const [loadedShardKey, setLoadedShardKey] = React.useState<string | null>(null);
|
|
277
|
-
const
|
|
440
|
+
const translationShardDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
278
441
|
const query = searchParams.get("q") || "";
|
|
279
|
-
const
|
|
442
|
+
const searchParamsRef = React.useRef(searchParams);
|
|
280
443
|
|
|
281
|
-
// Sync input display when the URL query changes externally (hint clicks, navigation)
|
|
282
444
|
React.useEffect(() => {
|
|
283
|
-
|
|
284
|
-
}, [
|
|
445
|
+
searchParamsRef.current = searchParams;
|
|
446
|
+
}, [searchParams]);
|
|
447
|
+
|
|
448
|
+
const commitSearchQuery = React.useCallback(
|
|
449
|
+
(value: string) => {
|
|
450
|
+
const nextQuery = value.trim() ? value : undefined;
|
|
451
|
+
if ((searchParamsRef.current.get("q") || "") === (nextQuery || "")) return;
|
|
452
|
+
React.startTransition(() => {
|
|
453
|
+
setSearchParams(setSearchParam(searchParamsRef.current, "q", nextQuery));
|
|
454
|
+
});
|
|
455
|
+
},
|
|
456
|
+
[setSearchParams],
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
React.useEffect(() => {
|
|
460
|
+
return () => {
|
|
461
|
+
if (translationShardDebounceRef.current) {
|
|
462
|
+
clearTimeout(translationShardDebounceRef.current);
|
|
463
|
+
translationShardDebounceRef.current = null;
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
}, []);
|
|
285
467
|
|
|
286
468
|
const firstTargetKey = props.allEntities?.target?.find((e) => !e.archived)?.key;
|
|
287
469
|
const firstLocaleKey = props.allEntities?.locale?.find((e) => !e.archived)?.key;
|
|
288
470
|
const translationSearchEnabled = props.translationSearchEnabled === true;
|
|
289
|
-
const hasHintsDefined =
|
|
290
|
-
getQueryHints(props.type, firstTargetKey, firstLocaleKey, translationSearchEnabled) !== null;
|
|
291
471
|
|
|
292
472
|
// Compute the 3-char shard prefix needed for the current query
|
|
293
473
|
const _translationQual = parseQuery(query).qualifiers.find((q) => q.key === "translation");
|
|
@@ -298,7 +478,9 @@ export function EntityList(props: {
|
|
|
298
478
|
|
|
299
479
|
// Debounced fetch: only triggers when the 3-char prefix changes
|
|
300
480
|
React.useEffect(() => {
|
|
301
|
-
if (
|
|
481
|
+
if (translationShardDebounceRef.current) {
|
|
482
|
+
clearTimeout(translationShardDebounceRef.current);
|
|
483
|
+
}
|
|
302
484
|
|
|
303
485
|
if (!neededShardKey) {
|
|
304
486
|
setTranslationShard(null);
|
|
@@ -308,8 +490,8 @@ export function EntityList(props: {
|
|
|
308
490
|
|
|
309
491
|
if (neededShardKey === loadedShardKey) return;
|
|
310
492
|
|
|
311
|
-
|
|
312
|
-
|
|
493
|
+
translationShardDebounceRef.current = setTimeout(() => {
|
|
494
|
+
translationShardDebounceRef.current = null;
|
|
313
495
|
fetchTranslationShard(neededShardKey, props.setKey).then((data) => {
|
|
314
496
|
setTranslationShard(data);
|
|
315
497
|
setLoadedShardKey(neededShardKey);
|
|
@@ -317,7 +499,10 @@ export function EntityList(props: {
|
|
|
317
499
|
}, 300);
|
|
318
500
|
|
|
319
501
|
return () => {
|
|
320
|
-
if (
|
|
502
|
+
if (translationShardDebounceRef.current) {
|
|
503
|
+
clearTimeout(translationShardDebounceRef.current);
|
|
504
|
+
translationShardDebounceRef.current = null;
|
|
505
|
+
}
|
|
321
506
|
};
|
|
322
507
|
}, [neededShardKey, loadedShardKey, props.setKey]);
|
|
323
508
|
const sortDirection = getSortDirection(searchParams.get("sort"));
|
|
@@ -359,7 +544,7 @@ export function EntityList(props: {
|
|
|
359
544
|
: current
|
|
360
545
|
? `${current} ${hint}`
|
|
361
546
|
: hint;
|
|
362
|
-
setSearchParams(setSearchParam(
|
|
547
|
+
setSearchParams(setSearchParam(searchParamsRef.current, "q", next || undefined));
|
|
363
548
|
}
|
|
364
549
|
|
|
365
550
|
return (
|
|
@@ -367,56 +552,15 @@ export function EntityList(props: {
|
|
|
367
552
|
<div className="px-6 pt-1">
|
|
368
553
|
<div className="grid gap-3 md:grid-cols-[minmax(0,1fr)_auto]">
|
|
369
554
|
{/* Input + slide-down hints, confined to the first column */}
|
|
370
|
-
<
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
placeholder={`Search ${entityLabels[props.type].plural.toLowerCase()}...`}
|
|
380
|
-
className={hasHintsDefined ? "pr-10" : ""}
|
|
381
|
-
/>
|
|
382
|
-
{hasHintsDefined && (
|
|
383
|
-
<button
|
|
384
|
-
type="button"
|
|
385
|
-
onClick={() => setShowHints((v) => !v)}
|
|
386
|
-
aria-label={
|
|
387
|
-
showHints ? "Hide advanced search hints" : "Show advanced search hints"
|
|
388
|
-
}
|
|
389
|
-
className={[
|
|
390
|
-
"absolute right-3 top-1/2 -translate-y-1/2 flex h-5 w-5 items-center justify-center rounded-full border text-xs font-bold transition-colors",
|
|
391
|
-
showHints
|
|
392
|
-
? "border-primary bg-primary/10 text-primary"
|
|
393
|
-
: "border-border bg-surface text-muted hover:border-primary hover:text-primary",
|
|
394
|
-
].join(" ")}
|
|
395
|
-
>
|
|
396
|
-
?
|
|
397
|
-
</button>
|
|
398
|
-
)}
|
|
399
|
-
</div>
|
|
400
|
-
|
|
401
|
-
{/* Animated slide-down hints panel, aligned to input's inner text area */}
|
|
402
|
-
<div
|
|
403
|
-
className={[
|
|
404
|
-
"grid transition-all duration-200 ease-in-out",
|
|
405
|
-
showHints ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
|
|
406
|
-
].join(" ")}
|
|
407
|
-
>
|
|
408
|
-
<div className="overflow-hidden pl-5">
|
|
409
|
-
<QueryHints
|
|
410
|
-
type={props.type}
|
|
411
|
-
query={query}
|
|
412
|
-
firstTargetKey={firstTargetKey}
|
|
413
|
-
firstLocaleKey={firstLocaleKey}
|
|
414
|
-
translationSearchEnabled={translationSearchEnabled}
|
|
415
|
-
onHintClick={handleHintClick}
|
|
416
|
-
/>
|
|
417
|
-
</div>
|
|
418
|
-
</div>
|
|
419
|
-
</div>
|
|
555
|
+
<EntityListSearchControls
|
|
556
|
+
type={props.type}
|
|
557
|
+
query={query}
|
|
558
|
+
firstTargetKey={firstTargetKey}
|
|
559
|
+
firstLocaleKey={firstLocaleKey}
|
|
560
|
+
translationSearchEnabled={translationSearchEnabled}
|
|
561
|
+
onQueryCommit={commitSearchQuery}
|
|
562
|
+
onHintClick={handleHintClick}
|
|
563
|
+
/>
|
|
420
564
|
|
|
421
565
|
<button
|
|
422
566
|
type="button"
|
package/src/node/index.spec.ts
CHANGED
|
@@ -9,7 +9,12 @@ import { Datasource } from "../../../core/src/datasource";
|
|
|
9
9
|
import { resolveExamples } from "../../../core/src/examples";
|
|
10
10
|
import { findDuplicateTranslations } from "../../../core/src/find-duplicates";
|
|
11
11
|
import { getProjectSetExecutions } from "../../../core/src/sets";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
__catalogDevInternals,
|
|
14
|
+
createCatalogApi,
|
|
15
|
+
createCatalogPlugin,
|
|
16
|
+
type CatalogRuntime,
|
|
17
|
+
} from "./index";
|
|
13
18
|
|
|
14
19
|
const catalogApi = createCatalogApi({
|
|
15
20
|
mergeFormats,
|
|
@@ -1174,6 +1179,104 @@ describe("catalog", function () {
|
|
|
1174
1179
|
|
|
1175
1180
|
expect(viteConfigSource).toContain('base: "/"');
|
|
1176
1181
|
});
|
|
1182
|
+
|
|
1183
|
+
it("watches only catalog input roots in dev mode", async function () {
|
|
1184
|
+
const root = await createProject();
|
|
1185
|
+
roots.push(root);
|
|
1186
|
+
const projectConfig = getProjectConfig(root);
|
|
1187
|
+
|
|
1188
|
+
const watchPaths = __catalogDevInternals.getCatalogInputWatchPaths(root, projectConfig);
|
|
1189
|
+
|
|
1190
|
+
expect(watchPaths).toEqual(
|
|
1191
|
+
expect.arrayContaining([
|
|
1192
|
+
path.join(root, "messagevisor.config.js"),
|
|
1193
|
+
projectConfig.localesDirectoryPath,
|
|
1194
|
+
projectConfig.messagesDirectoryPath,
|
|
1195
|
+
projectConfig.attributesDirectoryPath,
|
|
1196
|
+
projectConfig.segmentsDirectoryPath,
|
|
1197
|
+
projectConfig.targetsDirectoryPath,
|
|
1198
|
+
projectConfig.testsDirectoryPath,
|
|
1199
|
+
]),
|
|
1200
|
+
);
|
|
1201
|
+
expect(watchPaths).not.toContain(projectConfig.catalogDirectoryPath);
|
|
1202
|
+
expect(watchPaths).not.toContain(path.join(root, "node_modules"));
|
|
1203
|
+
});
|
|
1204
|
+
|
|
1205
|
+
it("plans incremental message rebuilds only for safe dev changes", async function () {
|
|
1206
|
+
const root = await createProject();
|
|
1207
|
+
roots.push(root);
|
|
1208
|
+
const projectConfig = getProjectConfig(root);
|
|
1209
|
+
const messagePath = path.join(root, "messages/common/welcome.yml");
|
|
1210
|
+
const localePath = path.join(root, "locales/en-US.yml");
|
|
1211
|
+
|
|
1212
|
+
expect(
|
|
1213
|
+
__catalogDevInternals.classifyCatalogDevChanges(root, projectConfig, [messagePath], {
|
|
1214
|
+
withTranslationSearch: false,
|
|
1215
|
+
withDuplicates: false,
|
|
1216
|
+
}),
|
|
1217
|
+
).toEqual(
|
|
1218
|
+
expect.objectContaining({
|
|
1219
|
+
kind: "message",
|
|
1220
|
+
messageKeys: ["common.welcome"],
|
|
1221
|
+
}),
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
expect(
|
|
1225
|
+
__catalogDevInternals.classifyCatalogDevChanges(root, projectConfig, [messagePath], {
|
|
1226
|
+
withTranslationSearch: true,
|
|
1227
|
+
withDuplicates: false,
|
|
1228
|
+
}),
|
|
1229
|
+
).toEqual(expect.objectContaining({ kind: "full" }));
|
|
1230
|
+
|
|
1231
|
+
expect(
|
|
1232
|
+
__catalogDevInternals.classifyCatalogDevChanges(root, projectConfig, [localePath], {
|
|
1233
|
+
withTranslationSearch: false,
|
|
1234
|
+
withDuplicates: false,
|
|
1235
|
+
}),
|
|
1236
|
+
).toEqual(expect.objectContaining({ kind: "full" }));
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
it("plans set-scoped dev rebuilds for set project input changes", async function () {
|
|
1240
|
+
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), "messagevisor-catalog-"));
|
|
1241
|
+
roots.push(root);
|
|
1242
|
+
|
|
1243
|
+
await writeFile(root, "messagevisor.config.js", "module.exports = { sets: true };\n");
|
|
1244
|
+
await writeFile(root, "sets/storefront/locales/en.yml", "description: English\n");
|
|
1245
|
+
await writeFile(
|
|
1246
|
+
root,
|
|
1247
|
+
"sets/storefront/messages/common/welcome.yml",
|
|
1248
|
+
"description: Welcome\ntranslations:\n en: Welcome\n",
|
|
1249
|
+
);
|
|
1250
|
+
|
|
1251
|
+
const projectConfig = getProjectConfig(root);
|
|
1252
|
+
const localePath = path.join(root, "sets/storefront/locales/en.yml");
|
|
1253
|
+
const messagePath = path.join(root, "sets/storefront/messages/common/welcome.yml");
|
|
1254
|
+
|
|
1255
|
+
expect(__catalogDevInternals.getCatalogInputWatchPaths(root, projectConfig)).toEqual(
|
|
1256
|
+
expect.arrayContaining([
|
|
1257
|
+
path.join(root, "messagevisor.config.js"),
|
|
1258
|
+
projectConfig.setsDirectoryPath,
|
|
1259
|
+
]),
|
|
1260
|
+
);
|
|
1261
|
+
expect(
|
|
1262
|
+
__catalogDevInternals.classifyCatalogDevChanges(root, projectConfig, [messagePath], {
|
|
1263
|
+
withTranslationSearch: false,
|
|
1264
|
+
withDuplicates: false,
|
|
1265
|
+
}),
|
|
1266
|
+
).toEqual(
|
|
1267
|
+
expect.objectContaining({
|
|
1268
|
+
kind: "message",
|
|
1269
|
+
set: "storefront",
|
|
1270
|
+
messageKeys: ["common.welcome"],
|
|
1271
|
+
}),
|
|
1272
|
+
);
|
|
1273
|
+
expect(
|
|
1274
|
+
__catalogDevInternals.classifyCatalogDevChanges(root, projectConfig, [localePath], {
|
|
1275
|
+
withTranslationSearch: false,
|
|
1276
|
+
withDuplicates: false,
|
|
1277
|
+
}),
|
|
1278
|
+
).toEqual(expect.objectContaining({ kind: "set", set: "storefront" }));
|
|
1279
|
+
});
|
|
1177
1280
|
});
|
|
1178
1281
|
|
|
1179
1282
|
describe("catalog plugin", function () {
|