@wix/patterns-cms 1.1.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 (163) hide show
  1. package/dist/cjs/adapter/__tests__/cmsFieldActions.spec.js +436 -0
  2. package/dist/cjs/adapter/__tests__/cmsFieldActions.spec.js.map +1 -0
  3. package/dist/cjs/adapter/__tests__/cmsPermissions.spec.js +175 -0
  4. package/dist/cjs/adapter/__tests__/cmsPermissions.spec.js.map +1 -0
  5. package/dist/cjs/adapter/__tests__/createCmsBackend.spec.js +440 -0
  6. package/dist/cjs/adapter/__tests__/createCmsBackend.spec.js.map +1 -0
  7. package/dist/cjs/adapter/__tests__/filterUtils.spec.js +426 -0
  8. package/dist/cjs/adapter/__tests__/filterUtils.spec.js.map +1 -0
  9. package/dist/cjs/adapter/__tests__/getFieldKey.spec.js +24 -0
  10. package/dist/cjs/adapter/__tests__/getFieldKey.spec.js.map +1 -0
  11. package/dist/cjs/adapter/__tests__/loadCmsSchema.spec.js +166 -0
  12. package/dist/cjs/adapter/__tests__/loadCmsSchema.spec.js.map +1 -0
  13. package/dist/cjs/adapter/__tests__/searchUtils.spec.js +116 -0
  14. package/dist/cjs/adapter/__tests__/searchUtils.spec.js.map +1 -0
  15. package/dist/cjs/adapter/__tests__/sortUtils.spec.js +118 -0
  16. package/dist/cjs/adapter/__tests__/sortUtils.spec.js.map +1 -0
  17. package/dist/cjs/adapter/__tests__/transformCmsSchema.spec.js +210 -0
  18. package/dist/cjs/adapter/__tests__/transformCmsSchema.spec.js.map +1 -0
  19. package/dist/cjs/adapter/__tests__/wixDataQueryRecorder.js +54 -0
  20. package/dist/cjs/adapter/__tests__/wixDataQueryRecorder.js.map +1 -0
  21. package/dist/cjs/adapter/cmsBackup.js +52 -0
  22. package/dist/cjs/adapter/cmsBackup.js.map +1 -0
  23. package/dist/cjs/adapter/cmsFieldTypeMap.js +43 -0
  24. package/dist/cjs/adapter/cmsFieldTypeMap.js.map +1 -0
  25. package/dist/cjs/adapter/cmsPermissions.js +94 -0
  26. package/dist/cjs/adapter/cmsPermissions.js.map +1 -0
  27. package/dist/cjs/adapter/constants.js +20 -0
  28. package/dist/cjs/adapter/constants.js.map +1 -0
  29. package/dist/cjs/adapter/createCmsBackend.js +131 -0
  30. package/dist/cjs/adapter/createCmsBackend.js.map +1 -0
  31. package/dist/cjs/adapter/createCmsFieldActions.js +182 -0
  32. package/dist/cjs/adapter/createCmsFieldActions.js.map +1 -0
  33. package/dist/cjs/adapter/fetchExternalDbConnections.js +24 -0
  34. package/dist/cjs/adapter/fetchExternalDbConnections.js.map +1 -0
  35. package/dist/cjs/adapter/fetchUserPermissions.js +24 -0
  36. package/dist/cjs/adapter/fetchUserPermissions.js.map +1 -0
  37. package/dist/cjs/adapter/filterUtils.js +128 -0
  38. package/dist/cjs/adapter/filterUtils.js.map +1 -0
  39. package/dist/cjs/adapter/getFieldKey.js +19 -0
  40. package/dist/cjs/adapter/getFieldKey.js.map +1 -0
  41. package/dist/cjs/adapter/index.js +36 -0
  42. package/dist/cjs/adapter/index.js.map +1 -0
  43. package/dist/cjs/adapter/loadCmsSchema.js +51 -0
  44. package/dist/cjs/adapter/loadCmsSchema.js.map +1 -0
  45. package/dist/cjs/adapter/pollUntilReady.js +30 -0
  46. package/dist/cjs/adapter/pollUntilReady.js.map +1 -0
  47. package/dist/cjs/adapter/searchUtils.js +32 -0
  48. package/dist/cjs/adapter/searchUtils.js.map +1 -0
  49. package/dist/cjs/adapter/sortUtils.js +34 -0
  50. package/dist/cjs/adapter/sortUtils.js.map +1 -0
  51. package/dist/cjs/adapter/transformCmsSchema.js +75 -0
  52. package/dist/cjs/adapter/transformCmsSchema.js.map +1 -0
  53. package/dist/cjs/index.js +10 -0
  54. package/dist/cjs/index.js.map +1 -0
  55. package/dist/esm/adapter/__tests__/cmsFieldActions.spec.js +335 -0
  56. package/dist/esm/adapter/__tests__/cmsFieldActions.spec.js.map +1 -0
  57. package/dist/esm/adapter/__tests__/cmsPermissions.spec.js +173 -0
  58. package/dist/esm/adapter/__tests__/cmsPermissions.spec.js.map +1 -0
  59. package/dist/esm/adapter/__tests__/createCmsBackend.spec.js +307 -0
  60. package/dist/esm/adapter/__tests__/createCmsBackend.spec.js.map +1 -0
  61. package/dist/esm/adapter/__tests__/filterUtils.spec.js +298 -0
  62. package/dist/esm/adapter/__tests__/filterUtils.spec.js.map +1 -0
  63. package/dist/esm/adapter/__tests__/getFieldKey.spec.js +22 -0
  64. package/dist/esm/adapter/__tests__/getFieldKey.spec.js.map +1 -0
  65. package/dist/esm/adapter/__tests__/loadCmsSchema.spec.js +147 -0
  66. package/dist/esm/adapter/__tests__/loadCmsSchema.spec.js.map +1 -0
  67. package/dist/esm/adapter/__tests__/searchUtils.spec.js +109 -0
  68. package/dist/esm/adapter/__tests__/searchUtils.spec.js.map +1 -0
  69. package/dist/esm/adapter/__tests__/sortUtils.spec.js +85 -0
  70. package/dist/esm/adapter/__tests__/sortUtils.spec.js.map +1 -0
  71. package/dist/esm/adapter/__tests__/transformCmsSchema.spec.js +201 -0
  72. package/dist/esm/adapter/__tests__/transformCmsSchema.spec.js.map +1 -0
  73. package/dist/esm/adapter/__tests__/wixDataQueryRecorder.js +42 -0
  74. package/dist/esm/adapter/__tests__/wixDataQueryRecorder.js.map +1 -0
  75. package/dist/esm/adapter/cmsBackup.js +34 -0
  76. package/dist/esm/adapter/cmsBackup.js.map +1 -0
  77. package/dist/esm/adapter/cmsFieldTypeMap.js +37 -0
  78. package/dist/esm/adapter/cmsFieldTypeMap.js.map +1 -0
  79. package/dist/esm/adapter/cmsPermissions.js +91 -0
  80. package/dist/esm/adapter/cmsPermissions.js.map +1 -0
  81. package/dist/esm/adapter/constants.js +25 -0
  82. package/dist/esm/adapter/constants.js.map +1 -0
  83. package/dist/esm/adapter/createCmsBackend.js +113 -0
  84. package/dist/esm/adapter/createCmsBackend.js.map +1 -0
  85. package/dist/esm/adapter/createCmsFieldActions.js +159 -0
  86. package/dist/esm/adapter/createCmsFieldActions.js.map +1 -0
  87. package/dist/esm/adapter/fetchExternalDbConnections.js +17 -0
  88. package/dist/esm/adapter/fetchExternalDbConnections.js.map +1 -0
  89. package/dist/esm/adapter/fetchUserPermissions.js +15 -0
  90. package/dist/esm/adapter/fetchUserPermissions.js.map +1 -0
  91. package/dist/esm/adapter/filterUtils.js +126 -0
  92. package/dist/esm/adapter/filterUtils.js.map +1 -0
  93. package/dist/esm/adapter/getFieldKey.js +13 -0
  94. package/dist/esm/adapter/getFieldKey.js.map +1 -0
  95. package/dist/esm/adapter/index.js +15 -0
  96. package/dist/esm/adapter/index.js.map +1 -0
  97. package/dist/esm/adapter/loadCmsSchema.js +48 -0
  98. package/dist/esm/adapter/loadCmsSchema.js.map +1 -0
  99. package/dist/esm/adapter/pollUntilReady.js +24 -0
  100. package/dist/esm/adapter/pollUntilReady.js.map +1 -0
  101. package/dist/esm/adapter/searchUtils.js +24 -0
  102. package/dist/esm/adapter/searchUtils.js.map +1 -0
  103. package/dist/esm/adapter/sortUtils.js +21 -0
  104. package/dist/esm/adapter/sortUtils.js.map +1 -0
  105. package/dist/esm/adapter/transformCmsSchema.js +70 -0
  106. package/dist/esm/adapter/transformCmsSchema.js.map +1 -0
  107. package/dist/esm/index.js +2 -0
  108. package/dist/esm/index.js.map +1 -0
  109. package/dist/types/adapter/__tests__/cmsFieldActions.spec.d.ts +2 -0
  110. package/dist/types/adapter/__tests__/cmsFieldActions.spec.d.ts.map +1 -0
  111. package/dist/types/adapter/__tests__/cmsPermissions.spec.d.ts +2 -0
  112. package/dist/types/adapter/__tests__/cmsPermissions.spec.d.ts.map +1 -0
  113. package/dist/types/adapter/__tests__/createCmsBackend.spec.d.ts +2 -0
  114. package/dist/types/adapter/__tests__/createCmsBackend.spec.d.ts.map +1 -0
  115. package/dist/types/adapter/__tests__/filterUtils.spec.d.ts +2 -0
  116. package/dist/types/adapter/__tests__/filterUtils.spec.d.ts.map +1 -0
  117. package/dist/types/adapter/__tests__/getFieldKey.spec.d.ts +2 -0
  118. package/dist/types/adapter/__tests__/getFieldKey.spec.d.ts.map +1 -0
  119. package/dist/types/adapter/__tests__/loadCmsSchema.spec.d.ts +2 -0
  120. package/dist/types/adapter/__tests__/loadCmsSchema.spec.d.ts.map +1 -0
  121. package/dist/types/adapter/__tests__/searchUtils.spec.d.ts +2 -0
  122. package/dist/types/adapter/__tests__/searchUtils.spec.d.ts.map +1 -0
  123. package/dist/types/adapter/__tests__/sortUtils.spec.d.ts +2 -0
  124. package/dist/types/adapter/__tests__/sortUtils.spec.d.ts.map +1 -0
  125. package/dist/types/adapter/__tests__/transformCmsSchema.spec.d.ts +2 -0
  126. package/dist/types/adapter/__tests__/transformCmsSchema.spec.d.ts.map +1 -0
  127. package/dist/types/adapter/__tests__/wixDataQueryRecorder.d.ts +40 -0
  128. package/dist/types/adapter/__tests__/wixDataQueryRecorder.d.ts.map +1 -0
  129. package/dist/types/adapter/cmsBackup.d.ts +7 -0
  130. package/dist/types/adapter/cmsBackup.d.ts.map +1 -0
  131. package/dist/types/adapter/cmsFieldTypeMap.d.ts +8 -0
  132. package/dist/types/adapter/cmsFieldTypeMap.d.ts.map +1 -0
  133. package/dist/types/adapter/cmsPermissions.d.ts +21 -0
  134. package/dist/types/adapter/cmsPermissions.d.ts.map +1 -0
  135. package/dist/types/adapter/constants.d.ts +14 -0
  136. package/dist/types/adapter/constants.d.ts.map +1 -0
  137. package/dist/types/adapter/createCmsBackend.d.ts +9 -0
  138. package/dist/types/adapter/createCmsBackend.d.ts.map +1 -0
  139. package/dist/types/adapter/createCmsFieldActions.d.ts +8 -0
  140. package/dist/types/adapter/createCmsFieldActions.d.ts.map +1 -0
  141. package/dist/types/adapter/fetchExternalDbConnections.d.ts +11 -0
  142. package/dist/types/adapter/fetchExternalDbConnections.d.ts.map +1 -0
  143. package/dist/types/adapter/fetchUserPermissions.d.ts +7 -0
  144. package/dist/types/adapter/fetchUserPermissions.d.ts.map +1 -0
  145. package/dist/types/adapter/filterUtils.d.ts +14 -0
  146. package/dist/types/adapter/filterUtils.d.ts.map +1 -0
  147. package/dist/types/adapter/getFieldKey.d.ts +3 -0
  148. package/dist/types/adapter/getFieldKey.d.ts.map +1 -0
  149. package/dist/types/adapter/index.d.ts +15 -0
  150. package/dist/types/adapter/index.d.ts.map +1 -0
  151. package/dist/types/adapter/loadCmsSchema.d.ts +29 -0
  152. package/dist/types/adapter/loadCmsSchema.d.ts.map +1 -0
  153. package/dist/types/adapter/pollUntilReady.d.ts +11 -0
  154. package/dist/types/adapter/pollUntilReady.d.ts.map +1 -0
  155. package/dist/types/adapter/searchUtils.d.ts +12 -0
  156. package/dist/types/adapter/searchUtils.d.ts.map +1 -0
  157. package/dist/types/adapter/sortUtils.d.ts +11 -0
  158. package/dist/types/adapter/sortUtils.d.ts.map +1 -0
  159. package/dist/types/adapter/transformCmsSchema.d.ts +12 -0
  160. package/dist/types/adapter/transformCmsSchema.d.ts.map +1 -0
  161. package/dist/types/index.d.ts +2 -0
  162. package/dist/types/index.d.ts.map +1 -0
  163. package/package.json +123 -0
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+
3
+ var _data = require("@wix/data");
4
+ var _loadCmsSchema = require("../loadCmsSchema");
5
+ var _fetchUserPermissions = require("../fetchUserPermissions");
6
+ var _fetchExternalDbConnections = require("../fetchExternalDbConnections");
7
+ jest.mock('@wix/essentials', () => ({
8
+ errorHandler: {
9
+ withErrorHandler: fn => fn()
10
+ }
11
+ }));
12
+
13
+ // Keep the real module (cmsFieldTypeMap reads `collections.Type` at evaluation
14
+ // time) and stub only the collection fetch.
15
+ jest.mock('@wix/data', () => {
16
+ const actual = jest.requireActual('@wix/data');
17
+ return {
18
+ ...actual,
19
+ collections: {
20
+ ...actual.collections,
21
+ getDataCollection: jest.fn()
22
+ }
23
+ };
24
+ });
25
+ jest.mock('../fetchUserPermissions', () => ({
26
+ fetchUserPermissions: jest.fn()
27
+ }));
28
+ jest.mock('../fetchExternalDbConnections', () => ({
29
+ fetchExternalDbConnections: jest.fn()
30
+ }));
31
+ const getDataCollection = _data.collections.getDataCollection;
32
+ const fetchUserPermissionsMock = _fetchUserPermissions.fetchUserPermissions;
33
+ const fetchExternalDbConnectionsMock = _fetchExternalDbConnections.fetchExternalDbConnections;
34
+ const COLLECTION_ID = 'collection-1';
35
+ const METASITE_ID = 'msid-1';
36
+ const FIELD_MANAGEMENT_PERMISSIONS = ['WIX_DATA.CREATE_COLLECTION_FIELD', 'WIX_DATA.UPDATE_COLLECTION_FIELD', 'WIX_DATA.DELETE_COLLECTION_FIELD'];
37
+ const makeCollection = () => ({
38
+ _id: COLLECTION_ID,
39
+ collectionType: 'NATIVE',
40
+ displayField: 'title',
41
+ capabilities: {
42
+ dataOperations: ['SAVE', 'UPDATE', 'REMOVE']
43
+ },
44
+ permissions: {
45
+ read: 'ANYONE',
46
+ insert: 'SITE_MEMBER',
47
+ update: 'SITE_MEMBER',
48
+ remove: 'SITE_MEMBER'
49
+ },
50
+ plugins: [],
51
+ fields: [{
52
+ key: 'title',
53
+ type: _data.collections.Type.TEXT,
54
+ systemField: false,
55
+ encrypted: false,
56
+ plugins: [],
57
+ displayName: 'Title',
58
+ capabilities: {
59
+ queryOperators: [],
60
+ sortable: true
61
+ }
62
+ }]
63
+ });
64
+ const httpClient = {};
65
+ describe('createCmsSchemaLoader', () => {
66
+ beforeEach(() => {
67
+ jest.clearAllMocks();
68
+ getDataCollection.mockResolvedValue(makeCollection());
69
+ fetchUserPermissionsMock.mockResolvedValue([]);
70
+ fetchExternalDbConnectionsMock.mockResolvedValue([]);
71
+ });
72
+ it('fetches the collection and returns schema, backend and fieldActions', async () => {
73
+ var _schema$fields$title;
74
+ const loader = (0, _loadCmsSchema.createCmsSchemaLoader)({
75
+ httpClient
76
+ });
77
+ const {
78
+ schema,
79
+ backend,
80
+ fieldActions
81
+ } = await loader(COLLECTION_ID);
82
+ expect(getDataCollection).toHaveBeenCalledWith(COLLECTION_ID, {
83
+ includeAllowedDataPermissions: true
84
+ });
85
+ expect(schema.id).toBe(COLLECTION_ID);
86
+ expect(schema.displayField).toBe('title');
87
+ expect((_schema$fields$title = schema.fields.title) == null ? void 0 : _schema$fields$title.type).toBe('SHORT_TEXT');
88
+ expect(typeof backend.find).toBe('function');
89
+ expect(typeof backend.get).toBe('function');
90
+ expect(typeof (fieldActions == null ? void 0 : fieldActions.addField)).toBe('function');
91
+ });
92
+ it('denies field management by default (no ABAC fetch)', async () => {
93
+ const loader = (0, _loadCmsSchema.createCmsSchemaLoader)({
94
+ httpClient
95
+ });
96
+ const {
97
+ schema
98
+ } = await loader(COLLECTION_ID);
99
+ expect(fetchUserPermissionsMock).not.toHaveBeenCalled();
100
+ expect(schema.schemaPermissions).toEqual({
101
+ createField: false,
102
+ updateField: false,
103
+ deleteField: false
104
+ });
105
+ });
106
+ it('fetches ABAC permissions with the host metasiteId and grants field management', async () => {
107
+ fetchUserPermissionsMock.mockResolvedValue(FIELD_MANAGEMENT_PERMISSIONS);
108
+ const loader = (0, _loadCmsSchema.createCmsSchemaLoader)({
109
+ httpClient,
110
+ includeUserPermissions: true,
111
+ metasiteId: METASITE_ID
112
+ });
113
+ const {
114
+ schema
115
+ } = await loader(COLLECTION_ID);
116
+ expect(fetchUserPermissionsMock).toHaveBeenCalledWith(METASITE_ID);
117
+ expect(schema.schemaPermissions).toEqual({
118
+ createField: true,
119
+ updateField: true,
120
+ deleteField: true
121
+ });
122
+ });
123
+ it('skips the ABAC fetch when no metasiteId is supplied', async () => {
124
+ const loader = (0, _loadCmsSchema.createCmsSchemaLoader)({
125
+ httpClient,
126
+ includeUserPermissions: true
127
+ });
128
+ await loader(COLLECTION_ID);
129
+ expect(fetchUserPermissionsMock).not.toHaveBeenCalled();
130
+ });
131
+ it('uses pre-resolved userPermissions without fetching', async () => {
132
+ const loader = (0, _loadCmsSchema.createCmsSchemaLoader)({
133
+ httpClient,
134
+ userPermissions: FIELD_MANAGEMENT_PERMISSIONS
135
+ });
136
+ const {
137
+ schema
138
+ } = await loader(COLLECTION_ID);
139
+ expect(fetchUserPermissionsMock).not.toHaveBeenCalled();
140
+ expect(schema.schemaPermissions).toEqual({
141
+ createField: true,
142
+ updateField: true,
143
+ deleteField: true
144
+ });
145
+ });
146
+ it('still loads the schema when permission/connection fetches fail', async () => {
147
+ fetchUserPermissionsMock.mockRejectedValue(new Error('perms down'));
148
+ fetchExternalDbConnectionsMock.mockRejectedValue(new Error('connections down'));
149
+ const loader = (0, _loadCmsSchema.createCmsSchemaLoader)({
150
+ httpClient,
151
+ includeUserPermissions: true,
152
+ metasiteId: METASITE_ID
153
+ });
154
+ const {
155
+ schema
156
+ } = await loader(COLLECTION_ID);
157
+ expect(schema.id).toBe(COLLECTION_ID);
158
+ // Failed ABAC fetch degrades to no permissions → field management denied.
159
+ expect(schema.schemaPermissions).toEqual({
160
+ createField: false,
161
+ updateField: false,
162
+ deleteField: false
163
+ });
164
+ });
165
+ });
166
+ //# sourceMappingURL=loadCmsSchema.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_data","require","_loadCmsSchema","_fetchUserPermissions","_fetchExternalDbConnections","jest","mock","errorHandler","withErrorHandler","fn","actual","requireActual","collections","getDataCollection","fetchUserPermissions","fetchExternalDbConnections","fetchUserPermissionsMock","fetchExternalDbConnectionsMock","COLLECTION_ID","METASITE_ID","FIELD_MANAGEMENT_PERMISSIONS","makeCollection","_id","collectionType","displayField","capabilities","dataOperations","permissions","read","insert","update","remove","plugins","fields","key","type","Type","TEXT","systemField","encrypted","displayName","queryOperators","sortable","httpClient","describe","beforeEach","clearAllMocks","mockResolvedValue","it","_schema$fields$title","loader","createCmsSchemaLoader","schema","backend","fieldActions","expect","toHaveBeenCalledWith","includeAllowedDataPermissions","id","toBe","title","find","get","addField","not","toHaveBeenCalled","schemaPermissions","toEqual","createField","updateField","deleteField","includeUserPermissions","metasiteId","userPermissions","mockRejectedValue","Error"],"sources":["../../../../src/adapter/__tests__/loadCmsSchema.spec.ts"],"sourcesContent":["import { collections } from '@wix/data';\nimport {\n createCmsSchemaLoader,\n type CreateCmsSchemaLoaderDeps,\n} from '../loadCmsSchema';\nimport { fetchUserPermissions } from '../fetchUserPermissions';\nimport { fetchExternalDbConnections } from '../fetchExternalDbConnections';\n\njest.mock('@wix/essentials', () => ({\n errorHandler: {\n withErrorHandler: (fn: () => unknown) => fn(),\n },\n}));\n\n// Keep the real module (cmsFieldTypeMap reads `collections.Type` at evaluation\n// time) and stub only the collection fetch.\njest.mock('@wix/data', () => {\n const actual = jest.requireActual('@wix/data');\n return {\n ...actual,\n collections: {\n ...actual.collections,\n getDataCollection: jest.fn(),\n },\n };\n});\n\njest.mock('../fetchUserPermissions', () => ({\n fetchUserPermissions: jest.fn(),\n}));\njest.mock('../fetchExternalDbConnections', () => ({\n fetchExternalDbConnections: jest.fn(),\n}));\n\nconst getDataCollection = collections.getDataCollection as unknown as jest.Mock;\nconst fetchUserPermissionsMock = fetchUserPermissions as unknown as jest.Mock;\nconst fetchExternalDbConnectionsMock =\n fetchExternalDbConnections as unknown as jest.Mock;\n\nconst COLLECTION_ID = 'collection-1';\nconst METASITE_ID = 'msid-1';\n\nconst FIELD_MANAGEMENT_PERMISSIONS = [\n 'WIX_DATA.CREATE_COLLECTION_FIELD',\n 'WIX_DATA.UPDATE_COLLECTION_FIELD',\n 'WIX_DATA.DELETE_COLLECTION_FIELD',\n];\n\nconst makeCollection = (): collections.DataCollection => ({\n _id: COLLECTION_ID,\n collectionType: 'NATIVE',\n displayField: 'title',\n capabilities: { dataOperations: ['SAVE', 'UPDATE', 'REMOVE'] },\n permissions: {\n read: 'ANYONE',\n insert: 'SITE_MEMBER',\n update: 'SITE_MEMBER',\n remove: 'SITE_MEMBER',\n },\n plugins: [],\n fields: [\n {\n key: 'title',\n type: collections.Type.TEXT,\n systemField: false,\n encrypted: false,\n plugins: [],\n displayName: 'Title',\n capabilities: { queryOperators: [], sortable: true },\n },\n ],\n});\n\nconst httpClient = {} as unknown as CreateCmsSchemaLoaderDeps['httpClient'];\n\ndescribe('createCmsSchemaLoader', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n getDataCollection.mockResolvedValue(makeCollection());\n fetchUserPermissionsMock.mockResolvedValue([]);\n fetchExternalDbConnectionsMock.mockResolvedValue([]);\n });\n\n it('fetches the collection and returns schema, backend and fieldActions', async () => {\n const loader = createCmsSchemaLoader({ httpClient });\n\n const { schema, backend, fieldActions } = await loader(COLLECTION_ID);\n\n expect(getDataCollection).toHaveBeenCalledWith(COLLECTION_ID, {\n includeAllowedDataPermissions: true,\n });\n expect(schema.id).toBe(COLLECTION_ID);\n expect(schema.displayField).toBe('title');\n expect(schema.fields.title?.type).toBe('SHORT_TEXT');\n expect(typeof backend.find).toBe('function');\n expect(typeof backend.get).toBe('function');\n expect(typeof fieldActions?.addField).toBe('function');\n });\n\n it('denies field management by default (no ABAC fetch)', async () => {\n const loader = createCmsSchemaLoader({ httpClient });\n\n const { schema } = await loader(COLLECTION_ID);\n\n expect(fetchUserPermissionsMock).not.toHaveBeenCalled();\n expect(schema.schemaPermissions).toEqual({\n createField: false,\n updateField: false,\n deleteField: false,\n });\n });\n\n it('fetches ABAC permissions with the host metasiteId and grants field management', async () => {\n fetchUserPermissionsMock.mockResolvedValue(FIELD_MANAGEMENT_PERMISSIONS);\n const loader = createCmsSchemaLoader({\n httpClient,\n includeUserPermissions: true,\n metasiteId: METASITE_ID,\n });\n\n const { schema } = await loader(COLLECTION_ID);\n\n expect(fetchUserPermissionsMock).toHaveBeenCalledWith(METASITE_ID);\n expect(schema.schemaPermissions).toEqual({\n createField: true,\n updateField: true,\n deleteField: true,\n });\n });\n\n it('skips the ABAC fetch when no metasiteId is supplied', async () => {\n const loader = createCmsSchemaLoader({\n httpClient,\n includeUserPermissions: true,\n });\n\n await loader(COLLECTION_ID);\n\n expect(fetchUserPermissionsMock).not.toHaveBeenCalled();\n });\n\n it('uses pre-resolved userPermissions without fetching', async () => {\n const loader = createCmsSchemaLoader({\n httpClient,\n userPermissions: FIELD_MANAGEMENT_PERMISSIONS,\n });\n\n const { schema } = await loader(COLLECTION_ID);\n\n expect(fetchUserPermissionsMock).not.toHaveBeenCalled();\n expect(schema.schemaPermissions).toEqual({\n createField: true,\n updateField: true,\n deleteField: true,\n });\n });\n\n it('still loads the schema when permission/connection fetches fail', async () => {\n fetchUserPermissionsMock.mockRejectedValue(new Error('perms down'));\n fetchExternalDbConnectionsMock.mockRejectedValue(\n new Error('connections down'),\n );\n const loader = createCmsSchemaLoader({\n httpClient,\n includeUserPermissions: true,\n metasiteId: METASITE_ID,\n });\n\n const { schema } = await loader(COLLECTION_ID);\n\n expect(schema.id).toBe(COLLECTION_ID);\n // Failed ABAC fetch degrades to no permissions → field management denied.\n expect(schema.schemaPermissions).toEqual({\n createField: false,\n updateField: false,\n deleteField: false,\n });\n });\n});\n"],"mappings":";;AAAA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AAIA,IAAAE,qBAAA,GAAAF,OAAA;AACA,IAAAG,2BAAA,GAAAH,OAAA;AAEAI,IAAI,CAACC,IAAI,CAAC,iBAAiB,EAAE,OAAO;EAClCC,YAAY,EAAE;IACZC,gBAAgB,EAAGC,EAAiB,IAAKA,EAAE,CAAC;EAC9C;AACF,CAAC,CAAC,CAAC;;AAEH;AACA;AACAJ,IAAI,CAACC,IAAI,CAAC,WAAW,EAAE,MAAM;EAC3B,MAAMI,MAAM,GAAGL,IAAI,CAACM,aAAa,CAAC,WAAW,CAAC;EAC9C,OAAO;IACL,GAAGD,MAAM;IACTE,WAAW,EAAE;MACX,GAAGF,MAAM,CAACE,WAAW;MACrBC,iBAAiB,EAAER,IAAI,CAACI,EAAE,CAAC;IAC7B;EACF,CAAC;AACH,CAAC,CAAC;AAEFJ,IAAI,CAACC,IAAI,CAAC,yBAAyB,EAAE,OAAO;EAC1CQ,oBAAoB,EAAET,IAAI,CAACI,EAAE,CAAC;AAChC,CAAC,CAAC,CAAC;AACHJ,IAAI,CAACC,IAAI,CAAC,+BAA+B,EAAE,OAAO;EAChDS,0BAA0B,EAAEV,IAAI,CAACI,EAAE,CAAC;AACtC,CAAC,CAAC,CAAC;AAEH,MAAMI,iBAAiB,GAAGD,iBAAW,CAACC,iBAAyC;AAC/E,MAAMG,wBAAwB,GAAGF,0CAA4C;AAC7E,MAAMG,8BAA8B,GAClCF,sDAAkD;AAEpD,MAAMG,aAAa,GAAG,cAAc;AACpC,MAAMC,WAAW,GAAG,QAAQ;AAE5B,MAAMC,4BAA4B,GAAG,CACnC,kCAAkC,EAClC,kCAAkC,EAClC,kCAAkC,CACnC;AAED,MAAMC,cAAc,GAAGA,CAAA,MAAmC;EACxDC,GAAG,EAAEJ,aAAa;EAClBK,cAAc,EAAE,QAAQ;EACxBC,YAAY,EAAE,OAAO;EACrBC,YAAY,EAAE;IAAEC,cAAc,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ;EAAE,CAAC;EAC9DC,WAAW,EAAE;IACXC,IAAI,EAAE,QAAQ;IACdC,MAAM,EAAE,aAAa;IACrBC,MAAM,EAAE,aAAa;IACrBC,MAAM,EAAE;EACV,CAAC;EACDC,OAAO,EAAE,EAAE;EACXC,MAAM,EAAE,CACN;IACEC,GAAG,EAAE,OAAO;IACZC,IAAI,EAAEvB,iBAAW,CAACwB,IAAI,CAACC,IAAI;IAC3BC,WAAW,EAAE,KAAK;IAClBC,SAAS,EAAE,KAAK;IAChBP,OAAO,EAAE,EAAE;IACXQ,WAAW,EAAE,OAAO;IACpBf,YAAY,EAAE;MAAEgB,cAAc,EAAE,EAAE;MAAEC,QAAQ,EAAE;IAAK;EACrD,CAAC;AAEL,CAAC,CAAC;AAEF,MAAMC,UAAU,GAAG,CAAC,CAAuD;AAE3EC,QAAQ,CAAC,uBAAuB,EAAE,MAAM;EACtCC,UAAU,CAAC,MAAM;IACfxC,IAAI,CAACyC,aAAa,CAAC,CAAC;IACpBjC,iBAAiB,CAACkC,iBAAiB,CAAC1B,cAAc,CAAC,CAAC,CAAC;IACrDL,wBAAwB,CAAC+B,iBAAiB,CAAC,EAAE,CAAC;IAC9C9B,8BAA8B,CAAC8B,iBAAiB,CAAC,EAAE,CAAC;EACtD,CAAC,CAAC;EAEFC,EAAE,CAAC,qEAAqE,EAAE,YAAY;IAAA,IAAAC,oBAAA;IACpF,MAAMC,MAAM,GAAG,IAAAC,oCAAqB,EAAC;MAAER;IAAW,CAAC,CAAC;IAEpD,MAAM;MAAES,MAAM;MAAEC,OAAO;MAAEC;IAAa,CAAC,GAAG,MAAMJ,MAAM,CAAChC,aAAa,CAAC;IAErEqC,MAAM,CAAC1C,iBAAiB,CAAC,CAAC2C,oBAAoB,CAACtC,aAAa,EAAE;MAC5DuC,6BAA6B,EAAE;IACjC,CAAC,CAAC;IACFF,MAAM,CAACH,MAAM,CAACM,EAAE,CAAC,CAACC,IAAI,CAACzC,aAAa,CAAC;IACrCqC,MAAM,CAACH,MAAM,CAAC5B,YAAY,CAAC,CAACmC,IAAI,CAAC,OAAO,CAAC;IACzCJ,MAAM,EAAAN,oBAAA,GAACG,MAAM,CAACnB,MAAM,CAAC2B,KAAK,qBAAnBX,oBAAA,CAAqBd,IAAI,CAAC,CAACwB,IAAI,CAAC,YAAY,CAAC;IACpDJ,MAAM,CAAC,OAAOF,OAAO,CAACQ,IAAI,CAAC,CAACF,IAAI,CAAC,UAAU,CAAC;IAC5CJ,MAAM,CAAC,OAAOF,OAAO,CAACS,GAAG,CAAC,CAACH,IAAI,CAAC,UAAU,CAAC;IAC3CJ,MAAM,CAAC,QAAOD,YAAY,oBAAZA,YAAY,CAAES,QAAQ,EAAC,CAACJ,IAAI,CAAC,UAAU,CAAC;EACxD,CAAC,CAAC;EAEFX,EAAE,CAAC,oDAAoD,EAAE,YAAY;IACnE,MAAME,MAAM,GAAG,IAAAC,oCAAqB,EAAC;MAAER;IAAW,CAAC,CAAC;IAEpD,MAAM;MAAES;IAAO,CAAC,GAAG,MAAMF,MAAM,CAAChC,aAAa,CAAC;IAE9CqC,MAAM,CAACvC,wBAAwB,CAAC,CAACgD,GAAG,CAACC,gBAAgB,CAAC,CAAC;IACvDV,MAAM,CAACH,MAAM,CAACc,iBAAiB,CAAC,CAACC,OAAO,CAAC;MACvCC,WAAW,EAAE,KAAK;MAClBC,WAAW,EAAE,KAAK;MAClBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ,CAAC,CAAC;EAEFtB,EAAE,CAAC,+EAA+E,EAAE,YAAY;IAC9FhC,wBAAwB,CAAC+B,iBAAiB,CAAC3B,4BAA4B,CAAC;IACxE,MAAM8B,MAAM,GAAG,IAAAC,oCAAqB,EAAC;MACnCR,UAAU;MACV4B,sBAAsB,EAAE,IAAI;MAC5BC,UAAU,EAAErD;IACd,CAAC,CAAC;IAEF,MAAM;MAAEiC;IAAO,CAAC,GAAG,MAAMF,MAAM,CAAChC,aAAa,CAAC;IAE9CqC,MAAM,CAACvC,wBAAwB,CAAC,CAACwC,oBAAoB,CAACrC,WAAW,CAAC;IAClEoC,MAAM,CAACH,MAAM,CAACc,iBAAiB,CAAC,CAACC,OAAO,CAAC;MACvCC,WAAW,EAAE,IAAI;MACjBC,WAAW,EAAE,IAAI;MACjBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ,CAAC,CAAC;EAEFtB,EAAE,CAAC,qDAAqD,EAAE,YAAY;IACpE,MAAME,MAAM,GAAG,IAAAC,oCAAqB,EAAC;MACnCR,UAAU;MACV4B,sBAAsB,EAAE;IAC1B,CAAC,CAAC;IAEF,MAAMrB,MAAM,CAAChC,aAAa,CAAC;IAE3BqC,MAAM,CAACvC,wBAAwB,CAAC,CAACgD,GAAG,CAACC,gBAAgB,CAAC,CAAC;EACzD,CAAC,CAAC;EAEFjB,EAAE,CAAC,oDAAoD,EAAE,YAAY;IACnE,MAAME,MAAM,GAAG,IAAAC,oCAAqB,EAAC;MACnCR,UAAU;MACV8B,eAAe,EAAErD;IACnB,CAAC,CAAC;IAEF,MAAM;MAAEgC;IAAO,CAAC,GAAG,MAAMF,MAAM,CAAChC,aAAa,CAAC;IAE9CqC,MAAM,CAACvC,wBAAwB,CAAC,CAACgD,GAAG,CAACC,gBAAgB,CAAC,CAAC;IACvDV,MAAM,CAACH,MAAM,CAACc,iBAAiB,CAAC,CAACC,OAAO,CAAC;MACvCC,WAAW,EAAE,IAAI;MACjBC,WAAW,EAAE,IAAI;MACjBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ,CAAC,CAAC;EAEFtB,EAAE,CAAC,gEAAgE,EAAE,YAAY;IAC/EhC,wBAAwB,CAAC0D,iBAAiB,CAAC,IAAIC,KAAK,CAAC,YAAY,CAAC,CAAC;IACnE1D,8BAA8B,CAACyD,iBAAiB,CAC9C,IAAIC,KAAK,CAAC,kBAAkB,CAC9B,CAAC;IACD,MAAMzB,MAAM,GAAG,IAAAC,oCAAqB,EAAC;MACnCR,UAAU;MACV4B,sBAAsB,EAAE,IAAI;MAC5BC,UAAU,EAAErD;IACd,CAAC,CAAC;IAEF,MAAM;MAAEiC;IAAO,CAAC,GAAG,MAAMF,MAAM,CAAChC,aAAa,CAAC;IAE9CqC,MAAM,CAACH,MAAM,CAACM,EAAE,CAAC,CAACC,IAAI,CAACzC,aAAa,CAAC;IACrC;IACAqC,MAAM,CAACH,MAAM,CAACc,iBAAiB,CAAC,CAACC,OAAO,CAAC;MACvCC,WAAW,EAAE,KAAK;MAClBC,WAAW,EAAE,KAAK;MAClBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+
3
+ var _data = require("@wix/data");
4
+ var _searchUtils = require("../searchUtils");
5
+ var _wixDataQueryRecorder = require("./wixDataQueryRecorder");
6
+ jest.mock('@wix/data', () => {
7
+ const recorder = require('./wixDataQueryRecorder');
8
+ return {
9
+ items: {
10
+ query: jest.fn(() => recorder.createQueryRecorder()),
11
+ filter: jest.fn(() => recorder.createQueryRecorder())
12
+ }
13
+ };
14
+ });
15
+ const makeQuery = search => ({
16
+ search
17
+ });
18
+ const textField = id => ({
19
+ id,
20
+ type: 'SHORT_TEXT',
21
+ displayName: id,
22
+ capabilities: {
23
+ supportedQueryOperators: [],
24
+ sortable: true
25
+ }
26
+ });
27
+ const numberField = id => ({
28
+ id,
29
+ type: 'NUMBER',
30
+ displayName: id,
31
+ capabilities: {
32
+ supportedQueryOperators: [],
33
+ sortable: true
34
+ }
35
+ });
36
+
37
+ /** Recursively collect every `contains` arg pair across a recorder and any nested filter recorders. */
38
+ const collectContains = recorder => {
39
+ const direct = recorder.calls.filter(c => c.method === 'contains').map(c => c.args);
40
+ const nested = recorder.calls.filter(c => c.method === 'or' || c.method === 'and').flatMap(c => c.args.filter(a => !!a && Array.isArray(a.calls)).flatMap(collectContains));
41
+ return [...direct, ...nested];
42
+ };
43
+ describe('addSearchToDataQuery', () => {
44
+ beforeEach(() => {
45
+ jest.clearAllMocks();
46
+ });
47
+ it('applies a contains filter over a searchable text field', () => {
48
+ const dataQuery = _data.items.query('collectionId');
49
+ (0, _searchUtils.addSearchToDataQuery)({
50
+ dataQuery: dataQuery,
51
+ query: makeQuery('test'),
52
+ fields: {
53
+ shortTextField: textField('shortTextField'),
54
+ nonShortTextField: numberField('nonShortTextField')
55
+ },
56
+ searchableFieldIds: ['shortTextField', 'nonShortTextField']
57
+ });
58
+
59
+ // The search filter is attached to the data query via .and(...).
60
+ const andArgs = (0, _wixDataQueryRecorder.firstCallArgs)(dataQuery, 'and');
61
+ expect(andArgs).toBeDefined();
62
+ const searchFilter = andArgs[0];
63
+ const containsPairs = collectContains(searchFilter);
64
+ // Only the text field is searched — the NUMBER field is ignored.
65
+ expect(containsPairs).toEqual([['shortTextField', 'test']]);
66
+ });
67
+ it('ignores non-text fields even when listed in searchableFieldIds', () => {
68
+ const dataQuery = _data.items.query('collectionId');
69
+ (0, _searchUtils.addSearchToDataQuery)({
70
+ dataQuery: dataQuery,
71
+ query: makeQuery('test'),
72
+ fields: {
73
+ shortTextField: textField('shortTextField'),
74
+ nonShortTextField: numberField('nonShortTextField')
75
+ },
76
+ searchableFieldIds: ['nonShortTextField']
77
+ });
78
+
79
+ // No text field is searchable → no .and() filter is attached.
80
+ expect((0, _wixDataQueryRecorder.wasCalled)(dataQuery, 'and')).toBe(false);
81
+ });
82
+ it('ORs a contains filter for each searchable text field', () => {
83
+ const dataQuery = _data.items.query('collectionId');
84
+ (0, _searchUtils.addSearchToDataQuery)({
85
+ dataQuery: dataQuery,
86
+ query: makeQuery('test'),
87
+ fields: {
88
+ ShortTextField1: textField('ShortTextField1'),
89
+ ShortTextField2: textField('ShortTextField2')
90
+ },
91
+ searchableFieldIds: ['ShortTextField1', 'ShortTextField2']
92
+ });
93
+ const andArgs = (0, _wixDataQueryRecorder.firstCallArgs)(dataQuery, 'and');
94
+ expect(andArgs).toBeDefined();
95
+ const searchFilter = andArgs[0];
96
+
97
+ // The two field filters are combined with .or(...).
98
+ expect((0, _wixDataQueryRecorder.wasCalled)(searchFilter, 'or')).toBe(true);
99
+ const containsPairs = collectContains(searchFilter);
100
+ expect(containsPairs).toEqual(expect.arrayContaining([['ShortTextField1', 'test'], ['ShortTextField2', 'test']]));
101
+ expect(containsPairs).toHaveLength(2);
102
+ });
103
+ it('does nothing for an empty search term', () => {
104
+ const dataQuery = _data.items.query('collectionId');
105
+ (0, _searchUtils.addSearchToDataQuery)({
106
+ dataQuery: dataQuery,
107
+ query: makeQuery(''),
108
+ fields: {
109
+ shortTextField: textField('shortTextField')
110
+ },
111
+ searchableFieldIds: ['shortTextField']
112
+ });
113
+ expect(dataQuery.calls).toHaveLength(0);
114
+ });
115
+ });
116
+ //# sourceMappingURL=searchUtils.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_data","require","_searchUtils","_wixDataQueryRecorder","jest","mock","recorder","items","query","fn","createQueryRecorder","filter","makeQuery","search","textField","id","type","displayName","capabilities","supportedQueryOperators","sortable","numberField","collectContains","direct","calls","c","method","map","args","nested","flatMap","a","Array","isArray","describe","beforeEach","clearAllMocks","it","dataQuery","addSearchToDataQuery","fields","shortTextField","nonShortTextField","searchableFieldIds","andArgs","firstCallArgs","expect","toBeDefined","searchFilter","containsPairs","toEqual","wasCalled","toBe","ShortTextField1","ShortTextField2","arrayContaining","toHaveLength"],"sources":["../../../../src/adapter/__tests__/searchUtils.spec.ts"],"sourcesContent":["import { items } from '@wix/data';\nimport type { OffsetQuery, Schema } from '@wix/bex-core';\nimport { addSearchToDataQuery } from '../searchUtils';\nimport {\n firstCallArgs,\n wasCalled,\n type QueryRecorder,\n} from './wixDataQueryRecorder';\n\njest.mock('@wix/data', () => {\n const recorder = require('./wixDataQueryRecorder');\n return {\n items: {\n query: jest.fn(() => recorder.createQueryRecorder()),\n filter: jest.fn(() => recorder.createQueryRecorder()),\n },\n };\n});\n\ntype SchemaFields = Schema['fields'];\n\nconst makeQuery = (search: string): OffsetQuery =>\n ({ search } as unknown as OffsetQuery);\n\nconst textField = (id: string): SchemaFields[string] => ({\n id,\n type: 'SHORT_TEXT',\n displayName: id,\n capabilities: { supportedQueryOperators: [], sortable: true },\n});\n\nconst numberField = (id: string): SchemaFields[string] => ({\n id,\n type: 'NUMBER',\n displayName: id,\n capabilities: { supportedQueryOperators: [], sortable: true },\n});\n\n/** Recursively collect every `contains` arg pair across a recorder and any nested filter recorders. */\nconst collectContains = (recorder: QueryRecorder): unknown[][] => {\n const direct = recorder.calls\n .filter((c) => c.method === 'contains')\n .map((c) => c.args);\n const nested = recorder.calls\n .filter((c) => c.method === 'or' || c.method === 'and')\n .flatMap((c) =>\n c.args\n .filter(\n (a): a is QueryRecorder =>\n !!a && Array.isArray((a as QueryRecorder).calls),\n )\n .flatMap(collectContains),\n );\n return [...direct, ...nested];\n};\n\ndescribe('addSearchToDataQuery', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n });\n\n it('applies a contains filter over a searchable text field', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSearchToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery('test'),\n fields: {\n shortTextField: textField('shortTextField'),\n nonShortTextField: numberField('nonShortTextField'),\n },\n searchableFieldIds: ['shortTextField', 'nonShortTextField'],\n });\n\n // The search filter is attached to the data query via .and(...).\n const andArgs = firstCallArgs(dataQuery, 'and');\n expect(andArgs).toBeDefined();\n const searchFilter = andArgs![0] as QueryRecorder;\n\n const containsPairs = collectContains(searchFilter);\n // Only the text field is searched — the NUMBER field is ignored.\n expect(containsPairs).toEqual([['shortTextField', 'test']]);\n });\n\n it('ignores non-text fields even when listed in searchableFieldIds', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSearchToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery('test'),\n fields: {\n shortTextField: textField('shortTextField'),\n nonShortTextField: numberField('nonShortTextField'),\n },\n searchableFieldIds: ['nonShortTextField'],\n });\n\n // No text field is searchable → no .and() filter is attached.\n expect(wasCalled(dataQuery, 'and')).toBe(false);\n });\n\n it('ORs a contains filter for each searchable text field', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSearchToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery('test'),\n fields: {\n ShortTextField1: textField('ShortTextField1'),\n ShortTextField2: textField('ShortTextField2'),\n },\n searchableFieldIds: ['ShortTextField1', 'ShortTextField2'],\n });\n\n const andArgs = firstCallArgs(dataQuery, 'and');\n expect(andArgs).toBeDefined();\n const searchFilter = andArgs![0] as QueryRecorder;\n\n // The two field filters are combined with .or(...).\n expect(wasCalled(searchFilter, 'or')).toBe(true);\n\n const containsPairs = collectContains(searchFilter);\n expect(containsPairs).toEqual(\n expect.arrayContaining([\n ['ShortTextField1', 'test'],\n ['ShortTextField2', 'test'],\n ]),\n );\n expect(containsPairs).toHaveLength(2);\n });\n\n it('does nothing for an empty search term', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSearchToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery(''),\n fields: { shortTextField: textField('shortTextField') },\n searchableFieldIds: ['shortTextField'],\n });\n\n expect(dataQuery.calls).toHaveLength(0);\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ var _data = require("@wix/data");
4
+ var _sortUtils = require("../sortUtils");
5
+ var _wixDataQueryRecorder = require("./wixDataQueryRecorder");
6
+ jest.mock('@wix/data', () => {
7
+ const recorder = require('./wixDataQueryRecorder');
8
+ return {
9
+ items: {
10
+ query: jest.fn(() => recorder.createQueryRecorder()),
11
+ filter: jest.fn(() => recorder.createQueryRecorder())
12
+ }
13
+ };
14
+ });
15
+ const makeQuery = sort => ({
16
+ sort
17
+ });
18
+ const sortableField = (id, sortable = true) => ({
19
+ id,
20
+ type: 'NUMBER',
21
+ displayName: id,
22
+ capabilities: {
23
+ supportedQueryOperators: [],
24
+ sortable
25
+ }
26
+ });
27
+ describe('addSortToDataQuery', () => {
28
+ beforeEach(() => {
29
+ jest.clearAllMocks();
30
+ });
31
+ it('applies .ascending for an asc sort on a sortable field', () => {
32
+ const dataQuery = _data.items.query('collectionId');
33
+ (0, _sortUtils.addSortToDataQuery)({
34
+ dataQuery: dataQuery,
35
+ query: makeQuery([{
36
+ fieldName: 'numberField',
37
+ order: 'asc'
38
+ }]),
39
+ fields: {
40
+ numberField: sortableField('numberField')
41
+ }
42
+ });
43
+ expect((0, _wixDataQueryRecorder.firstCallArgs)(dataQuery, 'ascending')).toEqual(['numberField']);
44
+ expect((0, _wixDataQueryRecorder.wasCalled)(dataQuery, 'descending')).toBe(false);
45
+ });
46
+ it('applies .descending for a desc sort on a sortable field', () => {
47
+ const dataQuery = _data.items.query('collectionId');
48
+ (0, _sortUtils.addSortToDataQuery)({
49
+ dataQuery: dataQuery,
50
+ query: makeQuery([{
51
+ fieldName: 'numberField',
52
+ order: 'desc'
53
+ }]),
54
+ fields: {
55
+ numberField: sortableField('numberField')
56
+ }
57
+ });
58
+ expect((0, _wixDataQueryRecorder.firstCallArgs)(dataQuery, 'descending')).toEqual(['numberField']);
59
+ expect((0, _wixDataQueryRecorder.wasCalled)(dataQuery, 'ascending')).toBe(false);
60
+ });
61
+ it('ignores sorts on non-sortable fields', () => {
62
+ const dataQuery = _data.items.query('collectionId');
63
+ (0, _sortUtils.addSortToDataQuery)({
64
+ dataQuery: dataQuery,
65
+ query: makeQuery([{
66
+ fieldName: 'numberField',
67
+ order: 'asc'
68
+ }]),
69
+ fields: {
70
+ numberField: sortableField('numberField', false)
71
+ }
72
+ });
73
+ expect(dataQuery.calls).toHaveLength(0);
74
+ });
75
+ it('applies multiple sort fields in order', () => {
76
+ const dataQuery = _data.items.query('collectionId');
77
+ (0, _sortUtils.addSortToDataQuery)({
78
+ dataQuery: dataQuery,
79
+ query: makeQuery([{
80
+ fieldName: 'numberField',
81
+ order: 'asc'
82
+ }, {
83
+ fieldName: 'shortTextField',
84
+ order: 'desc'
85
+ }]),
86
+ fields: {
87
+ numberField: sortableField('numberField'),
88
+ shortTextField: {
89
+ id: 'shortTextField',
90
+ type: 'SHORT_TEXT',
91
+ displayName: 'shortTextField',
92
+ capabilities: {
93
+ supportedQueryOperators: [],
94
+ sortable: true
95
+ }
96
+ }
97
+ }
98
+ });
99
+ expect((0, _wixDataQueryRecorder.calledMethods)(dataQuery)).toEqual(['ascending', 'descending']);
100
+ expect((0, _wixDataQueryRecorder.firstCallArgs)(dataQuery, 'ascending')).toEqual(['numberField']);
101
+ expect((0, _wixDataQueryRecorder.firstCallArgs)(dataQuery, 'descending')).toEqual(['shortTextField']);
102
+ });
103
+ it('ignores a sort whose field is not in the schema', () => {
104
+ const dataQuery = _data.items.query('collectionId');
105
+ (0, _sortUtils.addSortToDataQuery)({
106
+ dataQuery: dataQuery,
107
+ query: makeQuery([{
108
+ fieldName: 'unknownField',
109
+ order: 'asc'
110
+ }]),
111
+ fields: {
112
+ numberField: sortableField('numberField')
113
+ }
114
+ });
115
+ expect(dataQuery.calls).toHaveLength(0);
116
+ });
117
+ });
118
+ //# sourceMappingURL=sortUtils.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_data","require","_sortUtils","_wixDataQueryRecorder","jest","mock","recorder","items","query","fn","createQueryRecorder","filter","makeQuery","sort","sortableField","id","sortable","type","displayName","capabilities","supportedQueryOperators","describe","beforeEach","clearAllMocks","it","dataQuery","addSortToDataQuery","fieldName","order","fields","numberField","expect","firstCallArgs","toEqual","wasCalled","toBe","calls","toHaveLength","shortTextField","calledMethods"],"sources":["../../../../src/adapter/__tests__/sortUtils.spec.ts"],"sourcesContent":["import { items } from '@wix/data';\nimport type { OffsetQuery, Schema } from '@wix/bex-core';\nimport { addSortToDataQuery } from '../sortUtils';\nimport {\n calledMethods,\n firstCallArgs,\n wasCalled,\n type QueryRecorder,\n} from './wixDataQueryRecorder';\n\njest.mock('@wix/data', () => {\n const recorder = require('./wixDataQueryRecorder');\n return {\n items: {\n query: jest.fn(() => recorder.createQueryRecorder()),\n filter: jest.fn(() => recorder.createQueryRecorder()),\n },\n };\n});\n\ntype SchemaFields = Schema['fields'];\n\nconst makeQuery = (\n sort: { fieldName: string; order: 'asc' | 'desc' }[],\n): OffsetQuery => ({ sort } as unknown as OffsetQuery);\n\nconst sortableField = (id: string, sortable = true): SchemaFields[string] => ({\n id,\n type: 'NUMBER',\n displayName: id,\n capabilities: { supportedQueryOperators: [], sortable },\n});\n\ndescribe('addSortToDataQuery', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n });\n\n it('applies .ascending for an asc sort on a sortable field', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSortToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery([{ fieldName: 'numberField', order: 'asc' }]),\n fields: { numberField: sortableField('numberField') },\n });\n\n expect(firstCallArgs(dataQuery, 'ascending')).toEqual(['numberField']);\n expect(wasCalled(dataQuery, 'descending')).toBe(false);\n });\n\n it('applies .descending for a desc sort on a sortable field', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSortToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery([{ fieldName: 'numberField', order: 'desc' }]),\n fields: { numberField: sortableField('numberField') },\n });\n\n expect(firstCallArgs(dataQuery, 'descending')).toEqual(['numberField']);\n expect(wasCalled(dataQuery, 'ascending')).toBe(false);\n });\n\n it('ignores sorts on non-sortable fields', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSortToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery([{ fieldName: 'numberField', order: 'asc' }]),\n fields: { numberField: sortableField('numberField', false) },\n });\n\n expect(dataQuery.calls).toHaveLength(0);\n });\n\n it('applies multiple sort fields in order', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSortToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery([\n { fieldName: 'numberField', order: 'asc' },\n { fieldName: 'shortTextField', order: 'desc' },\n ]),\n fields: {\n numberField: sortableField('numberField'),\n shortTextField: {\n id: 'shortTextField',\n type: 'SHORT_TEXT',\n displayName: 'shortTextField',\n capabilities: { supportedQueryOperators: [], sortable: true },\n },\n },\n });\n\n expect(calledMethods(dataQuery)).toEqual(['ascending', 'descending']);\n expect(firstCallArgs(dataQuery, 'ascending')).toEqual(['numberField']);\n expect(firstCallArgs(dataQuery, 'descending')).toEqual(['shortTextField']);\n });\n\n it('ignores a sort whose field is not in the schema', () => {\n const dataQuery = items.query('collectionId') as unknown as QueryRecorder;\n\n addSortToDataQuery({\n dataQuery: dataQuery as never,\n query: makeQuery([{ fieldName: 'unknownField', order: 'asc' }]),\n fields: { numberField: sortableField('numberField') },\n });\n\n expect(dataQuery.calls).toHaveLength(0);\n });\n});\n"],"mappings":"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","ignoreList":[]}