Skip to content

Commit 866c8f5

Browse files
authored
Merge pull request #297 from mfikria/dev-296
Improvements for product/project template refactoring issue #296
2 parents 29ed9d4 + bae5000 commit 866c8f5

File tree

9 files changed

+167
-155
lines changed

9 files changed

+167
-155
lines changed

src/routes/productTemplates/create.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ const schema = {
2323
brief: Joi.string().max(45).required(),
2424
details: Joi.string().max(255).required(),
2525
aliases: Joi.array().required(),
26-
template: Joi.object(),
27-
form: Joi.object(),
26+
template: Joi.object().empty(null),
27+
form: Joi.object().empty(null),
2828
disabled: Joi.boolean().optional(),
2929
hidden: Joi.boolean().optional(),
3030
isAddOn: Joi.boolean().optional(),
@@ -34,7 +34,9 @@ const schema = {
3434
createdBy: Joi.any().strip(),
3535
updatedBy: Joi.any().strip(),
3636
deletedBy: Joi.any().strip(),
37-
}).required(),
37+
})
38+
.xor('form', 'template')
39+
.required(),
3840
},
3941
};
4042

src/routes/productTemplates/create.spec.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,18 @@ describe('CREATE product template', () => {
8989
},
9090
};
9191

92-
const bodyWithForm = _.cloneDeep(body);
93-
bodyWithForm.param.form = {
92+
const bodyDefinedFormTemplate = _.cloneDeep(body);
93+
bodyDefinedFormTemplate.param.form = {
9494
version: 1,
9595
key: 'dev',
9696
};
97+
98+
const bodyWithForm = _.cloneDeep(bodyDefinedFormTemplate);
9799
delete bodyWithForm.param.template;
98100

101+
const bodyMissingFormTemplate = _.cloneDeep(bodyWithForm);
102+
delete bodyMissingFormTemplate.param.form;
103+
99104
const bodyInvalidForm = _.cloneDeep(body);
100105
bodyInvalidForm.param.form = {
101106
version: 1,
@@ -277,5 +282,27 @@ describe('CREATE product template', () => {
277282
.send(bodyInvalidForm)
278283
.expect(422, done);
279284
});
285+
286+
it('should return 422 if both form or template field are defined', (done) => {
287+
request(server)
288+
.post('/v4/projects/metadata/productTemplates')
289+
.set({
290+
Authorization: `Bearer ${testUtil.jwts.admin}`,
291+
})
292+
.send(bodyDefinedFormTemplate)
293+
.expect('Content-Type', /json/)
294+
.expect(422, done);
295+
});
296+
297+
it('should return 422 if both form or template field are missing', (done) => {
298+
request(server)
299+
.post('/v4/projects/metadata/productTemplates')
300+
.set({
301+
Authorization: `Bearer ${testUtil.jwts.admin}`,
302+
})
303+
.send(bodyMissingFormTemplate)
304+
.expect('Content-Type', /json/)
305+
.expect(422, done);
306+
});
280307
});
281308
});

src/routes/productTemplates/update.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ const schema = {
2626
brief: Joi.string().max(45),
2727
details: Joi.string().max(255),
2828
aliases: Joi.array(),
29-
template: Joi.object(),
30-
form: Joi.object(),
29+
template: Joi.object().empty(null),
30+
form: Joi.object().empty(null),
3131
disabled: Joi.boolean().optional(),
3232
hidden: Joi.boolean().optional(),
3333
isAddOn: Joi.boolean().optional(),
@@ -37,7 +37,9 @@ const schema = {
3737
createdBy: Joi.any().strip(),
3838
updatedBy: Joi.any().strip(),
3939
deletedBy: Joi.any().strip(),
40-
}).required(),
40+
})
41+
.xor('form', 'template')
42+
.required(),
4143
},
4244
};
4345

src/routes/productTemplates/update.spec.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,18 @@ describe('UPDATE product template', () => {
133133
},
134134
};
135135

136-
const bodyWithForm = _.cloneDeep(body);
137-
bodyWithForm.param.form = {
136+
const bodyDefinedFormTemplate = _.cloneDeep(body);
137+
bodyDefinedFormTemplate.param.form = {
138138
version: 1,
139139
key: 'dev',
140140
};
141141

142+
const bodyWithForm = _.cloneDeep(bodyDefinedFormTemplate);
143+
delete bodyWithForm.param.template;
144+
145+
const bodyMissingFormTemplate = _.cloneDeep(bodyWithForm);
146+
delete bodyMissingFormTemplate.param.form;
147+
142148
const bodyInvalidForm = _.cloneDeep(body);
143149
bodyInvalidForm.param.form = {
144150
version: 1,
@@ -312,5 +318,25 @@ describe('UPDATE product template', () => {
312318
.send(bodyInvalidForm)
313319
.expect(422, done);
314320
});
321+
322+
it('should return 422 if both form or template field are defined', (done) => {
323+
request(server)
324+
.patch(`/v4/projects/metadata/productTemplates/${templateId}`)
325+
.set({
326+
Authorization: `Bearer ${testUtil.jwts.admin}`,
327+
})
328+
.send(bodyDefinedFormTemplate)
329+
.expect(422, done);
330+
});
331+
332+
it('should return 422 if both form or template field are missing', (done) => {
333+
request(server)
334+
.patch(`/v4/projects/metadata/productTemplates/${templateId}`)
335+
.set({
336+
Authorization: `Bearer ${testUtil.jwts.admin}`,
337+
})
338+
.send(bodyMissingFormTemplate)
339+
.expect(422, done);
340+
});
315341
});
316342
});

