gt-sanity 0.0.6 → 1.0.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.
Files changed (88) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/index.d.mts +95 -73
  3. package/dist/index.d.ts +95 -73
  4. package/dist/index.js +9066 -1207
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +9083 -1197
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +8 -3
  9. package/src/adapter/core.ts +41 -4
  10. package/src/adapter/getLocales.ts +2 -2
  11. package/src/components/TranslationsProvider.tsx +942 -0
  12. package/src/components/page/BatchProgress.tsx +27 -0
  13. package/src/components/page/ImportAllDialog.tsx +51 -0
  14. package/src/components/page/ImportMissingDialog.tsx +55 -0
  15. package/src/components/page/TranslateAllDialog.tsx +55 -0
  16. package/src/components/page/TranslationsTable.tsx +81 -0
  17. package/src/components/page/TranslationsTool.tsx +299 -837
  18. package/src/components/shared/BaseTranslationWrapper.tsx +82 -0
  19. package/src/components/shared/LocaleCheckbox.tsx +47 -0
  20. package/src/components/shared/SingleDocumentView.tsx +108 -0
  21. package/src/components/tab/TranslationView.tsx +379 -0
  22. package/src/components/tab/TranslationsTab.tsx +25 -0
  23. package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +6 -9
  24. package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +5 -24
  25. package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +3 -23
  26. package/src/configuration/baseDocumentLevelConfig/index.ts +16 -68
  27. package/src/configuration/baseFieldLevelConfig.ts +15 -50
  28. package/src/index.ts +29 -43
  29. package/src/sanity-api/findDocuments.ts +44 -0
  30. package/src/sanity-api/publishDocuments.ts +49 -0
  31. package/src/sanity-api/resolveRefs.ts +146 -0
  32. package/src/serialization/BaseDocumentMerger.ts +138 -0
  33. package/src/serialization/BaseSerializationConfig.ts +220 -0
  34. package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/documentLevelDeserialization.test.ts.snap +189 -0
  35. package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/fieldLevelDeserialization.test.ts.snap +107 -0
  36. package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +397 -0
  37. package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts +107 -0
  38. package/src/serialization/__tests__/BaseDocumentDeserializer/fieldLevelDeserialization.test.ts +107 -0
  39. package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/documentLevelMerge.test.ts.snap +193 -0
  40. package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/fieldLevelMerge.test.ts.snap +97 -0
  41. package/src/serialization/__tests__/BaseDocumentMerger/baseMerge.test.ts +36 -0
  42. package/src/serialization/__tests__/BaseDocumentMerger/documentLevelMerge.test.ts +96 -0
  43. package/src/serialization/__tests__/BaseDocumentMerger/fieldLevelMerge.test.ts +142 -0
  44. package/src/serialization/__tests__/BaseDocumentMerger/utils.ts +52 -0
  45. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentInlineMarks.test.ts.snap +39 -0
  46. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentLevelSerialization.test.ts.snap +8 -0
  47. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/fieldLevelSerialization.test.ts.snap +8 -0
  48. package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +345 -0
  49. package/src/serialization/__tests__/BaseDocumentSerializer/documentInlineMarks.test.ts +53 -0
  50. package/src/serialization/__tests__/BaseDocumentSerializer/documentLevelSerialization.test.ts +120 -0
  51. package/src/serialization/__tests__/BaseDocumentSerializer/fieldLevelSerialization.test.ts +153 -0
  52. package/src/serialization/__tests__/BaseDocumentSerializer/utils.ts +27 -0
  53. package/src/serialization/__tests__/README +2 -0
  54. package/src/serialization/__tests__/__fixtures__/annotationAndInlineBlocks.json +140 -0
  55. package/src/serialization/__tests__/__fixtures__/customStyles.json +62 -0
  56. package/src/serialization/__tests__/__fixtures__/documentInlineMarks.json +70 -0
  57. package/src/serialization/__tests__/__fixtures__/documentLevelArticle.json +185 -0
  58. package/src/serialization/__tests__/__fixtures__/fieldLevelArticle.json +107 -0
  59. package/src/serialization/__tests__/__fixtures__/inlineDocumentLevelArticle.json +134 -0
  60. package/src/serialization/__tests__/__fixtures__/inlineSchema.ts +270 -0
  61. package/src/serialization/__tests__/__fixtures__/messy-html.html +26 -0
  62. package/src/serialization/__tests__/__fixtures__/nestedLanguageFields.json +54 -0
  63. package/src/serialization/__tests__/__fixtures__/schema.ts +310 -0
  64. package/src/serialization/__tests__/global.setup.ts +40 -0
  65. package/src/serialization/__tests__/helpers.ts +132 -0
  66. package/src/serialization/data.ts +82 -0
  67. package/src/serialization/deserialize/BaseDocumentDeserializer.ts +171 -0
  68. package/src/serialization/deserialize/helpers.ts +42 -0
  69. package/src/serialization/helpers.ts +18 -0
  70. package/src/serialization/index.ts +11 -0
  71. package/src/serialization/serialize/fieldFilters.ts +124 -0
  72. package/src/serialization/serialize/index.ts +284 -0
  73. package/src/serialization/types.ts +41 -0
  74. package/src/translation/importDocument.ts +4 -5
  75. package/src/translation/uploadFiles.ts +1 -1
  76. package/src/types.ts +3 -19
  77. package/src/utils/batchProcessor.ts +111 -0
  78. package/src/utils/importUtils.ts +95 -0
  79. package/src/utils/serialize.ts +25 -5
  80. package/src/utils/shared.ts +1 -1
  81. package/src/adapter/index.ts +0 -13
  82. package/src/components/NewTask.tsx +0 -251
  83. package/src/components/TaskView.tsx +0 -257
  84. package/src/components/TranslationContext.tsx +0 -24
  85. package/src/components/TranslationView.tsx +0 -114
  86. package/src/components/TranslationsTab.tsx +0 -181
  87. /package/src/components/{LanguageStatus.tsx → shared/LanguageStatus.tsx} +0 -0
  88. /package/src/components/{ProgressBar.tsx → shared/ProgressBar.tsx} +0 -0
