@flusys/nestjs-form-builder 6.0.1 → 6.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/cjs/controllers/form-result.controller.spec.js +257 -0
- package/cjs/controllers/form.controller.spec.js +212 -0
- package/cjs/docs/form-builder-swagger.config.spec.js +75 -0
- package/cjs/entities/index.spec.js +18 -0
- package/cjs/modules/form-builder.module.spec.js +133 -0
- package/cjs/services/form-builder-config.service.spec.js +121 -0
- package/cjs/services/form-builder-datasource.provider.spec.js +147 -0
- package/cjs/services/form-result.service.spec.js +702 -0
- package/cjs/services/form.service.spec.js +746 -0
- package/cjs/utils/computed-field.utils.spec.js +1205 -0
- package/cjs/utils/permission.utils.spec.js +118 -0
- package/fesm/controllers/form-result.controller.spec.js +253 -0
- package/fesm/controllers/form.controller.spec.js +208 -0
- package/fesm/docs/form-builder-swagger.config.spec.js +71 -0
- package/fesm/entities/index.spec.js +14 -0
- package/fesm/modules/form-builder.module.spec.js +129 -0
- package/fesm/services/form-builder-config.service.spec.js +117 -0
- package/fesm/services/form-builder-datasource.provider.spec.js +143 -0
- package/fesm/services/form-result.service.spec.js +657 -0
- package/fesm/services/form.service.spec.js +701 -0
- package/fesm/utils/computed-field.utils.spec.js +1201 -0
- package/fesm/utils/permission.utils.spec.js +114 -0
- package/package.json +3 -3
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _testing = require("@nestjs/testing");
|
|
6
|
+
const _modules = require("@flusys/nestjs-shared/modules");
|
|
7
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
8
|
+
const _formresultcontroller = require("./form-result.controller");
|
|
9
|
+
const _formresultservice = require("../services/form-result.service");
|
|
10
|
+
function buildResultDto(overrides = {}) {
|
|
11
|
+
return {
|
|
12
|
+
id: 'result-1',
|
|
13
|
+
formId: 'form-1',
|
|
14
|
+
schemaVersionSnapshot: {
|
|
15
|
+
sections: []
|
|
16
|
+
},
|
|
17
|
+
schemaVersion: 1,
|
|
18
|
+
data: {
|
|
19
|
+
field1: 'value1'
|
|
20
|
+
},
|
|
21
|
+
submittedById: 'user-uuid-1',
|
|
22
|
+
submittedAt: new Date(),
|
|
23
|
+
isDraft: false,
|
|
24
|
+
createdAt: new Date(),
|
|
25
|
+
updatedAt: new Date(),
|
|
26
|
+
deletedAt: null,
|
|
27
|
+
createdById: null,
|
|
28
|
+
updatedById: null,
|
|
29
|
+
deletedById: null,
|
|
30
|
+
...overrides
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
describe('FormResultController', ()=>{
|
|
34
|
+
let controller;
|
|
35
|
+
let mockService;
|
|
36
|
+
beforeEach(async ()=>{
|
|
37
|
+
mockService = {
|
|
38
|
+
insert: jest.fn(),
|
|
39
|
+
insertMany: jest.fn(),
|
|
40
|
+
findById: jest.fn(),
|
|
41
|
+
findByIds: jest.fn(),
|
|
42
|
+
getAll: jest.fn(),
|
|
43
|
+
update: jest.fn(),
|
|
44
|
+
updateMany: jest.fn(),
|
|
45
|
+
delete: jest.fn(),
|
|
46
|
+
submitForm: jest.fn(),
|
|
47
|
+
getMyDraft: jest.fn(),
|
|
48
|
+
updateDraft: jest.fn(),
|
|
49
|
+
getByFormId: jest.fn(),
|
|
50
|
+
hasUserSubmitted: jest.fn()
|
|
51
|
+
};
|
|
52
|
+
const module = await _testing.Test.createTestingModule({
|
|
53
|
+
controllers: [
|
|
54
|
+
_formresultcontroller.FormResultController
|
|
55
|
+
],
|
|
56
|
+
// UtilsService is a real (dependency-free) provider — required to satisfy the
|
|
57
|
+
// Slug interceptor applied by the inherited insert/update endpoints.
|
|
58
|
+
providers: [
|
|
59
|
+
{
|
|
60
|
+
provide: _formresultservice.FormResultService,
|
|
61
|
+
useValue: mockService
|
|
62
|
+
},
|
|
63
|
+
_modules.UtilsService
|
|
64
|
+
]
|
|
65
|
+
}).compile();
|
|
66
|
+
controller = module.get(_formresultcontroller.FormResultController);
|
|
67
|
+
});
|
|
68
|
+
afterEach(()=>{
|
|
69
|
+
jest.clearAllMocks();
|
|
70
|
+
});
|
|
71
|
+
describe('submitForm', ()=>{
|
|
72
|
+
it('submits on behalf of the authenticated user (isPublic=false)', async ()=>{
|
|
73
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
74
|
+
mockService.submitForm.mockResolvedValue(buildResultDto());
|
|
75
|
+
const result = await controller.submitForm({
|
|
76
|
+
formId: 'form-1',
|
|
77
|
+
data: {
|
|
78
|
+
field1: 'value1'
|
|
79
|
+
}
|
|
80
|
+
}, user);
|
|
81
|
+
expect(mockService.submitForm).toHaveBeenCalledWith({
|
|
82
|
+
formId: 'form-1',
|
|
83
|
+
data: {
|
|
84
|
+
field1: 'value1'
|
|
85
|
+
}
|
|
86
|
+
}, user, false);
|
|
87
|
+
expect(result).toEqual({
|
|
88
|
+
success: true,
|
|
89
|
+
message: 'Form submitted successfully',
|
|
90
|
+
messageKey: 'form.result.submit.success',
|
|
91
|
+
data: expect.objectContaining({
|
|
92
|
+
id: 'result-1'
|
|
93
|
+
})
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
it('propagates errors from the service (e.g. permission denied)', async ()=>{
|
|
97
|
+
mockService.submitForm.mockRejectedValue(Object.assign(new Error('denied'), {
|
|
98
|
+
messageKey: 'form.access.denied'
|
|
99
|
+
}));
|
|
100
|
+
await expect(controller.submitForm({
|
|
101
|
+
formId: 'form-1',
|
|
102
|
+
data: {}
|
|
103
|
+
}, (0, _loggedusermock.buildMockUser)())).rejects.toThrow();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe('submitPublicForm', ()=>{
|
|
107
|
+
it('submits without a user and marks the submission as public', async ()=>{
|
|
108
|
+
mockService.submitForm.mockResolvedValue(buildResultDto({
|
|
109
|
+
submittedById: null
|
|
110
|
+
}));
|
|
111
|
+
const result = await controller.submitPublicForm({
|
|
112
|
+
formId: 'form-1',
|
|
113
|
+
data: {}
|
|
114
|
+
});
|
|
115
|
+
expect(mockService.submitForm).toHaveBeenCalledWith({
|
|
116
|
+
formId: 'form-1',
|
|
117
|
+
data: {}
|
|
118
|
+
}, null, true);
|
|
119
|
+
expect(result.data.submittedById).toBeNull();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('getMyDraft', ()=>{
|
|
123
|
+
it('returns the current draft for the user', async ()=>{
|
|
124
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
125
|
+
mockService.getMyDraft.mockResolvedValue(buildResultDto({
|
|
126
|
+
isDraft: true
|
|
127
|
+
}));
|
|
128
|
+
const result = await controller.getMyDraft({
|
|
129
|
+
formId: 'form-1'
|
|
130
|
+
}, user);
|
|
131
|
+
expect(mockService.getMyDraft).toHaveBeenCalledWith('form-1', user);
|
|
132
|
+
expect(result.data?.isDraft).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
it('returns null data when no draft exists', async ()=>{
|
|
135
|
+
mockService.getMyDraft.mockResolvedValue(null);
|
|
136
|
+
const result = await controller.getMyDraft({
|
|
137
|
+
formId: 'form-1'
|
|
138
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
139
|
+
expect(result.data).toBeNull();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('updateDraft', ()=>{
|
|
143
|
+
it('updates the identified draft', async ()=>{
|
|
144
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
145
|
+
mockService.updateDraft.mockResolvedValue(buildResultDto({
|
|
146
|
+
isDraft: true
|
|
147
|
+
}));
|
|
148
|
+
const result = await controller.updateDraft({
|
|
149
|
+
draftId: 'draft-1',
|
|
150
|
+
formId: 'form-1',
|
|
151
|
+
data: {
|
|
152
|
+
field1: 'new'
|
|
153
|
+
}
|
|
154
|
+
}, user);
|
|
155
|
+
expect(mockService.updateDraft).toHaveBeenCalledWith('draft-1', {
|
|
156
|
+
draftId: 'draft-1',
|
|
157
|
+
formId: 'form-1',
|
|
158
|
+
data: {
|
|
159
|
+
field1: 'new'
|
|
160
|
+
}
|
|
161
|
+
}, user);
|
|
162
|
+
expect(result.success).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('getByFormId', ()=>{
|
|
166
|
+
it('returns paginated results with the requested page/pageSize', async ()=>{
|
|
167
|
+
mockService.getByFormId.mockResolvedValue({
|
|
168
|
+
data: [
|
|
169
|
+
buildResultDto()
|
|
170
|
+
],
|
|
171
|
+
total: 1
|
|
172
|
+
});
|
|
173
|
+
const result = await controller.getByFormId({
|
|
174
|
+
formId: 'form-1',
|
|
175
|
+
page: 1,
|
|
176
|
+
pageSize: 5
|
|
177
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
178
|
+
expect(mockService.getByFormId).toHaveBeenCalledWith('form-1', expect.any(Object), {
|
|
179
|
+
page: 1,
|
|
180
|
+
pageSize: 5
|
|
181
|
+
});
|
|
182
|
+
expect(result.meta).toEqual({
|
|
183
|
+
total: 1,
|
|
184
|
+
page: 1,
|
|
185
|
+
pageSize: 5,
|
|
186
|
+
count: 1
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
it('defaults to page 0 and pageSize 10 when not provided', async ()=>{
|
|
190
|
+
mockService.getByFormId.mockResolvedValue({
|
|
191
|
+
data: [],
|
|
192
|
+
total: 0
|
|
193
|
+
});
|
|
194
|
+
const result = await controller.getByFormId({
|
|
195
|
+
formId: 'form-1'
|
|
196
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
197
|
+
expect(mockService.getByFormId).toHaveBeenCalledWith('form-1', expect.any(Object), {
|
|
198
|
+
page: 0,
|
|
199
|
+
pageSize: 10
|
|
200
|
+
});
|
|
201
|
+
expect(result.meta).toEqual({
|
|
202
|
+
total: 0,
|
|
203
|
+
page: 0,
|
|
204
|
+
pageSize: 10,
|
|
205
|
+
count: 0
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
describe('hasUserSubmitted', ()=>{
|
|
210
|
+
it('returns a truthy submitted message when the user has submitted', async ()=>{
|
|
211
|
+
mockService.hasUserSubmitted.mockResolvedValue(true);
|
|
212
|
+
const result = await controller.hasUserSubmitted({
|
|
213
|
+
formId: 'form-1'
|
|
214
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
215
|
+
expect(result).toEqual({
|
|
216
|
+
success: true,
|
|
217
|
+
message: 'User has submitted this form',
|
|
218
|
+
messageKey: 'form.result.has.submitted.success',
|
|
219
|
+
data: true
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
it('returns a not-submitted message when the user has not submitted', async ()=>{
|
|
223
|
+
mockService.hasUserSubmitted.mockResolvedValue(false);
|
|
224
|
+
const result = await controller.hasUserSubmitted({
|
|
225
|
+
formId: 'form-1'
|
|
226
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
227
|
+
expect(result).toEqual({
|
|
228
|
+
success: true,
|
|
229
|
+
message: 'User has not submitted this form',
|
|
230
|
+
messageKey: 'form.result.has.not.submitted.success',
|
|
231
|
+
data: false
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
// ==========================================================================
|
|
236
|
+
// Inherited base CRUD wiring (createApiController)
|
|
237
|
+
// ==========================================================================
|
|
238
|
+
describe('inherited CRUD endpoints', ()=>{
|
|
239
|
+
it('delete delegates to FormResultService.delete', async ()=>{
|
|
240
|
+
mockService.delete.mockResolvedValue(null);
|
|
241
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
242
|
+
const result = await controller.delete({
|
|
243
|
+
id: [
|
|
244
|
+
'result-1'
|
|
245
|
+
],
|
|
246
|
+
type: 'delete'
|
|
247
|
+
}, user);
|
|
248
|
+
expect(mockService.delete).toHaveBeenCalledWith({
|
|
249
|
+
id: [
|
|
250
|
+
'result-1'
|
|
251
|
+
],
|
|
252
|
+
type: 'delete'
|
|
253
|
+
}, user);
|
|
254
|
+
expect(result.success).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _testing = require("@nestjs/testing");
|
|
6
|
+
const _modules = require("@flusys/nestjs-shared/modules");
|
|
7
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
8
|
+
const _formaccesstypeenum = require("../enums/form-access-type.enum");
|
|
9
|
+
const _formcontroller = require("./form.controller");
|
|
10
|
+
const _formservice = require("../services/form.service");
|
|
11
|
+
describe('FormController', ()=>{
|
|
12
|
+
let controller;
|
|
13
|
+
let mockService;
|
|
14
|
+
beforeEach(async ()=>{
|
|
15
|
+
mockService = {
|
|
16
|
+
insert: jest.fn(),
|
|
17
|
+
insertMany: jest.fn(),
|
|
18
|
+
findById: jest.fn(),
|
|
19
|
+
findByIds: jest.fn(),
|
|
20
|
+
getAll: jest.fn(),
|
|
21
|
+
update: jest.fn(),
|
|
22
|
+
updateMany: jest.fn(),
|
|
23
|
+
delete: jest.fn(),
|
|
24
|
+
getFormAccessInfo: jest.fn(),
|
|
25
|
+
getPublicForm: jest.fn(),
|
|
26
|
+
getAuthenticatedForm: jest.fn(),
|
|
27
|
+
getBySlug: jest.fn(),
|
|
28
|
+
getPublicFormBySlug: jest.fn()
|
|
29
|
+
};
|
|
30
|
+
const module = await _testing.Test.createTestingModule({
|
|
31
|
+
controllers: [
|
|
32
|
+
_formcontroller.FormController
|
|
33
|
+
],
|
|
34
|
+
// UtilsService is a real (dependency-free) provider — required to satisfy the
|
|
35
|
+
// Slug interceptor applied by the inherited insert/update endpoints.
|
|
36
|
+
providers: [
|
|
37
|
+
{
|
|
38
|
+
provide: _formservice.FormService,
|
|
39
|
+
useValue: mockService
|
|
40
|
+
},
|
|
41
|
+
_modules.UtilsService
|
|
42
|
+
]
|
|
43
|
+
}).compile();
|
|
44
|
+
controller = module.get(_formcontroller.FormController);
|
|
45
|
+
});
|
|
46
|
+
afterEach(()=>{
|
|
47
|
+
jest.clearAllMocks();
|
|
48
|
+
});
|
|
49
|
+
describe('getFormAccessInfo', ()=>{
|
|
50
|
+
it('returns access info without requiring authentication', async ()=>{
|
|
51
|
+
mockService.getFormAccessInfo.mockResolvedValue({
|
|
52
|
+
id: 'form-1',
|
|
53
|
+
name: 'Survey',
|
|
54
|
+
description: null,
|
|
55
|
+
accessType: _formaccesstypeenum.FormAccessType.PUBLIC,
|
|
56
|
+
actionGroups: null,
|
|
57
|
+
isActive: true
|
|
58
|
+
});
|
|
59
|
+
const result = await controller.getFormAccessInfo('form-1');
|
|
60
|
+
expect(result).toEqual({
|
|
61
|
+
success: true,
|
|
62
|
+
message: 'Form access info retrieved',
|
|
63
|
+
messageKey: 'form.get.access.info.success',
|
|
64
|
+
data: expect.objectContaining({
|
|
65
|
+
id: 'form-1',
|
|
66
|
+
accessType: _formaccesstypeenum.FormAccessType.PUBLIC
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
expect(mockService.getFormAccessInfo).toHaveBeenCalledWith('form-1');
|
|
70
|
+
});
|
|
71
|
+
it('propagates NotFoundException raised by the service', async ()=>{
|
|
72
|
+
mockService.getFormAccessInfo.mockRejectedValue(Object.assign(new Error('not found'), {
|
|
73
|
+
messageKey: 'form.not.found'
|
|
74
|
+
}));
|
|
75
|
+
await expect(controller.getFormAccessInfo('missing')).rejects.toThrow();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('getPublicForm', ()=>{
|
|
79
|
+
it('returns the public form projection', async ()=>{
|
|
80
|
+
mockService.getPublicForm.mockResolvedValue({
|
|
81
|
+
id: 'form-1',
|
|
82
|
+
name: 'Survey',
|
|
83
|
+
description: null,
|
|
84
|
+
schema: {
|
|
85
|
+
sections: []
|
|
86
|
+
},
|
|
87
|
+
schemaVersion: 1
|
|
88
|
+
});
|
|
89
|
+
const result = await controller.getPublicForm('form-1');
|
|
90
|
+
expect(result.success).toBe(true);
|
|
91
|
+
expect(result.messageKey).toBe('form.get.success');
|
|
92
|
+
expect(result.data.id).toBe('form-1');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('getAuthenticatedForm', ()=>{
|
|
96
|
+
it('forwards the current user to the service and returns the form', async ()=>{
|
|
97
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
98
|
+
mockService.getAuthenticatedForm.mockResolvedValue({
|
|
99
|
+
id: 'form-1',
|
|
100
|
+
name: 'Survey',
|
|
101
|
+
description: null,
|
|
102
|
+
schema: {},
|
|
103
|
+
schemaVersion: 1
|
|
104
|
+
});
|
|
105
|
+
const result = await controller.getAuthenticatedForm('form-1', user);
|
|
106
|
+
expect(mockService.getAuthenticatedForm).toHaveBeenCalledWith('form-1', user);
|
|
107
|
+
expect(result.data.id).toBe('form-1');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('getBySlug', ()=>{
|
|
111
|
+
it('returns the form when found by slug', async ()=>{
|
|
112
|
+
mockService.getBySlug.mockResolvedValue({
|
|
113
|
+
id: 'form-1',
|
|
114
|
+
name: 'Survey',
|
|
115
|
+
description: null,
|
|
116
|
+
slug: 'survey',
|
|
117
|
+
schema: {},
|
|
118
|
+
schemaVersion: 1,
|
|
119
|
+
accessType: _formaccesstypeenum.FormAccessType.AUTHENTICATED,
|
|
120
|
+
actionGroups: null,
|
|
121
|
+
tags: null,
|
|
122
|
+
companyId: null,
|
|
123
|
+
isActive: true,
|
|
124
|
+
createdAt: new Date(),
|
|
125
|
+
updatedAt: new Date(),
|
|
126
|
+
deletedAt: null,
|
|
127
|
+
createdById: null,
|
|
128
|
+
updatedById: null,
|
|
129
|
+
deletedById: null
|
|
130
|
+
});
|
|
131
|
+
const result = await controller.getBySlug('survey', (0, _loggedusermock.buildMockUser)());
|
|
132
|
+
expect(result.data?.slug).toBe('survey');
|
|
133
|
+
});
|
|
134
|
+
it('returns null data when no form matches the slug', async ()=>{
|
|
135
|
+
mockService.getBySlug.mockResolvedValue(null);
|
|
136
|
+
const result = await controller.getBySlug('missing', (0, _loggedusermock.buildMockUser)());
|
|
137
|
+
expect(result.data).toBeNull();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('getPublicFormBySlug', ()=>{
|
|
141
|
+
it('returns the public form projection when found', async ()=>{
|
|
142
|
+
mockService.getPublicFormBySlug.mockResolvedValue({
|
|
143
|
+
id: 'form-1',
|
|
144
|
+
name: 'Survey',
|
|
145
|
+
description: null,
|
|
146
|
+
schema: {},
|
|
147
|
+
schemaVersion: 1
|
|
148
|
+
});
|
|
149
|
+
const result = await controller.getPublicFormBySlug('survey');
|
|
150
|
+
expect(result.data?.id).toBe('form-1');
|
|
151
|
+
});
|
|
152
|
+
it('returns null data when no public form matches the slug', async ()=>{
|
|
153
|
+
mockService.getPublicFormBySlug.mockResolvedValue(null);
|
|
154
|
+
const result = await controller.getPublicFormBySlug('missing');
|
|
155
|
+
expect(result.data).toBeNull();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
// ==========================================================================
|
|
159
|
+
// Inherited base CRUD wiring (createApiController)
|
|
160
|
+
// ==========================================================================
|
|
161
|
+
describe('inherited CRUD endpoints', ()=>{
|
|
162
|
+
it('insert delegates to FormService.insert and wraps the result', async ()=>{
|
|
163
|
+
mockService.insert.mockResolvedValue({
|
|
164
|
+
id: 'form-1',
|
|
165
|
+
name: 'Survey',
|
|
166
|
+
description: null,
|
|
167
|
+
slug: null,
|
|
168
|
+
schema: {},
|
|
169
|
+
schemaVersion: 1,
|
|
170
|
+
accessType: _formaccesstypeenum.FormAccessType.AUTHENTICATED,
|
|
171
|
+
actionGroups: null,
|
|
172
|
+
tags: null,
|
|
173
|
+
companyId: null,
|
|
174
|
+
isActive: true,
|
|
175
|
+
createdAt: new Date(),
|
|
176
|
+
updatedAt: new Date(),
|
|
177
|
+
deletedAt: null,
|
|
178
|
+
createdById: null,
|
|
179
|
+
updatedById: null,
|
|
180
|
+
deletedById: null
|
|
181
|
+
});
|
|
182
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
183
|
+
const result = await controller.insert({
|
|
184
|
+
name: 'Survey',
|
|
185
|
+
schema: {}
|
|
186
|
+
}, user);
|
|
187
|
+
expect(mockService.insert).toHaveBeenCalledWith({
|
|
188
|
+
name: 'Survey',
|
|
189
|
+
schema: {}
|
|
190
|
+
}, user);
|
|
191
|
+
expect(result.success).toBe(true);
|
|
192
|
+
expect(result.data.name).toBe('Survey');
|
|
193
|
+
});
|
|
194
|
+
it('delete delegates to FormService.delete', async ()=>{
|
|
195
|
+
mockService.delete.mockResolvedValue(null);
|
|
196
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
197
|
+
const result = await controller.delete({
|
|
198
|
+
id: [
|
|
199
|
+
'form-1'
|
|
200
|
+
],
|
|
201
|
+
type: 'delete'
|
|
202
|
+
}, user);
|
|
203
|
+
expect(mockService.delete).toHaveBeenCalledWith({
|
|
204
|
+
id: [
|
|
205
|
+
'form-1'
|
|
206
|
+
],
|
|
207
|
+
type: 'delete'
|
|
208
|
+
}, user);
|
|
209
|
+
expect(result.success).toBe(true);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _formbuilderswaggerconfig = require("./form-builder-swagger.config");
|
|
6
|
+
describe('formBuilderSwaggerConfig', ()=>{
|
|
7
|
+
it('should default to company feature enabled and single-database mode when no config is given', ()=>{
|
|
8
|
+
const config = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)();
|
|
9
|
+
expect(config.title).toBe('Form Builder API');
|
|
10
|
+
expect(config.path).toBe('api/docs/form-builder');
|
|
11
|
+
expect(config.bearerAuth).toBe(true);
|
|
12
|
+
expect(config.excludeTags).toEqual([]);
|
|
13
|
+
expect(config.excludeSchemaProperties).toBeUndefined();
|
|
14
|
+
expect(config.description).not.toContain('Multi-Tenant Mode');
|
|
15
|
+
});
|
|
16
|
+
it('should exclude companyId schema properties when the company feature is disabled', ()=>{
|
|
17
|
+
const config = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)({
|
|
18
|
+
enableCompanyFeature: false
|
|
19
|
+
});
|
|
20
|
+
expect(config.excludeSchemaProperties).toEqual([
|
|
21
|
+
{
|
|
22
|
+
schemaName: 'CreateFormDto',
|
|
23
|
+
properties: [
|
|
24
|
+
'companyId'
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
schemaName: 'UpdateFormDto',
|
|
29
|
+
properties: [
|
|
30
|
+
'companyId'
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
schemaName: 'FormQueryDto',
|
|
35
|
+
properties: [
|
|
36
|
+
'companyId'
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
schemaName: 'FormResponseDto',
|
|
41
|
+
properties: [
|
|
42
|
+
'companyId'
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
it('should not exclude any schema properties when the company feature is enabled', ()=>{
|
|
48
|
+
const config = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)({
|
|
49
|
+
enableCompanyFeature: true
|
|
50
|
+
});
|
|
51
|
+
expect(config.excludeSchemaProperties).toBeUndefined();
|
|
52
|
+
});
|
|
53
|
+
it('should describe company isolation and multi-tenant support only when the company feature is enabled', ()=>{
|
|
54
|
+
const withCompany = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)({
|
|
55
|
+
enableCompanyFeature: true
|
|
56
|
+
});
|
|
57
|
+
const withoutCompany = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)({
|
|
58
|
+
enableCompanyFeature: false
|
|
59
|
+
});
|
|
60
|
+
expect(withCompany.description).toContain('Company isolation');
|
|
61
|
+
expect(withCompany.description).toContain('## Multi-Tenant Support');
|
|
62
|
+
expect(withoutCompany.description).not.toContain('Company isolation');
|
|
63
|
+
expect(withoutCompany.description).not.toContain('## Multi-Tenant Support');
|
|
64
|
+
});
|
|
65
|
+
it('should mention multi-tenant mode in the description only for multi-tenant database mode', ()=>{
|
|
66
|
+
const multiTenant = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)({
|
|
67
|
+
databaseMode: 'multi-tenant'
|
|
68
|
+
});
|
|
69
|
+
const single = (0, _formbuilderswaggerconfig.formBuilderSwaggerConfig)({
|
|
70
|
+
databaseMode: 'single'
|
|
71
|
+
});
|
|
72
|
+
expect(multiTenant.description).toContain('Multi-Tenant Mode');
|
|
73
|
+
expect(single.description).not.toContain('Multi-Tenant Mode');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _index = require("./index");
|
|
6
|
+
const _formresultentity = require("./form-result.entity");
|
|
7
|
+
describe('getFormBuilderEntitiesByConfig', ()=>{
|
|
8
|
+
it('returns the core entities when the company feature is disabled', ()=>{
|
|
9
|
+
expect((0, _index.getFormBuilderEntitiesByConfig)(false)).toBe(_index.FormCoreEntities);
|
|
10
|
+
});
|
|
11
|
+
it('returns the company-scoped entities when the company feature is enabled', ()=>{
|
|
12
|
+
expect((0, _index.getFormBuilderEntitiesByConfig)(true)).toBe(_index.FormCompanyEntities);
|
|
13
|
+
});
|
|
14
|
+
it('FormResult is shared between core and company entity sets (not company-scoped)', ()=>{
|
|
15
|
+
expect((0, _index.getFormBuilderEntitiesByConfig)(false)).toContain(_formresultentity.FormResult);
|
|
16
|
+
expect((0, _index.getFormBuilderEntitiesByConfig)(true)).toContain(_formresultentity.FormResult);
|
|
17
|
+
});
|
|
18
|
+
});
|