src/routes/projectTemplates/create.js

Lines changed: 14 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ const schema = {
2222
question: Joi.string().max(255).required(),
2323
info: Joi.string().max(255).required(),
2424
aliases: Joi.array().required(),
25-
scope: Joi.object().optional().allow(null),
26-
phases: Joi.object().optional().allow(null),
27-
form: Joi.object().optional().allow(null),
28-
planConfig: Joi.object().optional().allow(null),
29-
priceConfig: Joi.object().optional().allow(null),
25+
scope: Joi.object().empty(null),
26+
phases: Joi.object().empty(null),
27+
form: Joi.object().empty(null),
28+
planConfig: Joi.object().empty(null),
29+
priceConfig: Joi.object().empty(null),
3030
disabled: Joi.boolean().optional(),
3131
hidden: Joi.boolean().optional(),
3232
createdAt: Joi.any().strip(),
@@ -35,7 +35,11 @@ const schema = {
3535
createdBy: Joi.any().strip(),
3636
updatedBy: Joi.any().strip(),
3737
deletedBy: Joi.any().strip(),
38-
}).required(),
38+
})
39+
.xor('form', 'scope')
40+
.xor('phases', 'planConfig')
41+
.nand('priceConfig', 'scope')
42+
.required(),
3943
},
4044
};
4145

@@ -47,54 +51,12 @@ module.exports = [
4751
const param = req.body.param;
4852
const { form, priceConfig, planConfig } = param;
4953

50-
const checkModel = (keyInfo, modelName, model) => {
51-
let errorMessage = '';
52-
if (keyInfo == null) {
53-
return Promise.resolve(null);
54-
}
55-
if ((keyInfo.version != null) && (keyInfo.key != null)) {
56-
errorMessage = `${modelName} with key ${keyInfo.key} and version ${keyInfo.version}`
57-
+ ' referred in the project template is not found';
58-
return (model.findOne({
59-
where: {
60-
key: keyInfo.key,
61-
version: keyInfo.version,
62-
},
63-
})).then((record) => {
64-
if (record == null) {
65-
return Promise.resolve(errorMessage);
66-
}
67-
return Promise.resolve(null);
68-
});
69-
} else if ((keyInfo.version == null) && (keyInfo.key != null)) {
70-
errorMessage = `${modelName} with key ${keyInfo.key}`
71-
+ ' referred in the project template is not found';
72-
return model.findOne({
73-
where: {
74-
key: keyInfo.key,
75-
},
76-
}).then((record) => {
77-
if (record == null) {
78-
return Promise.resolve(errorMessage);
79-
}
80-
return Promise.resolve(null);
81-
});
82-
}
83-
return Promise.resolve(null);
84-
};
85-
8654
return Promise.all([
87-
checkModel(form, 'Form', models.Form, next),
88-
checkModel(priceConfig, 'PriceConfig', models.PriceConfig, next),
89-
checkModel(planConfig, 'PlanConfig', models.PlanConfig, next),
55+
util.checkModel(form, 'Form', models.Form, 'project template'),
56+
util.checkModel(priceConfig, 'PriceConfig', models.PriceConfig, 'project template'),
57+
util.checkModel(planConfig, 'PlanConfig', models.PlanConfig, 'project template'),
9058
])
91-
.then((errorMessages) => {
92-
const errorMessage = errorMessages.find(e => e && e.length > 0);
93-
if (errorMessage) {
94-
const apiErr = new Error(errorMessage);
95-
apiErr.status = 422;
96-
throw apiErr;
97-
}
59+
.then(() => {
9860
const entity = _.assign(req.body.param, {
9961
createdBy: req.authUser.userId,
10062
updatedBy: req.authUser.userId,

src/routes/projectTemplates/create.spec.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ describe('CREATE project template', () => {
108108
},
109109
};
110110

111+
const bodyDefinedFormScope = _.cloneDeep(body);
112+
bodyDefinedFormScope.param.form = {
113+
scope1: {
114+
subScope1A: 1,
115+
subScope1B: 2,
116+
},
117+
scope2: [1, 2, 3],
118+
};
119+
const bodyMissingFormScope = _.cloneDeep(body);
120+
delete bodyMissingFormScope.param.scope;
121+
111122
it('should return 403 if user is not authenticated', (done) => {
112123
request(server)
113124
.post('/v4/projects/metadata/projectTemplates')
@@ -270,5 +281,27 @@ describe('CREATE project template', () => {
270281
done();
271282
});
272283
});
284+
285+
it('should return 422 if both scope and form are defined', (done) => {
286+
request(server)
287+
.post('/v4/projects/metadata/projectTemplates')
288+
.set({
289+
Authorization: `Bearer ${testUtil.jwts.admin}`,
290+
})
291+
.send(bodyDefinedFormScope)
292+
.expect('Content-Type', /json/)
293+
.expect(422, done);
294+
});
295+
296+
it('should return 422 if both scope and form are missing', (done) => {
297+
request(server)
298+
.post('/v4/projects/metadata/projectTemplates')
299+
.set({
300+
Authorization: `Bearer ${testUtil.jwts.admin}`,
301+
})
302+
.send(bodyMissingFormScope)
303+
.expect('Content-Type', /json/)
304+
.expect(422, done);
305+
});
273306
});
274307
});

src/routes/projectTemplates/update.js

Lines changed: 16 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ const schema = {
2525
question: Joi.string().max(255),
2626
info: Joi.string().max(255),
2727
aliases: Joi.array(),
28-
scope: Joi.object().optional().allow(null),
29-
phases: Joi.object().optional().allow(null),
30-
form: Joi.object().optional().allow(null),
31-
planConfig: Joi.object().optional().allow(null),
32-
priceConfig: Joi.object().optional().allow(null),
28+
scope: Joi.object().empty(null),
29+
phases: Joi.object().empty(null),
30+
form: Joi.object().empty(null),
31+
planConfig: Joi.object().empty(null),
32+
priceConfig: Joi.object().empty(null),
3333
disabled: Joi.boolean().optional(),
3434
hidden: Joi.boolean().optional(),
3535
createdAt: Joi.any().strip(),
@@ -38,7 +38,11 @@ const schema = {
3838
createdBy: Joi.any().strip(),
3939
updatedBy: Joi.any().strip(),
4040
deletedBy: Joi.any().strip(),
41-
}).required(),
41+
})
42+
.xor('form', 'scope')
43+
.xor('phases', 'planConfig')
44+
.nand('priceConfig', 'scope')
45+
.required(),
4246
},
4347
};
4448

