@strapi/strapi 4.10.0 → 4.10.1
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/coverage/clover.xml +1613 -0
- package/coverage/coverage-final.json +48 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/commands/__tests__/data-transfer/shared/index.html +116 -0
- package/coverage/lcov-report/commands/__tests__/data-transfer/shared/transfer.test.utils.js.html +133 -0
- package/coverage/lcov-report/commands/admin-create.js.html +424 -0
- package/coverage/lcov-report/commands/admin-reset.js.html +241 -0
- package/coverage/lcov-report/commands/generate-template.js.html +373 -0
- package/coverage/lcov-report/commands/index.html +146 -0
- package/coverage/lcov-report/commands/transfer/export.js.html +619 -0
- package/coverage/lcov-report/commands/transfer/import.js.html +562 -0
- package/coverage/lcov-report/commands/transfer/index.html +146 -0
- package/coverage/lcov-report/commands/transfer/transfer.js.html +532 -0
- package/coverage/lcov-report/commands/utils/helpers.js.html +430 -0
- package/coverage/lcov-report/commands/utils/index.html +116 -0
- package/coverage/lcov-report/core/registries/custom-fields.js.html +301 -0
- package/coverage/lcov-report/core/registries/index.html +116 -0
- package/coverage/lcov-report/core-api/controller/collection-type.js.html +418 -0
- package/coverage/lcov-report/core-api/controller/index.html +161 -0
- package/coverage/lcov-report/core-api/controller/index.js.html +220 -0
- package/coverage/lcov-report/core-api/controller/single-type.js.html +274 -0
- package/coverage/lcov-report/core-api/controller/transform.js.html +376 -0
- package/coverage/lcov-report/core-api/service/collection-type.js.html +325 -0
- package/coverage/lcov-report/core-api/service/index.html +161 -0
- package/coverage/lcov-report/core-api/service/index.js.html +220 -0
- package/coverage/lcov-report/core-api/service/pagination.js.html +460 -0
- package/coverage/lcov-report/core-api/service/single-type.js.html +301 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +386 -0
- package/coverage/lcov-report/load/filepath-to-prop-path.js.html +151 -0
- package/coverage/lcov-report/load/index.html +116 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/services/content-api/index.html +116 -0
- package/coverage/lcov-report/services/content-api/index.js.html +307 -0
- package/coverage/lcov-report/services/content-api/permissions/engine.js.html +100 -0
- package/coverage/lcov-report/services/content-api/permissions/index.html +131 -0
- package/coverage/lcov-report/services/content-api/permissions/index.js.html +529 -0
- package/coverage/lcov-report/services/content-api/permissions/providers/action.js.html +142 -0
- package/coverage/lcov-report/services/content-api/permissions/providers/condition.js.html +142 -0
- package/coverage/lcov-report/services/content-api/permissions/providers/index.html +146 -0
- package/coverage/lcov-report/services/content-api/permissions/providers/index.js.html +112 -0
- package/coverage/lcov-report/services/core-store.js.html +520 -0
- package/coverage/lcov-report/services/entity-service/attributes/index.html +131 -0
- package/coverage/lcov-report/services/entity-service/attributes/index.js.html +178 -0
- package/coverage/lcov-report/services/entity-service/attributes/transforms.js.html +145 -0
- package/coverage/lcov-report/services/entity-service/components.js.html +1246 -0
- package/coverage/lcov-report/services/entity-service/index.html +146 -0
- package/coverage/lcov-report/services/entity-service/index.js.html +1120 -0
- package/coverage/lcov-report/services/entity-service/params.js.html +112 -0
- package/coverage/lcov-report/services/entity-validator/__tests__/relations/utils/index.html +116 -0
- package/coverage/lcov-report/services/entity-validator/__tests__/relations/utils/relations.testdata.js.html +544 -0
- package/coverage/lcov-report/services/entity-validator/index.html +131 -0
- package/coverage/lcov-report/services/entity-validator/index.js.html +1231 -0
- package/coverage/lcov-report/services/entity-validator/validators.js.html +733 -0
- package/coverage/lcov-report/services/event-hub.js.html +319 -0
- package/coverage/lcov-report/services/fs.js.html +259 -0
- package/coverage/lcov-report/services/index.html +161 -0
- package/coverage/lcov-report/services/metrics/admin-user-hash.js.html +148 -0
- package/coverage/lcov-report/services/metrics/index.html +206 -0
- package/coverage/lcov-report/services/metrics/index.js.html +265 -0
- package/coverage/lcov-report/services/metrics/is-truthy.js.html +112 -0
- package/coverage/lcov-report/services/metrics/middleware.js.html +184 -0
- package/coverage/lcov-report/services/metrics/rate-limiter.js.html +166 -0
- package/coverage/lcov-report/services/metrics/sender.js.html +394 -0
- package/coverage/lcov-report/services/metrics/stringify-deep.js.html +151 -0
- package/coverage/lcov-report/services/utils/index.html +116 -0
- package/coverage/lcov-report/services/utils/upload-files.js.html +322 -0
- package/coverage/lcov-report/services/worker-queue.js.html +262 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/utils/convert-custom-field-type.js.html +151 -0
- package/coverage/lcov-report/utils/index.html +146 -0
- package/coverage/lcov-report/utils/machine-id.js.html +127 -0
- package/coverage/lcov-report/utils/url-from-segments.js.html +121 -0
- package/lib/commands/__tests__/commands.test.js +20 -0
- package/lib/commands/__tests__/commands.test.utils.js +16 -0
- package/lib/commands/actions/admin/create-user/__tests__/admin.create-user.test.js +450 -0
- package/lib/commands/actions/admin/reset-user-password/__tests__/admin.reset-user-password.test.js +145 -0
- package/lib/commands/actions/build/action.js +18 -0
- package/lib/commands/actions/build/command.js +15 -0
- package/lib/commands/actions/export/__tests__/export.test.js +175 -0
- package/lib/commands/actions/import/__tests__/import.test.js +143 -0
- package/lib/commands/actions/templates/generate/__tests__/templates.generate.js +118 -0
- package/lib/commands/actions/transfer/__tests__/transfer.test.js +178 -0
- package/lib/core/registries/__tests__/custom-fields.test.js +152 -0
- package/lib/core-api/__tests__/controller.test.js +39 -0
- package/lib/core-api/controller/__tests__/transform.test.js +226 -0
- package/lib/core-api/service/__tests__/index.test.js +127 -0
- package/lib/core-api/service/__tests__/pagination.test.js +275 -0
- package/lib/load/__tests__/filepath-to-prop-path.test.js +30 -0
- package/lib/middlewares/__tests__/errors.test.js +21 -0
- package/lib/services/__tests__/content-api-permissions.test.js +291 -0
- package/lib/services/__tests__/core-store.test.js +148 -0
- package/lib/services/__tests__/event-hub.test.js +126 -0
- package/lib/services/__tests__/fs.test.js +78 -0
- package/lib/services/__tests__/worker-queue.test.js +47 -0
- package/lib/services/entity-service/__tests__/entity-service-events.test.js +117 -0
- package/lib/services/entity-service/__tests__/entity-service.test.js +587 -0
- package/lib/services/entity-validator/__tests__/biginteger-validators.test.js +220 -0
- package/lib/services/entity-validator/__tests__/date-validators.test.js +183 -0
- package/lib/services/entity-validator/__tests__/datetime-validators.test.js +183 -0
- package/lib/services/entity-validator/__tests__/email-validators.test.js +56 -0
- package/lib/services/entity-validator/__tests__/enumeration-validators.test.js +43 -0
- package/lib/services/entity-validator/__tests__/float-validators.test.js +278 -0
- package/lib/services/entity-validator/__tests__/index.test.js +609 -0
- package/lib/services/entity-validator/__tests__/integer-validators.test.js +278 -0
- package/lib/services/entity-validator/__tests__/relations/attribute-level.test.js +123 -0
- package/lib/services/entity-validator/__tests__/relations/component-level.test.js +275 -0
- package/lib/services/entity-validator/__tests__/relations/dynamic-zone-level.test.js +159 -0
- package/lib/services/entity-validator/__tests__/relations/media-level.test.js +74 -0
- package/lib/services/entity-validator/__tests__/relations/utils/relations.testdata.js +153 -0
- package/lib/services/entity-validator/__tests__/string-validators.test.js +374 -0
- package/lib/services/entity-validator/__tests__/time-validators.test.js +183 -0
- package/lib/services/entity-validator/__tests__/timestamp-validators.test.js +204 -0
- package/lib/services/entity-validator/__tests__/uid-validators.test.js +229 -0
- package/lib/services/metrics/__tests__/admin-user-hash.test.js +41 -0
- package/lib/services/metrics/__tests__/index.test.js +157 -0
- package/lib/services/metrics/__tests__/is-truthy.js +33 -0
- package/lib/services/metrics/__tests__/middleware.test.js +60 -0
- package/lib/services/metrics/__tests__/rate-limiter.test.js +50 -0
- package/lib/services/metrics/__tests__/stringify-deep.test.js +27 -0
- package/lib/utils/__tests__/convert-custom-field-type.test.js +69 -0
- package/lib/utils/__tests__/url-from-segments.test.js +40 -0
- package/package.json +15 -15
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const strapiUtils = require('@strapi/utils');
|
|
4
|
+
const {
|
|
5
|
+
errors: { YupValidationError },
|
|
6
|
+
} = require('@strapi/utils');
|
|
7
|
+
const validators = require('../validators');
|
|
8
|
+
|
|
9
|
+
describe('BigInteger validator', () => {
|
|
10
|
+
describe('unique', () => {
|
|
11
|
+
const fakeFindOne = jest.fn();
|
|
12
|
+
|
|
13
|
+
global.strapi = {
|
|
14
|
+
db: {
|
|
15
|
+
query: jest.fn(() => ({
|
|
16
|
+
findOne: fakeFindOne,
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
fakeFindOne.mockReset();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const fakeModel = {
|
|
27
|
+
kind: 'contentType',
|
|
28
|
+
modelName: 'test-model',
|
|
29
|
+
uid: 'test-uid',
|
|
30
|
+
privateAttributes: [],
|
|
31
|
+
options: {},
|
|
32
|
+
attributes: {
|
|
33
|
+
attrBigIntegerUnique: { type: 'biginteger', unique: true },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
test('it does not validate the unique constraint if the attribute is not set as unique', async () => {
|
|
38
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
39
|
+
|
|
40
|
+
const validator = strapiUtils.validateYupSchema(
|
|
41
|
+
validators.biginteger(
|
|
42
|
+
{
|
|
43
|
+
attr: { type: 'biginteger' },
|
|
44
|
+
model: fakeModel,
|
|
45
|
+
updatedAttribute: {
|
|
46
|
+
name: 'attrBigIntegerUnique',
|
|
47
|
+
value: 1,
|
|
48
|
+
},
|
|
49
|
+
entity: null,
|
|
50
|
+
},
|
|
51
|
+
{ isDraft: false }
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
await validator(1);
|
|
56
|
+
|
|
57
|
+
expect(fakeFindOne).not.toHaveBeenCalled();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('it does not validate the unique constraint if the attribute value is `null`', async () => {
|
|
61
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
62
|
+
|
|
63
|
+
const validator = strapiUtils.validateYupSchema(
|
|
64
|
+
validators
|
|
65
|
+
.biginteger(
|
|
66
|
+
{
|
|
67
|
+
attr: { type: 'biginteger', unique: true },
|
|
68
|
+
model: fakeModel,
|
|
69
|
+
updatedAttribute: {
|
|
70
|
+
name: 'attrBigIntegerUnique',
|
|
71
|
+
value: null,
|
|
72
|
+
},
|
|
73
|
+
entity: null,
|
|
74
|
+
},
|
|
75
|
+
{ isDraft: false }
|
|
76
|
+
)
|
|
77
|
+
.nullable()
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
await validator(null);
|
|
81
|
+
|
|
82
|
+
expect(fakeFindOne).not.toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('it validates the unique constraint if there is no other record in the database', async () => {
|
|
86
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
87
|
+
|
|
88
|
+
const validator = strapiUtils.validateYupSchema(
|
|
89
|
+
validators.biginteger(
|
|
90
|
+
{
|
|
91
|
+
attr: { type: 'biginteger', unique: true },
|
|
92
|
+
model: fakeModel,
|
|
93
|
+
updatedAttribute: {
|
|
94
|
+
name: 'attrBigIntegerUnique',
|
|
95
|
+
value: 1,
|
|
96
|
+
},
|
|
97
|
+
entity: null,
|
|
98
|
+
},
|
|
99
|
+
{ isDraft: false }
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
expect(await validator(1)).toBe(1);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('it fails the validation of the unique constraint if the database contains a record with the same attribute value', async () => {
|
|
107
|
+
expect.assertions(1);
|
|
108
|
+
fakeFindOne.mockResolvedValueOnce({ attrBigIntegerUnique: 2 });
|
|
109
|
+
|
|
110
|
+
const validator = strapiUtils.validateYupSchema(
|
|
111
|
+
validators.biginteger(
|
|
112
|
+
{
|
|
113
|
+
attr: { type: 'biginteger', unique: true },
|
|
114
|
+
model: fakeModel,
|
|
115
|
+
updatedAttribute: {
|
|
116
|
+
name: 'attrBigIntegerUnique',
|
|
117
|
+
value: 2,
|
|
118
|
+
},
|
|
119
|
+
entity: null,
|
|
120
|
+
},
|
|
121
|
+
{ isDraft: false }
|
|
122
|
+
)
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
await validator(2);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
expect(err).toBeInstanceOf(YupValidationError);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('it validates the unique constraint if the attribute data has not changed even if there is a record in the database with the same attribute value', async () => {
|
|
133
|
+
fakeFindOne.mockResolvedValueOnce({ attrBigIntegerUnique: 3 });
|
|
134
|
+
|
|
135
|
+
const validator = strapiUtils.validateYupSchema(
|
|
136
|
+
validators.biginteger(
|
|
137
|
+
{
|
|
138
|
+
attr: { type: 'biginteger', unique: true },
|
|
139
|
+
model: fakeModel,
|
|
140
|
+
updatedAttribute: {
|
|
141
|
+
name: 'attrBigIntegerUnique',
|
|
142
|
+
value: 3,
|
|
143
|
+
},
|
|
144
|
+
entity: { id: 1, attrBigIntegerUnique: 3 },
|
|
145
|
+
},
|
|
146
|
+
{ isDraft: false }
|
|
147
|
+
)
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(await validator(3)).toBe(3);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('it checks the database for records with the same value for the checked attribute', async () => {
|
|
154
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
155
|
+
|
|
156
|
+
const validator = strapiUtils.validateYupSchema(
|
|
157
|
+
validators.biginteger(
|
|
158
|
+
{
|
|
159
|
+
attr: { type: 'biginteger', unique: true },
|
|
160
|
+
model: fakeModel,
|
|
161
|
+
updatedAttribute: {
|
|
162
|
+
name: 'attrBigIntegerUnique',
|
|
163
|
+
value: 4,
|
|
164
|
+
},
|
|
165
|
+
entity: null,
|
|
166
|
+
},
|
|
167
|
+
{ isDraft: false }
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
await validator(4);
|
|
172
|
+
|
|
173
|
+
expect(fakeFindOne).toHaveBeenCalledWith({
|
|
174
|
+
select: ['id'],
|
|
175
|
+
where: { attrBigIntegerUnique: 4 },
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test('it checks the database for records with the same value but not the same id for the checked attribute if an entity is passed', async () => {
|
|
180
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
181
|
+
|
|
182
|
+
const validator = strapiUtils.validateYupSchema(
|
|
183
|
+
validators.biginteger(
|
|
184
|
+
{
|
|
185
|
+
attr: { type: 'biginteger', unique: true },
|
|
186
|
+
model: fakeModel,
|
|
187
|
+
updatedAttribute: {
|
|
188
|
+
name: 'attrBigIntegerUnique',
|
|
189
|
+
value: 5,
|
|
190
|
+
},
|
|
191
|
+
entity: { id: 1, attrBigIntegerUnique: 42 },
|
|
192
|
+
},
|
|
193
|
+
{ isDraft: false }
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
await validator(5);
|
|
198
|
+
|
|
199
|
+
expect(fakeFindOne).toHaveBeenCalledWith({
|
|
200
|
+
select: ['id'],
|
|
201
|
+
where: { $and: [{ attrBigIntegerUnique: 5 }, { $not: { id: 1 } }] },
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('min', () => {
|
|
207
|
+
test('it does not validate the min constraint if the attribute min is not a number', async () => {
|
|
208
|
+
const validator = strapiUtils.validateYupSchema(
|
|
209
|
+
validators.biginteger(
|
|
210
|
+
{
|
|
211
|
+
attr: { type: 'biginteger', minLength: '123' },
|
|
212
|
+
},
|
|
213
|
+
{ isDraft: false }
|
|
214
|
+
)
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
expect(await validator(1)).toBe(1);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const strapiUtils = require('@strapi/utils');
|
|
4
|
+
const {
|
|
5
|
+
errors: { YupValidationError },
|
|
6
|
+
} = require('@strapi/utils');
|
|
7
|
+
const validators = require('../validators');
|
|
8
|
+
|
|
9
|
+
describe('Date validator', () => {
|
|
10
|
+
describe('unique', () => {
|
|
11
|
+
const fakeFindOne = jest.fn();
|
|
12
|
+
|
|
13
|
+
global.strapi = {
|
|
14
|
+
db: {
|
|
15
|
+
query: jest.fn(() => ({
|
|
16
|
+
findOne: fakeFindOne,
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
fakeFindOne.mockReset();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const fakeModel = {
|
|
27
|
+
kind: 'contentType',
|
|
28
|
+
modelName: 'test-model',
|
|
29
|
+
uid: 'test-uid',
|
|
30
|
+
privateAttributes: [],
|
|
31
|
+
options: {},
|
|
32
|
+
attributes: {
|
|
33
|
+
attrDateUnique: { type: 'date', unique: true },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
test('it does not validates the unique constraint if the attribute is not set as unique', async () => {
|
|
38
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
39
|
+
|
|
40
|
+
const validator = strapiUtils.validateYupSchema(
|
|
41
|
+
validators.date(
|
|
42
|
+
{
|
|
43
|
+
attr: { type: 'date' },
|
|
44
|
+
model: fakeModel,
|
|
45
|
+
updatedAttribute: { name: 'attrDateUnique', value: '2021-11-29' },
|
|
46
|
+
entity: null,
|
|
47
|
+
},
|
|
48
|
+
{ isDraft: false }
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
await validator('2021-11-29');
|
|
53
|
+
|
|
54
|
+
expect(fakeFindOne).not.toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('it does not validates the unique constraint if the attribute value is `null`', async () => {
|
|
58
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
59
|
+
|
|
60
|
+
const validator = strapiUtils.validateYupSchema(
|
|
61
|
+
validators
|
|
62
|
+
.date(
|
|
63
|
+
{
|
|
64
|
+
attr: { type: 'date', unique: true },
|
|
65
|
+
model: fakeModel,
|
|
66
|
+
updatedAttribute: { name: 'attrDateUnique', value: null },
|
|
67
|
+
entity: null,
|
|
68
|
+
},
|
|
69
|
+
{ isDraft: false }
|
|
70
|
+
)
|
|
71
|
+
.nullable()
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
await validator(null);
|
|
75
|
+
expect(fakeFindOne).not.toHaveBeenCalled();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('it validates the unique constraint if there is no other record in the database', async () => {
|
|
79
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
80
|
+
|
|
81
|
+
const validator = strapiUtils.validateYupSchema(
|
|
82
|
+
validators.date(
|
|
83
|
+
{
|
|
84
|
+
attr: { type: 'date', unique: true },
|
|
85
|
+
model: fakeModel,
|
|
86
|
+
updatedAttribute: { name: 'attrDateUnique', value: '2021-11-29' },
|
|
87
|
+
entity: null,
|
|
88
|
+
},
|
|
89
|
+
{ isDraft: false }
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
expect(await validator('2021-11-29')).toBe('2021-11-29');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('it fails the validation of the unique constraint if the database contains a record with the same attribute value', async () => {
|
|
97
|
+
expect.assertions(1);
|
|
98
|
+
fakeFindOne.mockResolvedValueOnce({ attrDateUnique: '2021-11-29' });
|
|
99
|
+
|
|
100
|
+
const validator = strapiUtils.validateYupSchema(
|
|
101
|
+
validators.date(
|
|
102
|
+
{
|
|
103
|
+
attr: { type: 'date', unique: true },
|
|
104
|
+
model: fakeModel,
|
|
105
|
+
updatedAttribute: { name: 'attrDateUnique', value: '2021-11-29' },
|
|
106
|
+
entity: null,
|
|
107
|
+
},
|
|
108
|
+
{ isDraft: false }
|
|
109
|
+
)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
await validator('2021-11-29');
|
|
114
|
+
} catch (err) {
|
|
115
|
+
expect(err).toBeInstanceOf(YupValidationError);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('it validates the unique constraint if the attribute data has not changed even if there is a record in the database with the same attribute value', async () => {
|
|
120
|
+
fakeFindOne.mockResolvedValueOnce({ attrDateUnique: '2021-11-29' });
|
|
121
|
+
|
|
122
|
+
const validator = strapiUtils.validateYupSchema(
|
|
123
|
+
validators.date(
|
|
124
|
+
{
|
|
125
|
+
attr: { type: 'date', unique: true },
|
|
126
|
+
model: fakeModel,
|
|
127
|
+
updatedAttribute: { name: 'attrDateUnique', value: '2021-11-29' },
|
|
128
|
+
entity: { id: 1, attrDateUnique: '2021-11-29' },
|
|
129
|
+
},
|
|
130
|
+
{ isDraft: false }
|
|
131
|
+
)
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
expect(await validator('2021-11-29')).toBe('2021-11-29');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('it checks the database for records with the same value for the checked attribute', async () => {
|
|
138
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
139
|
+
|
|
140
|
+
const validator = strapiUtils.validateYupSchema(
|
|
141
|
+
validators.date(
|
|
142
|
+
{
|
|
143
|
+
attr: { type: 'date', unique: true },
|
|
144
|
+
model: fakeModel,
|
|
145
|
+
updatedAttribute: { name: 'attrDateUnique', value: '2021-11-29' },
|
|
146
|
+
entity: null,
|
|
147
|
+
},
|
|
148
|
+
{ isDraft: false }
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
await validator('2021-11-29');
|
|
153
|
+
|
|
154
|
+
expect(fakeFindOne).toHaveBeenCalledWith({
|
|
155
|
+
select: ['id'],
|
|
156
|
+
where: { attrDateUnique: '2021-11-29' },
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('it checks the database for records with the same value but not the same id for the checked attribute if an entity is passed', async () => {
|
|
161
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
162
|
+
|
|
163
|
+
const validator = strapiUtils.validateYupSchema(
|
|
164
|
+
validators.date(
|
|
165
|
+
{
|
|
166
|
+
attr: { type: 'date', unique: true },
|
|
167
|
+
model: fakeModel,
|
|
168
|
+
updatedAttribute: { name: 'attrDateUnique', value: '2021-11-29' },
|
|
169
|
+
entity: { id: 1, attrDateUnique: '2021-12-15' },
|
|
170
|
+
},
|
|
171
|
+
{ isDraft: false }
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
await validator('2021-11-29');
|
|
176
|
+
|
|
177
|
+
expect(fakeFindOne).toHaveBeenCalledWith({
|
|
178
|
+
select: ['id'],
|
|
179
|
+
where: { $and: [{ attrDateUnique: '2021-11-29' }, { $not: { id: 1 } }] },
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const strapiUtils = require('@strapi/utils');
|
|
4
|
+
const {
|
|
5
|
+
errors: { YupValidationError },
|
|
6
|
+
} = require('@strapi/utils');
|
|
7
|
+
const validators = require('../validators');
|
|
8
|
+
|
|
9
|
+
describe('Datetime validator', () => {
|
|
10
|
+
describe('unique', () => {
|
|
11
|
+
const fakeFindOne = jest.fn();
|
|
12
|
+
|
|
13
|
+
global.strapi = {
|
|
14
|
+
db: {
|
|
15
|
+
query: jest.fn(() => ({
|
|
16
|
+
findOne: fakeFindOne,
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
fakeFindOne.mockReset();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const fakeModel = {
|
|
27
|
+
kind: 'contentType',
|
|
28
|
+
modelName: 'test-model',
|
|
29
|
+
uid: 'test-uid',
|
|
30
|
+
privateAttributes: [],
|
|
31
|
+
options: {},
|
|
32
|
+
attributes: {
|
|
33
|
+
attrDateTimeUnique: { type: 'datetime', unique: true },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
test('it does not validates the unique constraint if the attribute is not set as unique', async () => {
|
|
38
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
39
|
+
|
|
40
|
+
const validator = strapiUtils.validateYupSchema(
|
|
41
|
+
validators.datetime(
|
|
42
|
+
{
|
|
43
|
+
attr: { type: 'datetime' },
|
|
44
|
+
model: fakeModel,
|
|
45
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: '2021-11-29T00:00:00.000Z' },
|
|
46
|
+
entity: { id: 1, attrDateTimeUnique: '2021-11-29T00:00:00.000Z' },
|
|
47
|
+
},
|
|
48
|
+
{ isDraft: false }
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
await validator('2021-11-29T00:00:00.000Z');
|
|
53
|
+
|
|
54
|
+
expect(fakeFindOne).not.toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('it does not validates the unique constraint if the attribute value is `null`', async () => {
|
|
58
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
59
|
+
|
|
60
|
+
const validator = strapiUtils.validateYupSchema(
|
|
61
|
+
validators
|
|
62
|
+
.datetime(
|
|
63
|
+
{
|
|
64
|
+
attr: { type: 'datetime', unique: true },
|
|
65
|
+
model: fakeModel,
|
|
66
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: null },
|
|
67
|
+
entity: null,
|
|
68
|
+
},
|
|
69
|
+
{ isDraft: false }
|
|
70
|
+
)
|
|
71
|
+
.nullable()
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
await validator(null);
|
|
75
|
+
expect(fakeFindOne).not.toHaveBeenCalled();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('it validates the unique constraint if there is no other record in the database', async () => {
|
|
79
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
80
|
+
|
|
81
|
+
const validator = strapiUtils.validateYupSchema(
|
|
82
|
+
validators.datetime(
|
|
83
|
+
{
|
|
84
|
+
attr: { type: 'datetime', unique: true },
|
|
85
|
+
model: fakeModel,
|
|
86
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: '2021-11-29T00:00:00.000Z' },
|
|
87
|
+
entity: null,
|
|
88
|
+
},
|
|
89
|
+
{ isDraft: false }
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
expect(await validator('2021-11-29T00:00:00.000Z')).toBe('2021-11-29T00:00:00.000Z');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('it fails the validation of the unique constraint if the database contains a record with the same attribute value', async () => {
|
|
97
|
+
expect.assertions(1);
|
|
98
|
+
fakeFindOne.mockResolvedValueOnce({ attrDateTimeUnique: '2021-11-29T00:00:00.000Z' });
|
|
99
|
+
|
|
100
|
+
const validator = strapiUtils.validateYupSchema(
|
|
101
|
+
validators.datetime(
|
|
102
|
+
{
|
|
103
|
+
attr: { type: 'datetime', unique: true },
|
|
104
|
+
model: fakeModel,
|
|
105
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: '2021-11-29T00:00:00.000Z' },
|
|
106
|
+
entity: null,
|
|
107
|
+
},
|
|
108
|
+
{ isDraft: false }
|
|
109
|
+
)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
await validator('2021-11-29T00:00:00.000Z');
|
|
114
|
+
} catch (err) {
|
|
115
|
+
expect(err).toBeInstanceOf(YupValidationError);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('it validates the unique constraint if the attribute data has not changed even if there is a record in the database with the same attribute value', async () => {
|
|
120
|
+
fakeFindOne.mockResolvedValueOnce({ attrDateTimeUnique: '2021-11-29T00:00:00.000Z' });
|
|
121
|
+
|
|
122
|
+
const validator = strapiUtils.validateYupSchema(
|
|
123
|
+
validators.datetime(
|
|
124
|
+
{
|
|
125
|
+
attr: { type: 'datetime', unique: true },
|
|
126
|
+
model: fakeModel,
|
|
127
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: '2021-11-29T00:00:00.000Z' },
|
|
128
|
+
entity: { id: 1, attrDateTimeUnique: '2021-11-29T00:00:00.000Z' },
|
|
129
|
+
},
|
|
130
|
+
{ isDraft: false }
|
|
131
|
+
)
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
expect(await validator('2021-11-29T00:00:00.000Z')).toBe('2021-11-29T00:00:00.000Z');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('it checks the database for records with the same value for the checked attribute', async () => {
|
|
138
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
139
|
+
|
|
140
|
+
const validator = strapiUtils.validateYupSchema(
|
|
141
|
+
validators.datetime(
|
|
142
|
+
{
|
|
143
|
+
attr: { type: 'datetime', unique: true },
|
|
144
|
+
model: fakeModel,
|
|
145
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: '2021-11-29T00:00:00.000Z' },
|
|
146
|
+
entity: null,
|
|
147
|
+
},
|
|
148
|
+
{ isDraft: false }
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
await validator('2021-11-29T00:00:00.000Z');
|
|
153
|
+
|
|
154
|
+
expect(fakeFindOne).toHaveBeenCalledWith({
|
|
155
|
+
select: ['id'],
|
|
156
|
+
where: { attrDateTimeUnique: '2021-11-29T00:00:00.000Z' },
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('it checks the database for records with the same value but not the same id for the checked attribute if an entity is passed', async () => {
|
|
161
|
+
fakeFindOne.mockResolvedValueOnce(null);
|
|
162
|
+
|
|
163
|
+
const validator = strapiUtils.validateYupSchema(
|
|
164
|
+
validators.datetime(
|
|
165
|
+
{
|
|
166
|
+
attr: { type: 'datetime', unique: true },
|
|
167
|
+
model: fakeModel,
|
|
168
|
+
updatedAttribute: { name: 'attrDateTimeUnique', value: '2021-11-29T00:00:00.000Z' },
|
|
169
|
+
entity: { id: 1, attrDateTimeUnique: '2021-12-25T00:00:00.000Z' },
|
|
170
|
+
},
|
|
171
|
+
{ isDraft: false }
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
await validator('2021-11-29T00:00:00.000Z');
|
|
176
|
+
|
|
177
|
+
expect(fakeFindOne).toHaveBeenCalledWith({
|
|
178
|
+
select: ['id'],
|
|
179
|
+
where: { $and: [{ attrDateTimeUnique: '2021-11-29T00:00:00.000Z' }, { $not: { id: 1 } }] },
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const strapiUtils = require('@strapi/utils');
|
|
4
|
+
const {
|
|
5
|
+
errors: { YupValidationError },
|
|
6
|
+
} = require('@strapi/utils');
|
|
7
|
+
const validators = require('../validators');
|
|
8
|
+
|
|
9
|
+
describe('Email validator', () => {
|
|
10
|
+
describe('email', () => {
|
|
11
|
+
test('it fails the validation if the string is not a valid email', async () => {
|
|
12
|
+
expect.assertions(1);
|
|
13
|
+
|
|
14
|
+
const validator = strapiUtils.validateYupSchema(
|
|
15
|
+
validators.email(
|
|
16
|
+
{
|
|
17
|
+
attr: { type: 'email' },
|
|
18
|
+
},
|
|
19
|
+
{ isDraft: false }
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
await validator('invalid-email');
|
|
25
|
+
} catch (err) {
|
|
26
|
+
expect(err).toBeInstanceOf(YupValidationError);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('it validates the email if it is valid', async () => {
|
|
31
|
+
const validator = strapiUtils.validateYupSchema(
|
|
32
|
+
validators.email(
|
|
33
|
+
{
|
|
34
|
+
attr: { type: 'email' },
|
|
35
|
+
},
|
|
36
|
+
{ isDraft: false }
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(await validator('valid@email.com')).toBe('valid@email.com');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('it validates non-empty email required field', async () => {
|
|
44
|
+
const validator = strapiUtils.validateYupSchema(
|
|
45
|
+
validators.email({ attr: { type: 'email' } }, { isDraft: false })
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await validator('');
|
|
50
|
+
} catch (err) {
|
|
51
|
+
expect(err).toBeInstanceOf(YupValidationError);
|
|
52
|
+
expect(err.message).toBe('this cannot be empty');
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const strapiUtils = require('@strapi/utils');
|
|
4
|
+
const {
|
|
5
|
+
errors: { YupValidationError },
|
|
6
|
+
} = require('@strapi/utils');
|
|
7
|
+
const validators = require('../validators');
|
|
8
|
+
|
|
9
|
+
describe('Enumeration validator', () => {
|
|
10
|
+
describe('oneOf', () => {
|
|
11
|
+
test('it fails the validation if the value is not part of the allowed values', async () => {
|
|
12
|
+
expect.assertions(1);
|
|
13
|
+
|
|
14
|
+
const validator = strapiUtils.validateYupSchema(
|
|
15
|
+
validators.enumeration(
|
|
16
|
+
{
|
|
17
|
+
attr: { type: 'enum', enum: ['strapi', 'headless'] },
|
|
18
|
+
},
|
|
19
|
+
{ isDraft: false }
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
await validator('invalid-vlue');
|
|
25
|
+
} catch (err) {
|
|
26
|
+
expect(err).toBeInstanceOf(YupValidationError);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('it validates the value if it is part of the allowed values', async () => {
|
|
31
|
+
const validator = strapiUtils.validateYupSchema(
|
|
32
|
+
validators.enumeration(
|
|
33
|
+
{
|
|
34
|
+
attr: { type: 'enumeration', enum: ['strapi', 'headless'] },
|
|
35
|
+
},
|
|
36
|
+
{ isDraft: false }
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(await validator('strapi')).toBe('strapi');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|