@strapi/strapi 4.10.0-beta.1 → 4.10.1-experimental.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 (193) hide show
  1. package/bin/strapi.js +2 -468
  2. package/coverage/clover.xml +1613 -0
  3. package/coverage/coverage-final.json +48 -0
  4. package/coverage/lcov-report/base.css +224 -0
  5. package/coverage/lcov-report/block-navigation.js +87 -0
  6. package/coverage/lcov-report/commands/__tests__/data-transfer/shared/index.html +116 -0
  7. package/coverage/lcov-report/commands/__tests__/data-transfer/shared/transfer.test.utils.js.html +133 -0
  8. package/coverage/lcov-report/commands/admin-create.js.html +424 -0
  9. package/coverage/lcov-report/commands/admin-reset.js.html +241 -0
  10. package/coverage/lcov-report/commands/generate-template.js.html +373 -0
  11. package/coverage/lcov-report/commands/index.html +146 -0
  12. package/coverage/lcov-report/commands/transfer/export.js.html +619 -0
  13. package/coverage/lcov-report/commands/transfer/import.js.html +562 -0
  14. package/coverage/lcov-report/commands/transfer/index.html +146 -0
  15. package/coverage/lcov-report/commands/transfer/transfer.js.html +532 -0
  16. package/coverage/lcov-report/commands/utils/helpers.js.html +430 -0
  17. package/coverage/lcov-report/commands/utils/index.html +116 -0
  18. package/coverage/lcov-report/core/registries/custom-fields.js.html +301 -0
  19. package/coverage/lcov-report/core/registries/index.html +116 -0
  20. package/coverage/lcov-report/core-api/controller/collection-type.js.html +418 -0
  21. package/coverage/lcov-report/core-api/controller/index.html +161 -0
  22. package/coverage/lcov-report/core-api/controller/index.js.html +220 -0
  23. package/coverage/lcov-report/core-api/controller/single-type.js.html +274 -0
  24. package/coverage/lcov-report/core-api/controller/transform.js.html +376 -0
  25. package/coverage/lcov-report/core-api/service/collection-type.js.html +325 -0
  26. package/coverage/lcov-report/core-api/service/index.html +161 -0
  27. package/coverage/lcov-report/core-api/service/index.js.html +220 -0
  28. package/coverage/lcov-report/core-api/service/pagination.js.html +460 -0
  29. package/coverage/lcov-report/core-api/service/single-type.js.html +301 -0
  30. package/coverage/lcov-report/favicon.png +0 -0
  31. package/coverage/lcov-report/index.html +386 -0
  32. package/coverage/lcov-report/load/filepath-to-prop-path.js.html +151 -0
  33. package/coverage/lcov-report/load/index.html +116 -0
  34. package/coverage/lcov-report/prettify.css +1 -0
  35. package/coverage/lcov-report/prettify.js +2 -0
  36. package/coverage/lcov-report/services/content-api/index.html +116 -0
  37. package/coverage/lcov-report/services/content-api/index.js.html +307 -0
  38. package/coverage/lcov-report/services/content-api/permissions/engine.js.html +100 -0
  39. package/coverage/lcov-report/services/content-api/permissions/index.html +131 -0
  40. package/coverage/lcov-report/services/content-api/permissions/index.js.html +529 -0
  41. package/coverage/lcov-report/services/content-api/permissions/providers/action.js.html +142 -0
  42. package/coverage/lcov-report/services/content-api/permissions/providers/condition.js.html +142 -0
  43. package/coverage/lcov-report/services/content-api/permissions/providers/index.html +146 -0
  44. package/coverage/lcov-report/services/content-api/permissions/providers/index.js.html +112 -0
  45. package/coverage/lcov-report/services/core-store.js.html +520 -0
  46. package/coverage/lcov-report/services/entity-service/attributes/index.html +131 -0
  47. package/coverage/lcov-report/services/entity-service/attributes/index.js.html +178 -0
  48. package/coverage/lcov-report/services/entity-service/attributes/transforms.js.html +145 -0
  49. package/coverage/lcov-report/services/entity-service/components.js.html +1246 -0
  50. package/coverage/lcov-report/services/entity-service/index.html +146 -0
  51. package/coverage/lcov-report/services/entity-service/index.js.html +1120 -0
  52. package/coverage/lcov-report/services/entity-service/params.js.html +112 -0
  53. package/coverage/lcov-report/services/entity-validator/__tests__/relations/utils/index.html +116 -0
  54. package/coverage/lcov-report/services/entity-validator/__tests__/relations/utils/relations.testdata.js.html +544 -0
  55. package/coverage/lcov-report/services/entity-validator/index.html +131 -0
  56. package/coverage/lcov-report/services/entity-validator/index.js.html +1231 -0
  57. package/coverage/lcov-report/services/entity-validator/validators.js.html +733 -0
  58. package/coverage/lcov-report/services/event-hub.js.html +319 -0
  59. package/coverage/lcov-report/services/fs.js.html +259 -0
  60. package/coverage/lcov-report/services/index.html +161 -0
  61. package/coverage/lcov-report/services/metrics/admin-user-hash.js.html +148 -0
  62. package/coverage/lcov-report/services/metrics/index.html +206 -0
  63. package/coverage/lcov-report/services/metrics/index.js.html +265 -0
  64. package/coverage/lcov-report/services/metrics/is-truthy.js.html +112 -0
  65. package/coverage/lcov-report/services/metrics/middleware.js.html +184 -0
  66. package/coverage/lcov-report/services/metrics/rate-limiter.js.html +166 -0
  67. package/coverage/lcov-report/services/metrics/sender.js.html +394 -0
  68. package/coverage/lcov-report/services/metrics/stringify-deep.js.html +151 -0
  69. package/coverage/lcov-report/services/utils/index.html +116 -0
  70. package/coverage/lcov-report/services/utils/upload-files.js.html +322 -0
  71. package/coverage/lcov-report/services/worker-queue.js.html +262 -0
  72. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  73. package/coverage/lcov-report/sorter.js +196 -0
  74. package/coverage/lcov-report/utils/convert-custom-field-type.js.html +151 -0
  75. package/coverage/lcov-report/utils/index.html +146 -0
  76. package/coverage/lcov-report/utils/machine-id.js.html +127 -0
  77. package/coverage/lcov-report/utils/url-from-segments.js.html +121 -0
  78. package/ee/LICENSE.txt +21 -0
  79. package/ee/index.js +3 -1
  80. package/ee/license.js +8 -7
  81. package/lib/Strapi.js +3 -0
  82. package/lib/commands/__tests__/commands.test.js +20 -0
  83. package/lib/commands/__tests__/commands.test.utils.js +16 -0
  84. package/lib/commands/actions/admin/create-user/__tests__/admin.create-user.test.js +450 -0
  85. package/lib/commands/{admin-create.js → actions/admin/create-user/action.js} +2 -2
  86. package/lib/commands/actions/admin/create-user/command.js +19 -0
  87. package/lib/commands/actions/admin/reset-user-password/__tests__/admin.reset-user-password.test.js +145 -0
  88. package/lib/commands/{admin-reset.js → actions/admin/reset-user-password/action.js} +2 -2
  89. package/lib/commands/actions/admin/reset-user-password/command.js +17 -0
  90. package/lib/commands/{build.js → actions/build/action.js} +2 -2
  91. package/lib/commands/actions/build/command.js +15 -0
  92. package/lib/commands/{configurationDump.js → actions/configuration/dump/action.js} +1 -1
  93. package/lib/commands/actions/configuration/dump/command.js +17 -0
  94. package/lib/commands/{configurationRestore.js → actions/configuration/restore/action.js} +1 -1
  95. package/lib/commands/actions/configuration/restore/command.js +17 -0
  96. package/lib/commands/{console.js → actions/console/action.js} +2 -2
  97. package/lib/commands/actions/console/command.js +14 -0
  98. package/lib/commands/{content-types/list.js → actions/content-types/list/action.js} +2 -2
  99. package/lib/commands/actions/content-types/list/command.js +14 -0
  100. package/lib/commands/{controllers/list.js → actions/controllers/list/action.js} +2 -2
  101. package/lib/commands/actions/controllers/list/command.js +14 -0
  102. package/lib/commands/{develop.js → actions/develop/action.js} +3 -3
  103. package/lib/commands/actions/develop/command.js +19 -0
  104. package/lib/commands/actions/export/__tests__/export.test.js +175 -0
  105. package/lib/commands/{transfer/export.js → actions/export/action.js} +3 -2
  106. package/lib/commands/actions/export/command.js +45 -0
  107. package/lib/commands/actions/generate/command.js +18 -0
  108. package/lib/commands/{hooks/list.js → actions/hooks/list/action.js} +2 -2
  109. package/lib/commands/actions/hooks/list/command.js +14 -0
  110. package/lib/commands/actions/import/__tests__/import.test.js +143 -0
  111. package/lib/commands/{transfer/import.js → actions/import/action.js} +2 -2
  112. package/lib/commands/actions/import/command.js +97 -0
  113. package/lib/commands/{install.js → actions/install/action.js} +1 -1
  114. package/lib/commands/actions/install/command.js +14 -0
  115. package/lib/commands/{middlewares/list.js → actions/middlewares/list/action.js} +2 -2
  116. package/lib/commands/actions/middlewares/list/command.js +14 -0
  117. package/lib/commands/{new.js → actions/new/action.js} +1 -1
  118. package/lib/commands/actions/new/command.js +35 -0
  119. package/lib/commands/{policies/list.js → actions/policies/list/action.js} +2 -2
  120. package/lib/commands/actions/policies/list/command.js +14 -0
  121. package/lib/commands/{report.js → actions/report/action.js} +1 -1
  122. package/lib/commands/actions/report/command.js +17 -0
  123. package/lib/commands/{routes/list.js → actions/routes/list/action.js} +2 -2
  124. package/lib/commands/actions/routes/list/command.js +14 -0
  125. package/lib/commands/{services/list.js → actions/services/list/action.js} +2 -2
  126. package/lib/commands/actions/services/list/command.js +14 -0
  127. package/lib/commands/{start.js → actions/start/action.js} +1 -1
  128. package/lib/commands/actions/start/command.js +14 -0
  129. package/lib/commands/{opt-out-telemetry.js → actions/telemetry/disable/action.js} +1 -1
  130. package/lib/commands/actions/telemetry/disable/command.js +14 -0
  131. package/lib/commands/{opt-in-telemetry.js → actions/telemetry/enable/action.js} +1 -1
  132. package/lib/commands/actions/telemetry/enable/command.js +14 -0
  133. package/lib/commands/actions/templates/generate/__tests__/templates.generate.js +118 -0
  134. package/lib/commands/actions/templates/generate/command.js +14 -0
  135. package/lib/commands/actions/transfer/__tests__/transfer.test.js +178 -0
  136. package/lib/commands/{transfer/transfer.js → actions/transfer/action.js} +2 -2
  137. package/lib/commands/actions/transfer/command.js +115 -0
  138. package/lib/commands/{ts/generate-types.js → actions/ts/generate-types/action.js} +2 -2
  139. package/lib/commands/actions/ts/generate-types/command.js +21 -0
  140. package/lib/commands/{uninstall.js → actions/uninstall/action.js} +1 -1
  141. package/lib/commands/actions/uninstall/command.js +15 -0
  142. package/lib/commands/actions/version/command.js +19 -0
  143. package/lib/commands/{watchAdmin.js → actions/watch-admin/action.js} +4 -4
  144. package/lib/commands/actions/watch-admin/command.js +15 -0
  145. package/lib/commands/index.js +66 -0
  146. package/lib/commands/{transfer/utils.js → utils/data-transfer.js} +2 -2
  147. package/lib/commands/utils/helpers.js +54 -3
  148. package/lib/core/registries/__tests__/custom-fields.test.js +152 -0
  149. package/lib/core/registries/custom-fields.js +19 -2
  150. package/lib/core-api/__tests__/controller.test.js +39 -0
  151. package/lib/core-api/controller/__tests__/transform.test.js +226 -0
  152. package/lib/core-api/service/__tests__/index.test.js +127 -0
  153. package/lib/core-api/service/__tests__/pagination.test.js +275 -0
  154. package/lib/load/__tests__/filepath-to-prop-path.test.js +30 -0
  155. package/lib/middlewares/__tests__/errors.test.js +21 -0
  156. package/lib/services/__tests__/content-api-permissions.test.js +291 -0
  157. package/lib/services/__tests__/core-store.test.js +148 -0
  158. package/lib/services/__tests__/event-hub.test.js +126 -0
  159. package/lib/services/__tests__/fs.test.js +78 -0
  160. package/lib/services/__tests__/worker-queue.test.js +47 -0
  161. package/lib/services/entity-service/__tests__/entity-service-events.test.js +117 -0
  162. package/lib/services/entity-service/__tests__/entity-service.test.js +587 -0
  163. package/lib/services/entity-validator/__tests__/biginteger-validators.test.js +220 -0
  164. package/lib/services/entity-validator/__tests__/date-validators.test.js +183 -0
  165. package/lib/services/entity-validator/__tests__/datetime-validators.test.js +183 -0
  166. package/lib/services/entity-validator/__tests__/email-validators.test.js +56 -0
  167. package/lib/services/entity-validator/__tests__/enumeration-validators.test.js +43 -0
  168. package/lib/services/entity-validator/__tests__/float-validators.test.js +278 -0
  169. package/lib/services/entity-validator/__tests__/index.test.js +609 -0
  170. package/lib/services/entity-validator/__tests__/integer-validators.test.js +278 -0
  171. package/lib/services/entity-validator/__tests__/relations/attribute-level.test.js +123 -0
  172. package/lib/services/entity-validator/__tests__/relations/component-level.test.js +275 -0
  173. package/lib/services/entity-validator/__tests__/relations/dynamic-zone-level.test.js +159 -0
  174. package/lib/services/entity-validator/__tests__/relations/media-level.test.js +74 -0
  175. package/lib/services/entity-validator/__tests__/relations/utils/relations.testdata.js +153 -0
  176. package/lib/services/entity-validator/__tests__/string-validators.test.js +374 -0
  177. package/lib/services/entity-validator/__tests__/time-validators.test.js +183 -0
  178. package/lib/services/entity-validator/__tests__/timestamp-validators.test.js +204 -0
  179. package/lib/services/entity-validator/__tests__/uid-validators.test.js +229 -0
  180. package/lib/services/metrics/__tests__/admin-user-hash.test.js +41 -0
  181. package/lib/services/metrics/__tests__/index.test.js +157 -0
  182. package/lib/services/metrics/__tests__/is-truthy.js +33 -0
  183. package/lib/services/metrics/__tests__/middleware.test.js +60 -0
  184. package/lib/services/metrics/__tests__/rate-limiter.test.js +50 -0
  185. package/lib/services/metrics/__tests__/stringify-deep.test.js +27 -0
  186. package/lib/services/metrics/sender.js +1 -2
  187. package/lib/services/webhook-runner.js +4 -4
  188. package/lib/types/core/commands/index.d.ts +6 -0
  189. package/lib/utils/__tests__/convert-custom-field-type.test.js +69 -0
  190. package/lib/utils/__tests__/url-from-segments.test.js +40 -0
  191. package/lib/utils/fetch.js +23 -0
  192. package/package.json +17 -16
  193. /package/lib/commands/{generate-template.js → actions/templates/generate/action.js} +0 -0
