Skip to content

Commit ddbcc6d

Browse files
[TECH] Déplacer la route des contenus formatifs vers le domaine Dev Comp (PIX-16249).
#11285
2 parents 24f58b4 + b40ede5 commit ddbcc6d

File tree

11 files changed

+206
-250
lines changed

11 files changed

+206
-250
lines changed

api/lib/application/target-profiles/index.js

-41
This file was deleted.

api/lib/application/target-profiles/target-profile-controller.js

-19
This file was deleted.

api/lib/routes.js

-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import * as frameworks from './application/frameworks/index.js';
77
import * as memberships from './application/memberships/index.js';
88
import * as organizations from './application/organizations/index.js';
99
import * as scoOrganizationLearners from './application/sco-organization-learners/index.js';
10-
import * as targetProfiles from './application/target-profiles/index.js';
1110
import * as users from './application/users/index.js';
1211

1312
const routes = [
@@ -19,7 +18,6 @@ const routes = [
1918
memberships,
2019
organizations,
2120
scoOrganizationLearners,
22-
targetProfiles,
2321
frameworks,
2422
users,
2523
];

api/src/devcomp/application/trainings/index.js

+29
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,35 @@ const register = async function (server) {
286286
],
287287
},
288288
},
289+
{
290+
method: 'GET',
291+
path: '/api/admin/target-profiles/{id}/training-summaries',
292+
config: {
293+
pre: [
294+
{
295+
method: (request, h) =>
296+
securityPreHandlers.hasAtLeastOneAccessOf([
297+
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
298+
securityPreHandlers.checkAdminMemberHasRoleSupport,
299+
securityPreHandlers.checkAdminMemberHasRoleMetier,
300+
])(request, h),
301+
assign: 'hasAuthorizationToAccessAdminScope',
302+
},
303+
],
304+
validate: {
305+
params: Joi.object({
306+
id: identifiersType.targetProfileId,
307+
}),
308+
},
309+
handler: trainingsController.findPaginatedTrainingsSummariesByTargetProfileId,
310+
tags: ['api', 'admin', 'target-profiles', 'trainings'],
311+
notes: [
312+
"- **Cette route est restreinte aux utilisateurs authentifiés ayant les droits d'accès**\n" +
313+
'- Elle permet de récupérer les résumés des contenus formatifs liés au profil cible',
314+
],
315+
},
316+
},
317+
289318
{
290319
method: 'DELETE',
291320
path: '/api/admin/trainings/{trainingId}/target-profiles/{targetProfileId}',

api/src/devcomp/application/trainings/training-controller.js

+16
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,24 @@ const detachTargetProfile = async function (request, h) {
7777
return h.response({}).code(204);
7878
};
7979

80+
const findPaginatedTrainingsSummariesByTargetProfileId = async function (
81+
request,
82+
h,
83+
dependencies = { trainingSummarySerializer },
84+
) {
85+
const { page } = request.query;
86+
const targetProfileId = request.params.id;
87+
88+
const { trainings, meta } = await usecases.findPaginatedTargetProfileTrainingSummaries({
89+
targetProfileId,
90+
page,
91+
});
92+
return dependencies.trainingSummarySerializer.serialize(trainings, meta);
93+
};
94+
8095
const trainingController = {
8196
findPaginatedTrainingSummaries,
97+
findPaginatedTrainingsSummariesByTargetProfileId,
8298
findTargetProfileSummaries,
8399
getById,
84100
create,

api/tests/acceptance/application/target-profiles/index_test.js

-58
This file was deleted.

api/tests/devcomp/acceptance/application/trainings/index_test.js

+44
Original file line numberDiff line numberDiff line change
@@ -552,4 +552,48 @@ describe('Acceptance | Controller | training-controller', function () {
552552
expect(result).to.deepEqualArray([]);
553553
});
554554
});
555+
556+
describe('GET /api/admin/target-profiles/{id}/training-summaries', function () {
557+
let user;
558+
let targetProfileId;
559+
let training;
560+
561+
beforeEach(async function () {
562+
targetProfileId = databaseBuilder.factory.buildTargetProfile().id;
563+
training = databaseBuilder.factory.buildTraining();
564+
databaseBuilder.factory.buildTargetProfileTraining({ targetProfileId, trainingId: training.id });
565+
user = databaseBuilder.factory.buildUser.withRole();
566+
567+
await databaseBuilder.commit();
568+
});
569+
570+
it('should return 200', async function () {
571+
const options = {
572+
method: 'GET',
573+
url: `/api/admin/target-profiles/${targetProfileId}/training-summaries`,
574+
headers: generateAuthenticatedUserRequestHeaders({ userId: user.id }),
575+
};
576+
577+
// when
578+
const response = await server.inject(options);
579+
580+
// then
581+
expect(response.statusCode).to.equal(200);
582+
const expectedData = [
583+
{
584+
type: 'training-summaries',
585+
id: training.id.toString(),
586+
attributes: {
587+
'goal-threshold': undefined,
588+
'prerequisite-threshold': undefined,
589+
'is-disabled': false,
590+
'target-profiles-count': 1,
591+
title: 'title',
592+
'internal-title': 'internal title',
593+
},
594+
},
595+
];
596+
expect(response.result.data).to.deep.equal(expectedData);
597+
});
598+
});
555599
});