@@ -50,54 +54,12 @@ module.exports = [
5054
const param = req.body.param;
5155
const { form, priceConfig, planConfig } = param;
5256

53-
const checkModel = (keyInfo, modelName, model) => {
54-
let errorMessage = '';
55-
if (keyInfo == null) {
56-
return Promise.resolve(null);
57-
}
58-
if ((keyInfo.version != null) && (keyInfo.key != null)) {
59-
errorMessage = `${modelName} with key ${keyInfo.key} and version ${keyInfo.version}`
60-
+ ' referred in the project template is not found';
61-
return (model.findOne({
62-
where: {
63-
key: keyInfo.key,
64-
version: keyInfo.version,
65-
},
66-
})).then((record) => {
67-
if (record == null) {
68-
return Promise.resolve(errorMessage);
69-
}
70-
return Promise.resolve(null);
71-
});
72-
} else if ((keyInfo.version == null) && (keyInfo.key != null)) {
73-
errorMessage = `${modelName} with key ${keyInfo.key}`
74-
+ ' referred in the project template is not found';
75-
return model.findOne({
76-
where: {
77-
key: keyInfo.key,
78-
},
79-
}).then((record) => {
80-
if (record == null) {
81-
return Promise.resolve(errorMessage);
82-
}
83-
return Promise.resolve(null);
84-
});
85-
}
86-
return Promise.resolve(null);
87-
};
88-
8957
return Promise.all([
90-
checkModel(form, 'Form', models.Form, next),
91-
checkModel(priceConfig, 'PriceConfig', models.PriceConfig, next),
92-
checkModel(planConfig, 'PlanConfig', models.PlanConfig, next),
58+
util.checkModel(form, 'Form', models.Form, 'project template'),
59+
util.checkModel(priceConfig, 'PriceConfig', models.PriceConfig, 'project template'),
60+
util.checkModel(planConfig, 'PlanConfig', models.PlanConfig, 'project template'),
9361
])
94-
.then((errorMessages) => {
95-
const errorMessage = errorMessages.find(e => e && e.length > 0);
96-
if (errorMessage) {
97-
const apiErr = new Error(errorMessage);
98-
apiErr.status = 422;
99-
throw apiErr;
100-
}
62+
.then(() => {
10163
const entityToUpdate = _.assign(req.body.param, {
10264
updatedBy: req.authUser.userId,
10365
});
@@ -115,7 +77,7 @@ module.exports = [
11577
if (!projectTemplate) {
11678
const apiErr = new Error(`Project template not found for template id ${req.params.templateId}`);
11779
apiErr.status = 404;
118-
return Promise.reject(apiErr);
80+
throw apiErr;
11981
}
12082

12183
// Merge JSON fields
@@ -132,9 +94,7 @@ module.exports = [
13294
})
13395
.then((projectTemplate) => {
13496
res.json(util.wrapResponse(req.id, projectTemplate));
135-
return Promise.resolve();
136-
})
137-
.catch(next);
97+
});
13898
}).catch(next);
13999
},
140100
];

0 commit comments

Comments
 (0)