@@ -0,0 +1,152 @@
1
+ 'use strict';
2
+
3
+ const customFieldsRegistry = require('../custom-fields');
4
+
5
+ const strapi = {
6
+ plugins: { plugintest: 'foo' },
7
+ plugin: jest.fn((plugin) => strapi.plugins[plugin]),
8
+ };
9
+
10
+ describe('Custom fields registry', () => {
11
+ describe('add', () => {
12
+ it('adds a custom field registered in a plugin', () => {
13
+ const mockCF = {
14
+ name: 'test',
15
+ plugin: 'plugintest',
16
+ type: 'text',
17
+ };
18
+
19
+ const customFields = customFieldsRegistry(strapi);
20
+ customFields.add(mockCF);
21
+
22
+ const expected = {
23
+ 'plugin::plugintest.test': mockCF,
24
+ };
25
+ expect(customFields.getAll()).toEqual(expected);
26
+ });
27
+
28
+ it('adds a custom field not registered in a plugin', () => {
29
+ const mockCF = {
30
+ name: 'test',
31
+ type: 'text',
32
+ };
33
+
34
+ const customFields = customFieldsRegistry(strapi);
35
+ customFields.add(mockCF);
36
+
37
+ const expected = {
38
+ 'global::test': mockCF,
39
+ };
40
+ expect(customFields.getAll()).toEqual(expected);
41
+ });
42
+
43
+ it('requires a name key on the custom field', () => {
44
+ const mockCF = {
45
+ type: 'test',
46
+ };
47
+
48
+ const customFields = customFieldsRegistry(strapi);
49
+
50
+ expect(() => customFields.add(mockCF)).toThrowError(
51
+ `Custom fields require a 'name' and 'type' key`
52
+ );
53
+ });
54
+
55
+ it('requires a type key on the custom field', () => {
56
+ const mockCF = {
57
+ name: 'test',
58
+ };
59
+
60
+ const customFields = customFieldsRegistry(strapi);
61
+
62
+ expect(() => customFields.add(mockCF)).toThrowError(
63
+ `Custom fields require a 'name' and 'type' key`
64
+ );
65
+ });
66
+
67
+ it('validates the name can be used as an object key', () => {
68
+ const mockCF = {
69
+ name: 'test.boom',
70
+ type: 'text',
71
+ };
72
+
73
+ const customFields = customFieldsRegistry(strapi);
74
+
75
+ expect(() => customFields.add(mockCF)).toThrowError(
76
+ `Custom field name: 'test.boom' is not a valid object key`
77
+ );
78
+ });
79
+
80
+ it('validates the type is a Strapi type', () => {
81
+ const mockCF = {
82
+ name: 'test',
83
+ type: 'geojson',
84
+ };
85
+
86
+ const customFields = customFieldsRegistry(strapi);
87
+
88
+ expect(() => customFields.add(mockCF)).toThrowError(
89
+ `Custom field type: 'geojson' is not a valid Strapi type`
90
+ );
91
+ });
92
+
93
+ it('validates inputSize', () => {
94
+ const mockCF = {
95
+ name: 'test',
96
+ type: 'text',
97
+ };
98
+
99
+ const customFields = customFieldsRegistry(strapi);
100
+
101
+ expect(() => customFields.add({ ...mockCF, inputSize: 'small' })).toThrowError(
102
+ `inputSize should be an object with 'default' and 'isResizable' keys`
103
+ );
104
+ expect(() => customFields.add({ ...mockCF, inputSize: ['array'] })).toThrowError(
105
+ `inputSize should be an object with 'default' and 'isResizable' keys`
106
+ );
107
+ expect(() =>
108
+ customFields.add({ ...mockCF, inputSize: { default: 99, isResizable: true } })
109
+ ).toThrowError('Custom fields require a valid default input size');
110
+ expect(() =>
111
+ customFields.add({ ...mockCF, inputSize: { default: 12, isResizable: 'true' } })
112
+ ).toThrowError('Custom fields should specify if their input is resizable');
113
+ });
114
+
115
+ it('confirms the custom field does not already exist', () => {
116
+ const mockCF = {
117
+ name: 'test',
118
+ plugin: 'plugintest',
119
+ type: 'text',
120
+ };
121
+
122
+ const customFields = customFieldsRegistry(strapi);
123
+
124
+ customFields.add(mockCF);
125
+ expect(() => customFields.add(mockCF)).toThrowError(
126
+ `Custom field: 'plugin::plugintest.test' has already been registered`
127
+ );
128
+ });
129
+ });
130
+ describe('get', () => {
131
+ it('gets a registered custom field', () => {
132
+ const mockCF = {
133
+ name: 'test',
134
+ plugin: 'plugintest',
135
+ type: 'text',
136
+ };
137
+
138
+ const customFields = customFieldsRegistry(strapi);
139
+ customFields.add(mockCF);
140
+
141
+ expect(customFields.get('plugin::plugintest.test')).toEqual(mockCF);
142
+ });
143
+
144
+ it('throws when a custom field is not registered', () => {
145
+ const customFields = customFieldsRegistry(strapi);
146
+
147
+ expect(() => customFields.get('plugin::plugintest.test')).toThrowError(
148
+ `Could not find Custom Field: plugin::plugintest.test`
149
+ );
150
+ });
151
+ });
152
+ });
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { has } = require('lodash/fp');
3
+ const { has, isPlainObject } = require('lodash/fp');
4
4
 