api/tests/devcomp/integration/application/trainings/index_test.js

+75
Original file line numberDiff line numberDiff line change
@@ -1624,4 +1624,79 @@ describe('Integration | Devcomp | Application | Trainings | Router | training-ro
16241624
});
16251625
});
16261626
});
1627+
1628+
describe('GET /api/admin/target-profiles/{id}/training-summaries', function () {
1629+
const method = 'GET';
1630+
const url = '/api/admin/target-profiles/1/training-summaries';
1631+
1632+
context('when user has role "SUPER_ADMIN", "SUPPORT" or "METIER"', function () {
1633+
it('should return a response with an HTTP status code 200', async function () {
1634+
// given
1635+
sinon
1636+
.stub(securityPreHandlers, 'hasAtLeastOneAccessOf')
1637+
.withArgs([
1638+
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
1639+
securityPreHandlers.checkAdminMemberHasRoleSupport,
1640+
securityPreHandlers.checkAdminMemberHasRoleMetier,
1641+
])
1642+
.callsFake(() => (request, h) => h.response(true));
1643+
sinon
1644+
.stub(trainingController, 'findPaginatedTrainingsSummariesByTargetProfileId')
1645+
.callsFake((request, h) => h.response('ok').code(200));
1646+
const httpTestServer = new HttpTestServer();
1647+
await httpTestServer.register(moduleUnderTest);
1648+
1649+
// when
1650+
const { statusCode } = await httpTestServer.request(method, url);
1651+
1652+
// then
1653+
expect(statusCode).to.equal(200);
1654+
});
1655+
1656+
context('when id is not an integer', function () {
1657+
it('should reject request with HTTP code 400', async function () {
1658+
// given
1659+
const httpTestServer = new HttpTestServer();
1660+
await httpTestServer.register(moduleUnderTest);
1661+
1662+
// when
1663+
const { statusCode } = await httpTestServer.request(
1664+
method,
1665+
'/api/admin/target-profiles/azerty/training-summaries',
1666+
);
1667+
1668+
// then
1669+
expect(statusCode).to.equal(400);
1670+
});
1671+
});
1672+
});
1673+
1674+
context('when user has role "CERTIF"', function () {
1675+
it('should return a response with an HTTP status code 403', async function () {
1676+
// given
1677+
sinon
1678+
.stub(securityPreHandlers, 'hasAtLeastOneAccessOf')
1679+
.withArgs([
1680+
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
1681+
securityPreHandlers.checkAdminMemberHasRoleSupport,
1682+
securityPreHandlers.checkAdminMemberHasRoleMetier,
1683+
])
1684+
.callsFake(
1685+
() => (request, h) =>
1686+
h
1687+
.response({ errors: new Error('forbidden') })
1688+
.code(403)
1689+
.takeover(),
1690+
);
1691+
const httpTestServer = new HttpTestServer();
1692+
await httpTestServer.register(moduleUnderTest);
1693+
1694+
// when
1695+
const { statusCode } = await httpTestServer.request(method, url);
1696+
1697+
// then
1698+
expect(statusCode).to.equal(403);
1699+
});
1700+
});
1701+
});
16271702
});

api/tests/devcomp/unit/application/trainings/training-controller_test.js

+42
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,46 @@ describe('Unit | Devcomp | Application | Trainings | Controller | training-contr
356356
expect(usecases.attachTargetProfilesToTraining).to.have.been.calledWithExactly({ trainingId, targetProfileIds });
357357
});
358358
});
359+
360+
describe('#findPaginatedTrainingsSummariesByTargetProfileId', function () {
361+
it('should return trainings summaries', async function () {
362+
// given
363+
const targetProfileId = 123;
364+
const expectedResult = Symbol('serialized-training-summaries');
365+
const trainingSummaries = Symbol('trainingSummaries');
366+
const meta = Symbol('meta');
367+
const useCaseParameters = {
368+
targetProfileId,
369+
page: { size: 2, number: 1 },
370+
};
371+
372+
sinon.stub(usecases, 'findPaginatedTargetProfileTrainingSummaries').resolves({
373+
trainings: trainingSummaries,
374+
meta,
375+
});
376+
377+
const trainingSummarySerializer = {
378+
serialize: sinon.stub(),
379+
};
380+
trainingSummarySerializer.serialize.withArgs(trainingSummaries, meta).returns(expectedResult);
381+
382+
// when
383+
const response = await trainingController.findPaginatedTrainingsSummariesByTargetProfileId(
384+
{
385+
params: {
386+
id: targetProfileId,
387+
},
388+
query: {
389+
page: { size: 2, number: 1 },
390+
},
391+
},
392+
hFake,
393+
{ trainingSummarySerializer },
394+
);
395+
396+
// then
397+
expect(usecases.findPaginatedTargetProfileTrainingSummaries).to.have.been.calledWithExactly(useCaseParameters);
398+
expect(response).to.deep.equal(expectedResult);
399+
});
400+
});
359401
});

0 commit comments

Comments
 (0)