@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.
- package/dist/cjs/adapter/__tests__/cmsFieldActions.spec.js +436 -0
- package/dist/cjs/adapter/__tests__/cmsFieldActions.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/cmsPermissions.spec.js +175 -0
- package/dist/cjs/adapter/__tests__/cmsPermissions.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/createCmsBackend.spec.js +440 -0
- package/dist/cjs/adapter/__tests__/createCmsBackend.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/filterUtils.spec.js +426 -0
- package/dist/cjs/adapter/__tests__/filterUtils.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/getFieldKey.spec.js +24 -0
- package/dist/cjs/adapter/__tests__/getFieldKey.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/loadCmsSchema.spec.js +166 -0
- package/dist/cjs/adapter/__tests__/loadCmsSchema.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/searchUtils.spec.js +116 -0
- package/dist/cjs/adapter/__tests__/searchUtils.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/sortUtils.spec.js +118 -0
- package/dist/cjs/adapter/__tests__/sortUtils.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/transformCmsSchema.spec.js +210 -0
- package/dist/cjs/adapter/__tests__/transformCmsSchema.spec.js.map +1 -0
- package/dist/cjs/adapter/__tests__/wixDataQueryRecorder.js +54 -0
- package/dist/cjs/adapter/__tests__/wixDataQueryRecorder.js.map +1 -0
- package/dist/cjs/adapter/cmsBackup.js +52 -0
- package/dist/cjs/adapter/cmsBackup.js.map +1 -0
- package/dist/cjs/adapter/cmsFieldTypeMap.js +43 -0
- package/dist/cjs/adapter/cmsFieldTypeMap.js.map +1 -0
- package/dist/cjs/adapter/cmsPermissions.js +94 -0
- package/dist/cjs/adapter/cmsPermissions.js.map +1 -0
- package/dist/cjs/adapter/constants.js +20 -0
- package/dist/cjs/adapter/constants.js.map +1 -0
- package/dist/cjs/adapter/createCmsBackend.js +131 -0
- package/dist/cjs/adapter/createCmsBackend.js.map +1 -0
- package/dist/cjs/adapter/createCmsFieldActions.js +182 -0
- package/dist/cjs/adapter/createCmsFieldActions.js.map +1 -0
- package/dist/cjs/adapter/fetchExternalDbConnections.js +24 -0
- package/dist/cjs/adapter/fetchExternalDbConnections.js.map +1 -0
- package/dist/cjs/adapter/fetchUserPermissions.js +24 -0
- package/dist/cjs/adapter/fetchUserPermissions.js.map +1 -0
- package/dist/cjs/adapter/filterUtils.js +128 -0
- package/dist/cjs/adapter/filterUtils.js.map +1 -0
- package/dist/cjs/adapter/getFieldKey.js +19 -0
- package/dist/cjs/adapter/getFieldKey.js.map +1 -0
- package/dist/cjs/adapter/index.js +36 -0
- package/dist/cjs/adapter/index.js.map +1 -0
- package/dist/cjs/adapter/loadCmsSchema.js +51 -0
- package/dist/cjs/adapter/loadCmsSchema.js.map +1 -0
- package/dist/cjs/adapter/pollUntilReady.js +30 -0
- package/dist/cjs/adapter/pollUntilReady.js.map +1 -0
- package/dist/cjs/adapter/searchUtils.js +32 -0
- package/dist/cjs/adapter/searchUtils.js.map +1 -0
- package/dist/cjs/adapter/sortUtils.js +34 -0
- package/dist/cjs/adapter/sortUtils.js.map +1 -0
- package/dist/cjs/adapter/transformCmsSchema.js +75 -0
- package/dist/cjs/adapter/transformCmsSchema.js.map +1 -0
- package/dist/cjs/index.js +10 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/adapter/__tests__/cmsFieldActions.spec.js +335 -0
- package/dist/esm/adapter/__tests__/cmsFieldActions.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/cmsPermissions.spec.js +173 -0
- package/dist/esm/adapter/__tests__/cmsPermissions.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/createCmsBackend.spec.js +307 -0
- package/dist/esm/adapter/__tests__/createCmsBackend.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/filterUtils.spec.js +298 -0
- package/dist/esm/adapter/__tests__/filterUtils.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/getFieldKey.spec.js +22 -0
- package/dist/esm/adapter/__tests__/getFieldKey.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/loadCmsSchema.spec.js +147 -0
- package/dist/esm/adapter/__tests__/loadCmsSchema.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/searchUtils.spec.js +109 -0
- package/dist/esm/adapter/__tests__/searchUtils.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/sortUtils.spec.js +85 -0
- package/dist/esm/adapter/__tests__/sortUtils.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/transformCmsSchema.spec.js +201 -0
- package/dist/esm/adapter/__tests__/transformCmsSchema.spec.js.map +1 -0
- package/dist/esm/adapter/__tests__/wixDataQueryRecorder.js +42 -0
- package/dist/esm/adapter/__tests__/wixDataQueryRecorder.js.map +1 -0
- package/dist/esm/adapter/cmsBackup.js +34 -0
- package/dist/esm/adapter/cmsBackup.js.map +1 -0
- package/dist/esm/adapter/cmsFieldTypeMap.js +37 -0
- package/dist/esm/adapter/cmsFieldTypeMap.js.map +1 -0
- package/dist/esm/adapter/cmsPermissions.js +91 -0
- package/dist/esm/adapter/cmsPermissions.js.map +1 -0
- package/dist/esm/adapter/constants.js +25 -0
- package/dist/esm/adapter/constants.js.map +1 -0
- package/dist/esm/adapter/createCmsBackend.js +113 -0
- package/dist/esm/adapter/createCmsBackend.js.map +1 -0
- package/dist/esm/adapter/createCmsFieldActions.js +159 -0
- package/dist/esm/adapter/createCmsFieldActions.js.map +1 -0
- package/dist/esm/adapter/fetchExternalDbConnections.js +17 -0
- package/dist/esm/adapter/fetchExternalDbConnections.js.map +1 -0
- package/dist/esm/adapter/fetchUserPermissions.js +15 -0
- package/dist/esm/adapter/fetchUserPermissions.js.map +1 -0
- package/dist/esm/adapter/filterUtils.js +126 -0
- package/dist/esm/adapter/filterUtils.js.map +1 -0
- package/dist/esm/adapter/getFieldKey.js +13 -0
- package/dist/esm/adapter/getFieldKey.js.map +1 -0
- package/dist/esm/adapter/index.js +15 -0
- package/dist/esm/adapter/index.js.map +1 -0
- package/dist/esm/adapter/loadCmsSchema.js +48 -0
- package/dist/esm/adapter/loadCmsSchema.js.map +1 -0
- package/dist/esm/adapter/pollUntilReady.js +24 -0
- package/dist/esm/adapter/pollUntilReady.js.map +1 -0
- package/dist/esm/adapter/searchUtils.js +24 -0
- package/dist/esm/adapter/searchUtils.js.map +1 -0
- package/dist/esm/adapter/sortUtils.js +21 -0
- package/dist/esm/adapter/sortUtils.js.map +1 -0
- package/dist/esm/adapter/transformCmsSchema.js +70 -0
- package/dist/esm/adapter/transformCmsSchema.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/types/adapter/__tests__/cmsFieldActions.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/cmsFieldActions.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/cmsPermissions.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/cmsPermissions.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/createCmsBackend.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/createCmsBackend.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/filterUtils.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/filterUtils.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/getFieldKey.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/getFieldKey.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/loadCmsSchema.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/loadCmsSchema.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/searchUtils.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/searchUtils.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/sortUtils.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/sortUtils.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/transformCmsSchema.spec.d.ts +2 -0
- package/dist/types/adapter/__tests__/transformCmsSchema.spec.d.ts.map +1 -0
- package/dist/types/adapter/__tests__/wixDataQueryRecorder.d.ts +40 -0
- package/dist/types/adapter/__tests__/wixDataQueryRecorder.d.ts.map +1 -0
- package/dist/types/adapter/cmsBackup.d.ts +7 -0
- package/dist/types/adapter/cmsBackup.d.ts.map +1 -0
- package/dist/types/adapter/cmsFieldTypeMap.d.ts +8 -0
- package/dist/types/adapter/cmsFieldTypeMap.d.ts.map +1 -0
- package/dist/types/adapter/cmsPermissions.d.ts +21 -0
- package/dist/types/adapter/cmsPermissions.d.ts.map +1 -0
- package/dist/types/adapter/constants.d.ts +14 -0
- package/dist/types/adapter/constants.d.ts.map +1 -0
- package/dist/types/adapter/createCmsBackend.d.ts +9 -0
- package/dist/types/adapter/createCmsBackend.d.ts.map +1 -0
- package/dist/types/adapter/createCmsFieldActions.d.ts +8 -0
- package/dist/types/adapter/createCmsFieldActions.d.ts.map +1 -0
- package/dist/types/adapter/fetchExternalDbConnections.d.ts +11 -0
- package/dist/types/adapter/fetchExternalDbConnections.d.ts.map +1 -0
- package/dist/types/adapter/fetchUserPermissions.d.ts +7 -0
- package/dist/types/adapter/fetchUserPermissions.d.ts.map +1 -0
- package/dist/types/adapter/filterUtils.d.ts +14 -0
- package/dist/types/adapter/filterUtils.d.ts.map +1 -0
- package/dist/types/adapter/getFieldKey.d.ts +3 -0
- package/dist/types/adapter/getFieldKey.d.ts.map +1 -0
- package/dist/types/adapter/index.d.ts +15 -0
- package/dist/types/adapter/index.d.ts.map +1 -0
- package/dist/types/adapter/loadCmsSchema.d.ts +29 -0
- package/dist/types/adapter/loadCmsSchema.d.ts.map +1 -0
- package/dist/types/adapter/pollUntilReady.d.ts +11 -0
- package/dist/types/adapter/pollUntilReady.d.ts.map +1 -0
- package/dist/types/adapter/searchUtils.d.ts +12 -0
- package/dist/types/adapter/searchUtils.d.ts.map +1 -0
- package/dist/types/adapter/sortUtils.d.ts +11 -0
- package/dist/types/adapter/sortUtils.d.ts.map +1 -0
- package/dist/types/adapter/transformCmsSchema.d.ts +12 -0
- package/dist/types/adapter/transformCmsSchema.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- 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":"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","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":[]}
|