5
5
  const ALLOWED_TYPES = [
6
6
  'biginteger',
@@ -44,7 +44,7 @@ const customFieldsRegistry = (strapi) => {
44
44
  throw new Error(`Custom fields require a 'name' and 'type' key`);
45
45
  }
46
46
 
47
- const { name, plugin, type } = cf;
47
+ const { name, plugin, type, inputSize } = cf;
48
48
  if (!ALLOWED_TYPES.includes(type)) {
49
49
  throw new Error(
50
50
  `Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`
@@ -56,6 +56,23 @@ const customFieldsRegistry = (strapi) => {
56
56
  throw new Error(`Custom field name: '${name}' is not a valid object key`);
57
57
  }
58
58
 
59
+ // Validate inputSize when provided
60
+ if (inputSize) {
61
+ if (
62
+ !isPlainObject(inputSize) ||
63
+ !has('default', inputSize) ||
64
+ !has('isResizable', inputSize)
65
+ ) {
66
+ throw new Error(`inputSize should be an object with 'default' and 'isResizable' keys`);
67
+ }
68
+ if (![4, 6, 8, 12].includes(inputSize.default)) {
69
+ throw new Error('Custom fields require a valid default input size');
70
+ }
71
+ if (typeof inputSize.isResizable !== 'boolean') {
72
+ throw new Error('Custom fields should specify if their input is resizable');
73
+ }
74
+ }
75
+
59
76
  // When no plugin is specified, or it isn't found in Strapi, default to global
60
77
  const uid = strapi.plugin(plugin) ? `plugin::${plugin}.${name}` : `global::${name}`;
61
78
 
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const { createController } = require('../controller');
4
+
5
+ describe('Default Controller', () => {
6
+ test('Creates Collection Type default actions', () => {
7
+ const service = {};
8
+ const contentType = {
9
+ modelName: 'testModel',
10
+ kind: 'collectionType',
11
+ };
12
+
13
+ const controller = createController({ service, contentType });
14
+
15
+ expect(controller).toEqual({
16
+ find: expect.any(Function),
17
+ findOne: expect.any(Function),
18
+ create: expect.any(Function),
19
+ update: expect.any(Function),
20
+ delete: expect.any(Function),
21
+ });
22
+ });
23
+
24
+ test('Creates Single Type default actions', () => {
25
+ const service = {};
26
+ const contentType = {
27
+ modelName: 'testModel',
28
+ kind: 'singleType',
29
+ };
30
+
31
+ const controller = createController({ service, contentType });
32
+
33
+ expect(controller).toEqual({
34
+ find: expect.any(Function),
35
+ update: expect.any(Function),
36
+ delete: expect.any(Function),
37
+ });
38
+ });
39
+ });
@@ -0,0 +1,226 @@
1
+ 'use strict';
2
+
3
+ const transforms = require('../transform');
4
+
5
+ describe('Transforms', () => {
6
+ test('Leaves nil values untouched', () => {
7
+ expect(transforms.transformResponse()).toBeUndefined();
8
+ expect(transforms.transformResponse(null)).toBe(null);
9
+ });
10
+
11
+ test('Throws if entry is not and object or an array of object', () => {
12
+ expect(() => transforms.transformResponse(0)).toThrow();
13
+ expect(() => transforms.transformResponse(new Date())).toThrow();
14
+ expect(() => transforms.transformResponse('azaz')).toThrow();
15
+ });
16
+
17
+ test('Handles arrays of entries', () => {
18
+ expect(transforms.transformResponse([{ id: 1, title: 'Hello' }])).toStrictEqual({
19
+ data: [{ id: 1, attributes: { title: 'Hello' } }],
20
+ meta: {},
21
+ });
22
+ });
23
+
24
+ test('Handles single entry', () => {
25
+ expect(transforms.transformResponse({ id: 1, title: 'Hello' })).toStrictEqual({
26
+ data: { id: 1, attributes: { title: 'Hello' } },
27
+ meta: {},
28
+ });
29
+ });
30
+
31
+ test('Accepts any meta', () => {
32
+ const someMeta = { foo: 'bar' };
33
+ expect(transforms.transformResponse({ id: 1, title: 'Hello' }, someMeta)).toStrictEqual({
34
+ data: { id: 1, attributes: { title: 'Hello' } },
35
+ meta: someMeta,
36
+ });
37
+ });
38
+
39
+ test('Handles relations single value', () => {
40
+ const contentType = {
41
+ attributes: {
42
+ relation: {
43
+ type: 'relation',
44
+ target: 'xxx',
45
+ },
46
+ },
47
+ };
48
+
49
+ global.strapi = {
50
+ contentType() {
51
+ return undefined;
52
+ },
53
+ };
54
+
55
+ expect(
56
+ transforms.transformResponse(
57
+ { id: 1, title: 'Hello', relation: { id: 1, value: 'test' } },
58
+ undefined,
59
+ { contentType }
60
+ )
61
+ ).toStrictEqual({
62
+ data: {
63
+ id: 1,
64
+ attributes: {
65
+ title: 'Hello',
66
+ relation: {
67
+ data: {
68
+ id: 1,
69
+ attributes: {
70
+ value: 'test',
71
+ },
72
+ },
73
+ },
74
+ },
75
+ },
76
+ meta: {},
77
+ });
78
+ });
79
+
80
+ test('Handles relations array value', () => {
81
+ const contentType = {
82
+ attributes: {
83
+ relation: {
84
+ type: 'relation',
85
+ target: 'xxx',
86
+ },
87
+ },
88
+ };
89
+
90
+ global.strapi = {
91
+ contentType() {
92
+ return undefined;
93
+ },
94
+ };
95
+
96
+ expect(
97
+ transforms.transformResponse(
98
+ { id: 1, title: 'Hello', relation: [{ id: 1, value: 'test' }] },
99
+ undefined,
100
+ { contentType }
101
+ )
102
+ ).toStrictEqual({
103
+ data: {
104
+ id: 1,
105
+ attributes: {
106
+ title: 'Hello',
107
+ relation: {
108
+ data: [
109
+ {
110
+ id: 1,
111
+ attributes: {
112
+ value: 'test',
113
+ },
114
+ },
115
+ ],
116
+ },
117
+ },
118
+ },
119
+ meta: {},
120
+ });
121
+ });
122
+
123
+ test('Handles relations recursively', () => {
124
+ const contentType = {
125
+ attributes: {
126
+ relation: {
127
+ type: 'relation',
128
+ target: 'xxx',
129
+ },
130
+ },
131
+ };
132
+
133
+ global.strapi = {
134
+ contentType() {
135
+ return {
136
+ attributes: {
137
+ nestedRelation: {
138
+ type: 'relation',
139
+ target: 'xxxx',
140
+ },
141
+ },
142
+ };
143
+ },
144
+ };
145
+
146
+ expect(
147
+ transforms.transformResponse(
148
+ {
149
+ id: 1,
150
+ title: 'Hello',
151
+ relation: [{ id: 1, value: 'test', nestedRelation: { id: 2, foo: 'bar' } }],
152
+ },
153
+ undefined,
154
+ { contentType }
155
+ )
156
+ ).toStrictEqual({
157
+ data: {
158
+ id: 1,
159
+ attributes: {
160
+ title: 'Hello',
161
+ relation: {
162
+ data: [
163
+ {
164
+ id: 1,
165
+ attributes: {
166
+ value: 'test',
167
+ nestedRelation: {
168
+ data: {
169
+ id: 2,
170
+ attributes: {
171
+ foo: 'bar',
172
+ },
173
+ },
174
+ },
175
+ },
176
+ },
177
+ ],
178
+ },
179
+ },
180
+ },
181
+ meta: {},
182
+ });
183
+ });
184
+
185
+ test('Handles media like relations', () => {
186
+ const contentType = {
187
+ attributes: {
188
+ media: {
189
+ type: 'media',
190
+ },
191
+ },
192
+ };
193
+
194
+ global.strapi = {
195
+ contentType() {
196
+ return undefined;
197
+ },
198
+ };
199
+
200
+ expect(
201
+ transforms.transformResponse(
202
+ { id: 1, title: 'Hello', media: [{ id: 1, value: 'test' }] },
203
+ undefined,
204
+ { contentType }
205
+ )
206
+ ).toStrictEqual({
207
+ data: {
208
+ id: 1,
209
+ attributes: {
210
+ title: 'Hello',
211
+ media: {
212
+ data: [
213
+ {
214
+ id: 1,
215
+ attributes: {
216
+ value: 'test',
217
+ },
218
+ },
219
+ ],
220
+ },
221
+ },
222
+ },
223
+ meta: {},
224
+ });
225
+ });
226
+ });
@@ -0,0 +1,127 @@
1
+ 'use strict';
2
+
3
+ const { createService } = require('../index');
4
+
5
+ describe('Default Service', () => {
6
+ describe('Collection Type', () => {
7
+ test('Creates default actions', () => {
8
+ const contentType = {
9
+ modelName: 'testModel',
10
+ kind: 'collectionType',
11
+ };
12
+
13
+ const service = createService({ contentType });
14
+
15
+ expect(service).toEqual({
16
+ find: expect.any(Function),
17
+ findOne: expect.any(Function),
18
+ create: expect.any(Function),
19
+ update: expect.any(Function),
20
+ delete: expect.any(Function),
21
+ });
22
+ });
23
+ });
24
+
25
+ describe('Single Type', () => {
26
+ test('Creates default actions', () => {
27
+ const contentType = {
28
+ modelName: 'testModel',
29
+ kind: 'singleType',
30
+ };
31
+
32
+ const service = createService({ contentType });
33
+
34
+ expect(service).toEqual({
35
+ find: expect.any(Function),
36
+ createOrUpdate: expect.any(Function),
37
+ delete: expect.any(Function),
38
+ });
39
+ });
40
+
41
+ describe('Passes the logic down to the entityService', () => {
42
+ test('Creates data when no entity is found', async () => {
43
+ global.strapi = {
44
+ entityService: {
45
+ findMany: jest.fn(() => Promise.resolve(null)),
46
+ create: jest.fn(() => Promise.resolve({ id: 1 })),
47
+ },
48
+ query() {
49
+ return { count() {} };
50
+ },
51
+ };
52
+
53
+ const contentType = {
54
+ uid: 'testModel',
55
+ kind: 'singleType',
56
+ };
57
+
58
+ const service = createService({ contentType });
59
+
60
+ const input = {};
61
+ await service.createOrUpdate({ data: input });
62
+
63
+ expect(strapi.entityService.findMany).toHaveBeenCalledWith('testModel', {
64
+ publicationState: 'preview',
65
+ });
66
+
67
+ expect(strapi.entityService.create).toHaveBeenCalledWith('testModel', { data: input });
68
+ });
69
+
70
+ test('Updates data when entity is found', async () => {
71
+ global.strapi = {
72
+ entityService: {
73
+ findMany: jest.fn(() => Promise.resolve({ id: 1 })),
74
+ update: jest.fn(() => Promise.resolve({ id: 1 })),
75
+ },
76
+ query() {
77
+ return { count() {} };
78
+ },
79
+ };
80
+
81
+ const contentType = {
82
+ uid: 'testModel',
83
+ kind: 'singleType',
84
+ };
85
+
86
+ const service = createService({ contentType });
87
+
88
+ const input = {};
89
+ await service.createOrUpdate({ data: input });
90
+
91
+ expect(strapi.entityService.findMany).toHaveBeenCalledWith('testModel', {
92
+ populate: undefined,
93
+ publicationState: 'preview',
94
+ });
95
+
96
+ expect(strapi.entityService.update).toHaveBeenCalledWith('testModel', 1, {
97
+ data: input,
98
+ });
99
+ });
100
+
101
+ test('Delete data when entity is found', async () => {
102
+ global.strapi = {
103
+ entityService: {
104
+ findMany: jest.fn(() => Promise.resolve({ id: 1 })),
105
+ delete: jest.fn(() => Promise.resolve({ id: 1 })),
106
+ },
107
+ };
108
+
109
+ const contentType = {
110
+ uid: 'testModel',
111
+ kind: 'singleType',
112
+ };
113
+
114
+ const service = createService({ contentType });
115
+
116
+ await service.delete();
117
+
118
+ expect(strapi.entityService.findMany).toHaveBeenCalledWith('testModel', {
119
+ populate: undefined,
120
+ publicationState: 'live',
121
+ });
122
+
123
+ expect(strapi.entityService.delete).toHaveBeenCalledWith('testModel', 1);
124
+ });
125
+ });
126
+ });
127
+ });