@@ -0,0 +1,107 @@
1
+ import { PortableTextBlock } from 'sanity';
2
+ import { expect, test } from 'vitest';
3
+ import { fieldLevelArticle } from '../BaseDocumentSerializer/utils';
4
+ import { getDeserialized, toPlainText } from '../helpers';
5
+
6
+ test('Global test of working field-level functionality and snapshot match', () => {
7
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
8
+ expect(deserialized).toMatchSnapshot();
9
+ });
10
+
11
+ /*
12
+ * Top-level plain text
13
+ */
14
+
15
+ test('String and text types get deserialized correctly at top-level -- field level', () => {
16
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
17
+ expect(deserialized.title.en).toEqual(fieldLevelArticle.title.en);
18
+ expect(deserialized.snippet.en).toEqual(fieldLevelArticle.snippet.en);
19
+ });
20
+
21
+ /*
22
+ * Presence and accuracy of fields in "vanilla" deserialization -- objects
23
+ */
24
+ test('Nested object contains accurate values -- field level', () => {
25
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
26
+ const origTitle = fieldLevelArticle.config.en.title;
27
+ const deserializedTitle = deserialized.config.en.title;
28
+ expect(origTitle).toEqual(deserializedTitle);
29
+
30
+ const origBlockText = fieldLevelArticle.config.en.nestedArrayField;
31
+ const deserializedBlockText = deserialized.config.en.nestedArrayField;
32
+
33
+ const origKeys = origBlockText.map((block: PortableTextBlock) => block._key);
34
+ const deserializedKeys = deserializedBlockText.map(
35
+ (block: PortableTextBlock) => block._key
36
+ );
37
+
38
+ expect(deserializedKeys.sort()).toEqual(origKeys.sort());
39
+ expect(toPlainText(deserializedBlockText)).toEqual(
40
+ toPlainText(origBlockText)
41
+ );
42
+ });
43
+
44
+ test('Nested object in an object contains accurate values -- field level', () => {
45
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
46
+ const origNestedObject = fieldLevelArticle.config.en.objectAsField;
47
+ const deserializedNestedObject = deserialized.config.en.objectAsField;
48
+
49
+ expect(origNestedObject.title).toEqual(deserializedNestedObject.title);
50
+
51
+ const origKeys = origNestedObject.content.map(
52
+ (block: PortableTextBlock) => block._key
53
+ );
54
+ const deserializedKeys = deserializedNestedObject.content.map(
55
+ (block: PortableTextBlock) => block._key
56
+ );
57
+
58
+ expect(origKeys.sort()).toEqual(deserializedKeys.sort());
59
+ expect(toPlainText(deserializedNestedObject.content)).toEqual(
60
+ toPlainText(origNestedObject.content)
61
+ );
62
+ });
63
+
64
+ /*
65
+ * Presence and accuracy of fields in vanilla deserialization -- arrays
66
+ */
67
+
68
+ test('Array contains all serializable blocks with keys, in order -- field level', () => {
69
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
70
+ const origKeys = fieldLevelArticle.content.en.map(
71
+ (block: PortableTextBlock) => block._key
72
+ );
73
+ const deserializedKeys = deserialized.content.en.map(
74
+ (block: PortableTextBlock) => block._key
75
+ );
76
+ expect(deserializedKeys.sort()).toEqual(origKeys.sort());
77
+ });
78
+
79
+ test('Array contains top-level block text -- field level', () => {
80
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
81
+ expect(toPlainText(deserialized.content.en)).toEqual(
82
+ toPlainText(fieldLevelArticle.content.en)
83
+ );
84
+ });
85
+
86
+ test('Object in array contains accurate values in nested object -- field level', () => {
87
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
88
+ const origTitle = fieldLevelArticle.content.en.find(
89
+ (block: Record<string, any>) => block._type === 'objectField'
90
+ ).objectAsField.title;
91
+ const deserializedTitle = deserialized.content.en.find(
92
+ (block: Record<string, any>) => block._type === 'objectField'
93
+ ).objectAsField.title;
94
+ expect(deserializedTitle).toEqual(origTitle);
95
+
96
+ const origBlockText = toPlainText(
97
+ fieldLevelArticle.content.en.find(
98
+ (block: Record<string, any>) => block._type === 'objectField'
99
+ ).objectAsField.content
100
+ ).trim();
101
+ const deserializedBlockText = toPlainText(
102
+ fieldLevelArticle.content.en.find(
103
+ (block: Record<string, any>) => block._type === 'objectField'
104
+ ).objectAsField.content
105
+ ).trim();
106
+ expect(deserializedBlockText).toEqual(origBlockText);
107
+ });
@@ -0,0 +1,193 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Global document level snapshot test 1`] = `
4
+ {
5
+ "_createdAt": "2021-09-01T23:00:13Z",
6
+ "_id": "drafts.d8ffc675-ce86-4f60-9ac8-da164cde3b0a",
7
+ "_rev": "fxcnqj-uew-gr7-v6r-z965tfm69",
8
+ "_type": "documentLevelArticle",
9
+ "_updatedAt": "2021-09-01T23:02:05Z",
10
+ "config": {
11
+ "_type": "objectField",
12
+ "nestedArrayField": [
13
+ {
14
+ "_key": "4a58adc7c507",
15
+ "_type": "block",
16
+ "children": [
17
+ {
18
+ "_key": "4f6bc15ae261",
19
+ "_type": "span",
20
+ "marks": [],
21
+ "text": "New text",
22
+ },
23
+ ],
24
+ "markDefs": [],
25
+ "style": "normal",
26
+ },
27
+ ],
28
+ "objectAsField": {
29
+ "_type": "childObjectField",
30
+ "content": [
31
+ {
32
+ "_key": "1aa228ac848b",
33
+ "_type": "block",
34
+ "children": [
35
+ {
36
+ "_key": "e2cf67af8e62",
37
+ "_type": "span",
38
+ "marks": [],
39
+ "text": "This is a block text 2 levels deep",
40
+ },
41
+ ],
42
+ "markDefs": [],
43
+ "style": "normal",
44
+ },
45
+ ],
46
+ "title": "A new nested title",
47
+ },
48
+ "title": "A new title",
49
+ },
50
+ "content": [
51
+ {
52
+ "_key": "a4d177e92666",
53
+ "_type": "block",
54
+ "children": [
55
+ {
56
+ "_key": "randomKey-18",
57
+ "_type": "span",
58
+ "marks": [],
59
+ "text": "New block text",
60
+ },
61
+ ],
62
+ "markDefs": [],
63
+ "style": "normal",
64
+ },
65
+ {
66
+ "_key": "c0313627775e",
67
+ "_type": "objectField",
68
+ "objectAsField": {
69
+ "_type": "childObjectField",
70
+ "content": [
71
+ {
72
+ "_key": "4f24f6fbfae7",
73
+ "_type": "block",
74
+ "children": [
75
+ {
76
+ "_key": "d68f4288f5b7",
77
+ "_type": "span",
78
+ "marks": [],
79
+ "text": "This is block text in a nested object in an object in top-level block text.",
80
+ },
81
+ ],
82
+ "markDefs": [],
83
+ "style": "normal",
84
+ },
85
+ ],
86
+ "title": "This is a nested object in an object in top-level block text.",
87
+ },
88
+ "title": "This is an object in top-level block text.",
89
+ },
90
+ {
91
+ "_key": "9e2ab13c6d63",
92
+ "_type": "block",
93
+ "children": [
94
+ {
95
+ "_key": "17e856dc4766",
96
+ "_type": "span",
97
+ "marks": [],
98
+ "text": "This is h1 text",
99
+ },
100
+ ],
101
+ "markDefs": [],
102
+ "style": "h1",
103
+ },
104
+ {
105
+ "_key": "297142fbaf21",
106
+ "_type": "block",
107
+ "children": [
108
+ {
109
+ "_key": "0b2f9e94a161",
110
+ "_type": "span",
111
+ "marks": [],
112
+ "text": "This is h2 text",
113
+ },
114
+ ],
115
+ "markDefs": [],
116
+ "style": "h2",
117
+ },
118
+ {
119
+ "_key": "76e648fc3845",
120
+ "_type": "block",
121
+ "children": [
122
+ {
123
+ "_key": "49f466bbc78c",
124
+ "_type": "span",
125
+ "marks": [],
126
+ "text": "Bullet 1",
127
+ },
128
+ ],
129
+ "level": 1,
130
+ "listItem": "bullet",
131
+ "markDefs": [],
132
+ "style": "normal",
133
+ },
134
+ {
135
+ "_key": "d090cd8b27d2",
136
+ "_type": "block",
137
+ "children": [
138
+ {
139
+ "_key": "599c6991018f",
140
+ "_type": "span",
141
+ "marks": [],
142
+ "text": "nested bullet a",
143
+ },
144
+ ],
145
+ "level": 2,
146
+ "listItem": "bullet",
147
+ "markDefs": [],
148
+ "style": "normal",
149
+ },
150
+ {
151
+ "_key": "1cdffa5d50f5",
152
+ "_type": "block",
153
+ "children": [
154
+ {
155
+ "_key": "c16eb16f01cb",
156
+ "_type": "span",
157
+ "marks": [],
158
+ "text": "Styled bullet 2",
159
+ },
160
+ ],
161
+ "level": 1,
162
+ "listItem": "bullet",
163
+ "markDefs": [],
164
+ "style": "h2",
165
+ },
166
+ {
167
+ "_key": "da29f5063059",
168
+ "_type": "block",
169
+ "children": [
170
+ {
171
+ "_key": "e3d7e3eaad54",
172
+ "_type": "span",
173
+ "marks": [],
174
+ "text": "Number 1",
175
+ },
176
+ ],
177
+ "level": 1,
178
+ "listItem": "number",
179
+ "markDefs": [],
180
+ "style": "h3",
181
+ },
182
+ ],
183
+ "hidden": true,
184
+ "meta": "Do not translate this",
185
+ "snippet": "A new document snippet",
186
+ "tags": [
187
+ "tag 1",
188
+ "tag 2",
189
+ "tag 3",
190
+ ],
191
+ "title": "A new document title",
192
+ }
193
+ `;
@@ -0,0 +1,97 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Global field level snapshot test 1`] = `
4
+ {
5
+ "_id": "drafts.2947533e-1ea5-4116-955b-339608d3445d",
6
+ "_rev": "l58oha-n06-1s4-f6i-74g6cuakl",
7
+ "_type": "fieldLevelArticle",
8
+ "config.es_ES": {
9
+ "_type": "objectField",
10
+ "nestedArrayField": [
11
+ {
12
+ "_key": "f49b4d7e3e51",
13
+ "_type": "block",
14
+ "children": [
15
+ {
16
+ "_key": "a6170f21181c",
17
+ "_type": "span",
18
+ "marks": [],
19
+ "text": "New text",
20
+ },
21
+ ],
22
+ "markDefs": [],
23
+ "style": "normal",
24
+ },
25
+ ],
26
+ "objectAsField": {
27
+ "_type": "childObjectField",
28
+ "content": [
29
+ {
30
+ "_key": "869168fe3a2a",
31
+ "_type": "block",
32
+ "children": [
33
+ {
34
+ "_key": "10d423df228a",
35
+ "_type": "span",
36
+ "marks": [],
37
+ "text": "This is block text 2 levels deep",
38
+ },
39
+ ],
40
+ "markDefs": [],
41
+ "style": "normal",
42
+ },
43
+ ],
44
+ "title": "A new nested title",
45
+ },
46
+ "title": "A new title",
47
+ },
48
+ "content.es_ES": [
49
+ {
50
+ "_key": "e2a39d768ff8",
51
+ "_type": "block",
52
+ "children": [
53
+ {
54
+ "_key": "randomKey-18",
55
+ "_type": "span",
56
+ "marks": [],
57
+ "text": "New block text",
58
+ },
59
+ ],
60
+ "markDefs": [],
61
+ "style": "normal",
62
+ },
63
+ {
64
+ "_key": "271b0c6ee984",
65
+ "_type": "objectField",
66
+ "objectAsField": {
67
+ "_type": "childObjectField",
68
+ "content": [
69
+ {
70
+ "_key": "4f24f6fbfae7",
71
+ "_type": "block",
72
+ "children": [
73
+ {
74
+ "_key": "d68f4288f5b7",
75
+ "_type": "span",
76
+ "marks": [],
77
+ "text": "This is block text in a nested object in an object in top-level block text.",
78
+ },
79
+ ],
80
+ "markDefs": [],
81
+ "style": "normal",
82
+ },
83
+ ],
84
+ "title": "This is a nested object in an object in top-level block text.",
85
+ },
86
+ "title": "This is an object in top-level block text.",
87
+ },
88
+ ],
89
+ "snippet.es_ES": "A new document snippet",
90
+ "tags.es_ES": [
91
+ "tag 1",
92
+ "tag 2",
93
+ "tag 3",
94
+ ],
95
+ "title.es_ES": "A new document title",
96
+ }
97
+ `;
@@ -0,0 +1,36 @@
1
+ import { createRequire } from 'module';
2
+ import { PortableTextBlock } from 'sanity';
3
+ import { expect, test } from 'vitest';
4
+ import { BaseDocumentMerger } from '../../index';
5
+ import { getNewDocument } from './utils';
6
+
7
+ const require = createRequire(import.meta.url);
8
+
9
+ const documentLevelArticle = require('../__fixtures__/documentLevelArticle.json');
10
+
11
+ /*
12
+ * STYLE TAGS
13
+ */
14
+ test('Merged document should maintain style tags', () => {
15
+ const newDocument = getNewDocument();
16
+ const mergedDocument = BaseDocumentMerger.documentLevelMerge(
17
+ newDocument,
18
+ documentLevelArticle
19
+ );
20
+ const origH1Block = documentLevelArticle.content.find(
21
+ (block: PortableTextBlock) => block.style === 'h1'
22
+ );
23
+ const origH2Block = documentLevelArticle.content.find(
24
+ (block: PortableTextBlock) => block.style === 'h2'
25
+ );
26
+ const mergedH1Block = mergedDocument.content.find(
27
+ (block: PortableTextBlock) => block.style === 'h1'
28
+ );
29
+ const mergedH2Block = mergedDocument.content.find(
30
+ (block: PortableTextBlock) => block.style === 'h2'
31
+ );
32
+ expect(mergedH1Block).toBeDefined();
33
+ expect(mergedH2Block).toBeDefined();
34
+ expect(mergedH1Block._key).toEqual(origH1Block._key);
35
+ expect(mergedH2Block._key).toEqual(origH2Block._key);
36
+ });
@@ -0,0 +1,96 @@
1
+ import { createRequire } from 'module';
2
+ import { expect, test } from 'vitest';
3
+ import { BaseDocumentMerger } from '../../index';
4
+ import { getNewDocument, getNewObject } from './utils';
5
+
6
+ const require = createRequire(import.meta.url);
7
+
8
+ const documentLevelArticle = require('../__fixtures__/documentLevelArticle.json');
9
+
10
+ const newDocument = getNewDocument();
11
+ const mergedDocument = BaseDocumentMerger.documentLevelMerge(
12
+ newDocument,
13
+ documentLevelArticle
14
+ );
15
+
16
+ test('Global document level snapshot test', () => {
17
+ expect(mergedDocument).toMatchSnapshot();
18
+ });
19
+
20
+ /*
21
+ * Objects
22
+ */
23
+ test('Top-level string / text fields from new document override old document', () => {
24
+ expect(mergedDocument.title).toEqual(newDocument.title);
25
+ expect(mergedDocument.snippet).toEqual(newDocument.snippet);
26
+ expect(mergedDocument.title).not.toEqual(documentLevelArticle.title);
27
+ expect(mergedDocument.snippet).not.toEqual(documentLevelArticle.snippet);
28
+ });
29
+
30
+ test('Nested object fields override old object fields', () => {
31
+ expect(mergedDocument.config.title).toEqual(newDocument.config.title);
32
+ expect(mergedDocument.config.title).not.toEqual(
33
+ documentLevelArticle.config.title
34
+ );
35
+ expect(mergedDocument.config.nestedArrayField[0].children[0].text).toEqual(
36
+ newDocument.config.nestedArrayField[0].children[0].text
37
+ );
38
+ expect(
39
+ mergedDocument.config.nestedArrayField[0].children[0].text
40
+ ).not.toEqual(
41
+ documentLevelArticle.config.nestedArrayField[0].children[0].text
42
+ );
43
+ });
44
+
45
+ test('Nested object merge uses old fields when not present on new object', () => {
46
+ expect(newDocument.config.objectAsField.content).toBeUndefined();
47
+ expect(mergedDocument.config.objectAsField.content).toBeDefined();
48
+ });
49
+
50
+ /*
51
+ * Arrays
52
+ */
53
+ test('Arrays will use new objects when they exist', () => {
54
+ expect(mergedDocument.content[0].children[0].text).toEqual(
55
+ newDocument.content[0].children[0].text
56
+ );
57
+ expect(mergedDocument.content[0].children[0].text).not.toEqual(
58
+ documentLevelArticle.content[0].children[0].text
59
+ );
60
+ });
61
+
62
+ test('Arrays will use old blocks if they do not exist on new object', () => {
63
+ expect(newDocument.content[1]).toBeUndefined();
64
+ expect(mergedDocument.content[1]).toBeDefined();
65
+ expect(mergedDocument.content[1]._key).toEqual(
66
+ documentLevelArticle.content[1]._key
67
+ );
68
+ });
69
+
70
+ test('Arrays will merge objects in the array', () => {
71
+ const documentWithIncompleteObj = getNewDocument();
72
+ const incompleteObj = getNewObject();
73
+
74
+ //add a new block with some new content, but not all new content
75
+ documentWithIncompleteObj.content.push({
76
+ _key: documentLevelArticle.content[1]._key,
77
+ objectAsField: incompleteObj.objectAsField,
78
+ title: incompleteObj.title,
79
+ });
80
+ const documentWithMergedObj = BaseDocumentMerger.documentLevelMerge(
81
+ documentWithIncompleteObj,
82
+ documentLevelArticle
83
+ );
84
+
85
+ expect(documentWithMergedObj.content[1].title).toEqual(
86
+ documentWithIncompleteObj.content[1].title
87
+ );
88
+ expect(documentWithMergedObj.content[1].objectAsField.title).toEqual(
89
+ documentWithIncompleteObj.content[1].objectAsField.title
90
+ );
91
+ //content existed on old doc but not new, so the two coexist happily
92
+ expect(
93
+ documentWithIncompleteObj.content[1].objectAsField.content
94
+ ).toBeUndefined();
95
+ expect(documentWithMergedObj.content[1].objectAsField.content).toBeDefined();
96
+ });
@@ -0,0 +1,142 @@
1
+ import { createRequire } from 'module';
2
+ import { expect, test } from 'vitest';
3
+ import { BaseDocumentMerger } from '../../index';
4
+ import { getDeserialized } from '../helpers';
5
+ import { getNewFieldLevelDocument, getNewObject } from './utils';
6
+ import clone from 'just-clone';
7
+
8
+ const require = createRequire(import.meta.url);
9
+
10
+ const fieldLevelArticle = require('../__fixtures__/fieldLevelArticle.json');
11
+ const nestedLanguageFields = require('../__fixtures__/nestedLanguageFields.json');
12
+
13
+ const newDocument = getNewFieldLevelDocument();
14
+ const fieldLevelPatches = BaseDocumentMerger.fieldLevelMerge(
15
+ newDocument,
16
+ fieldLevelArticle,
17
+ 'es_ES',
18
+ 'en'
19
+ );
20
+ test('Global field level snapshot test', () => {
21
+ expect(fieldLevelPatches).toMatchSnapshot();
22
+ });
23
+
24
+ /*
25
+ * Objects
26
+ */
27
+ test('Top-level string / text fields from new document patch to new field, and will be maintained in old field', () => {
28
+ expect(fieldLevelPatches['title.es_ES']).toEqual(newDocument.title.en);
29
+ expect(fieldLevelPatches['snippet.es_ES']).toEqual(newDocument.snippet.en);
30
+ expect(fieldLevelPatches['title.es_ES']).not.toEqual(
31
+ fieldLevelArticle.title.en
32
+ );
33
+ expect(fieldLevelPatches['snippet.es_ES']).not.toEqual(
34
+ fieldLevelArticle.snippet.en
35
+ );
36
+ expect(fieldLevelPatches['title.en']).toBeUndefined();
37
+ expect(fieldLevelPatches['snippet.en']).toBeUndefined();
38
+ });
39
+
40
+ test('Nested object fields override old object fields', () => {
41
+ expect(fieldLevelPatches['config.es_ES'].title).toEqual(
42
+ newDocument.config.en.title
43
+ );
44
+ expect(fieldLevelPatches['config.es_ES'].title).not.toEqual(
45
+ fieldLevelArticle.config.en.title
46
+ );
47
+ expect(
48
+ fieldLevelPatches['config.es_ES'].nestedArrayField[0].children[0].text
49
+ ).toEqual(newDocument.config.en.nestedArrayField[0].children[0].text);
50
+ expect(
51
+ fieldLevelPatches['config.es_ES'].nestedArrayField[0].children[0].text
52
+ ).not.toEqual(
53
+ fieldLevelArticle.config.en.nestedArrayField[0].children[0].text
54
+ );
55
+ });
56
+
57
+ test('Nested object merge uses old fields when not present on new object', () => {
58
+ expect(fieldLevelPatches['config.es_ES'].objectAsField.content).toEqual(
59
+ fieldLevelArticle.config.en.objectAsField.content
60
+ );
61
+ });
62
+
63
+ /*
64
+ * Arrays
65
+ */
66
+ test('Arrays will use new objects when they exist', () => {
67
+ expect(fieldLevelPatches['content.es_ES'][0].children[0].text).toEqual(
68
+ newDocument.content.en[0].children[0].text
69
+ );
70
+ expect(fieldLevelPatches['content.es_ES'][0].children[0].text).not.toEqual(
71
+ fieldLevelArticle.content.en[0].children[0].text
72
+ );
73
+ });
74
+
75
+ test('Arrays will use old blocks if they do not exist on new object', () => {
76
+ expect(newDocument.content.en[1]).toBeUndefined();
77
+ expect(fieldLevelPatches['content.es_ES'][1]).toBeDefined();
78
+ expect(fieldLevelPatches['content.es_ES'][1]._key).toEqual(
79
+ fieldLevelArticle.content.en[1]._key
80
+ );
81
+ });
82
+
83
+ test('Arrays will merge objects in the array', () => {
84
+ const documentWithIncompleteObj = getNewFieldLevelDocument();
85
+ const incompleteObj = getNewObject();
86
+
87
+ //add a new block with some new content, but not all new content
88
+ documentWithIncompleteObj.content.en.push({
89
+ _key: fieldLevelArticle.content.en[1]._key,
90
+ objectAsField: incompleteObj.objectAsField,
91
+ title: incompleteObj.title,
92
+ //does not include "content" field -- we want that to be merged with the old
93
+ });
94
+
95
+ const fieldDocWithMergedObj = BaseDocumentMerger.fieldLevelMerge(
96
+ documentWithIncompleteObj,
97
+ fieldLevelArticle,
98
+ 'es_ES',
99
+ 'en'
100
+ );
101
+
102
+ expect(fieldDocWithMergedObj['content.es_ES'][1].title).toEqual(
103
+ documentWithIncompleteObj.content.en[1].title
104
+ );
105
+ expect(fieldDocWithMergedObj['content.es_ES'][1].objectAsField.title).toEqual(
106
+ documentWithIncompleteObj.content.en[1].objectAsField.title
107
+ );
108
+ //"content" field existed on old doc but not new, so the two coexist happily
109
+ expect(
110
+ documentWithIncompleteObj.content.en[1].objectAsField.content
111
+ ).toBeUndefined();
112
+ expect(
113
+ fieldDocWithMergedObj['content.es_ES'][1].objectAsField.content
114
+ ).toBeDefined();
115
+ });
116
+
117
+ test('nested locale fields will be merged', () => {
118
+ const newNestedFields = clone(nestedLanguageFields);
119
+ newNestedFields.pageFields.name.en = 'This is a new page field name';
120
+ newNestedFields.slices[0].en[0].children[0].text = 'This is new slice text';
121
+ const baseDocumentWithNestedFields = {
122
+ ...fieldLevelArticle,
123
+ ...nestedLanguageFields,
124
+ };
125
+ const newDocumentWithNestedFields = getDeserialized(
126
+ { ...fieldLevelArticle, ...newNestedFields },
127
+ 'field'
128
+ );
129
+ const nestedFieldLevelPatches = BaseDocumentMerger.fieldLevelMerge(
130
+ newDocumentWithNestedFields,
131
+ baseDocumentWithNestedFields,
132
+ 'es_ES',
133
+ 'en'
134
+ );
135
+
136
+ expect(
137
+ nestedFieldLevelPatches['slices[0].es_ES'][0].children[0].text
138
+ ).toEqual(newDocumentWithNestedFields.slices[0].en[0].children[0].text);
139
+ expect(nestedFieldLevelPatches['pageFields.name.es_ES']).toEqual(
140
+ newDocumentWithNestedFields.pageFields.name.en
141
+ );
142
+ });