Skip to content

Commit

Permalink
Merge pull request #2382 from sophiemoustard/COM-3677
Browse files Browse the repository at this point in the history
Com 3677
  • Loading branch information
sophiemoustard committed Apr 8, 2024
2 parents 9c3a3f0 + cb846b4 commit d180ce8
Show file tree
Hide file tree
Showing 9 changed files with 576 additions and 41 deletions.
6 changes: 5 additions & 1 deletion src/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,11 @@ module.exports = {
// QUESTIONNAIRE_HISTORY
START_COURSE: 'start_course',
END_COURSE: 'end_course',
get TIMELINE_OPTIONS() { return [this.START_COURSE, this.END_COURSE]; },
get TIMELINE_OPTIONS() { return [this.START_COURSE, this.END_COURSE, this.UNKNOWN]; },
// COURSE TIMELINE
BEFORE_MIDDLE_COURSE_END_DATE: 'before_middle_course_end_date',
BETWEEN_MID_AND_END_COURSE: 'between_mid_and_end_course',
ENDED: 'ended',
// tests end2end
PLANNING: 'planning',
AUTHENTICATION: 'authentication',
Expand Down
49 changes: 44 additions & 5 deletions src/helpers/questionnaireHistories.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,50 @@
const Boom = require('@hapi/boom');
const QuestionnaireHistory = require('../models/QuestionnaireHistory');
const { COURSE, TRAINEE } = require('./constants');
const Questionnaire = require('../models/Questionnaire');
const {
COURSE,
TRAINEE,
SELF_POSITIONNING,
START_COURSE,
END_COURSE,
BEFORE_MIDDLE_COURSE_END_DATE,
ENDED,
UNKNOWN,
} = require('./constants');
const CourseHistoriesHelper = require('./courseHistories');
const QuestionnaireHelper = require('./questionnaires');
const translate = require('./translate');

const { language } = translate;

exports.addQuestionnaireHistory = async (payload) => {
const traineesCompanyAtCourseRegistrationList = await CourseHistoriesHelper.getCompanyAtCourseRegistrationList(
{ key: COURSE, value: payload.course }, { key: TRAINEE, value: [payload.user] }
);
const { user: userId, questionnaire: questionnaireId, course: courseId } = payload;
const traineesCompanyAtCourseRegistrationList = await CourseHistoriesHelper
.getCompanyAtCourseRegistrationList({ key: COURSE, value: courseId }, { key: TRAINEE, value: [userId] });

const questionnaire = await Questionnaire.findOne({ _id: questionnaireId }, { type: 1 }).lean();

let timeline;
if (questionnaire.type === SELF_POSITIONNING) {
const { courseTimeline } = await QuestionnaireHelper.getCourseInfos(courseId);

return QuestionnaireHistory.create({ ...payload, company: traineesCompanyAtCourseRegistrationList[0].company });
switch (courseTimeline) {
case BEFORE_MIDDLE_COURSE_END_DATE:
timeline = START_COURSE;
break;
case ENDED:
timeline = END_COURSE;
break;
default:
timeline = UNKNOWN;
}
}

const questionnaireHistoryExists = await QuestionnaireHistory
.countDocuments({ course: courseId, user: userId, questionnaire: questionnaireId, ...(timeline && { timeline }) });
if (questionnaireHistoryExists) throw Boom.conflict(translate[language].questionnaireHistoryConflict);

return QuestionnaireHistory.create(
{ ...payload, company: traineesCompanyAtCourseRegistrationList[0].company, ...(timeline && { timeline }) }
);
};
13 changes: 6 additions & 7 deletions src/helpers/questionnaires.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ const {
START_COURSE,
END_COURSE,
DAY,
BEFORE_MIDDLE_COURSE_END_DATE,
BETWEEN_MID_AND_END_COURSE,
ENDED,
} = require('./constants');
const DatesUtilsHelper = require('./dates/utils');
const { CompaniDate } = require('./dates/companiDates');

exports.create = async payload => Questionnaire.create(payload);

const BEFORE_MIDDLE_COURSE_END_DATE = 'before_middle_course_end_date';
const BETWEEN_MID_AND_END_COURSE = 'between_mid_and_end_course';
const ENDED = 'ended';

const getCourseTimeline = (course) => {
const sortedSlots = [...course.slots].sort(DatesUtilsHelper.ascendingSortBy('startDate'));

Expand All @@ -46,7 +45,7 @@ const getCourseTimeline = (course) => {
return BETWEEN_MID_AND_END_COURSE;
};

const getCourseInfos = async (courseId) => {
exports.getCourseInfos = async (courseId) => {
const course = await Course.findOne({ _id: courseId })
.populate({ path: 'slots', select: '-__v -createdAt -updatedAt' })
.populate({ path: 'slotsToPlan', select: '_id' })
Expand All @@ -66,7 +65,7 @@ exports.list = async (credentials, query = {}) => {
return Questionnaire.find(query).populate({ path: 'historiesCount', options: { isVendorUser } }).lean();
}

const { isStrictlyELearning, courseTimeline, programId } = await getCourseInfos(courseId);
const { isStrictlyELearning, courseTimeline, programId } = await exports.getCourseInfos(courseId);

if (isStrictlyELearning) return [];

Expand Down Expand Up @@ -132,7 +131,7 @@ const findQuestionnaires = (questionnaireConditions, historiesConditions) => {
};

exports.getUserQuestionnaires = async (courseId, credentials) => {
const { isStrictlyELearning, courseTimeline, programId } = await getCourseInfos(courseId);
const { isStrictlyELearning, courseTimeline, programId } = await exports.getCourseInfos(courseId);

if (isStrictlyELearning) return [];

Expand Down
8 changes: 0 additions & 8 deletions src/routes/preHandlers/questionnaireHistories.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ const Boom = require('@hapi/boom');
const Questionnaire = require('../../models/Questionnaire');
const User = require('../../models/User');
const Course = require('../../models/Course');
const QuestionnaireHistory = require('../../models/QuestionnaireHistory');
const { checkQuestionnaireAnswersList } = require('./utils');
const translate = require('../../helpers/translate');

const { language } = translate;

exports.authorizeAddQuestionnaireHistory = async (req) => {
const { user: userId, questionnaire: questionnaireId, course: courseId, questionnaireAnswersList } = req.payload;
Expand All @@ -17,10 +13,6 @@ exports.authorizeAddQuestionnaireHistory = async (req) => {

if (!questionnaire || !user || !isCourseFollowedByUser) throw Boom.notFound();

const questionnaireHistory = await QuestionnaireHistory
.countDocuments({ course: courseId, user: userId, questionnaire: questionnaireId });
if (questionnaireHistory) return Boom.conflict(translate[language].questionnaireHistoryConflict);

if (questionnaireAnswersList) await checkQuestionnaireAnswersList(questionnaireAnswersList, questionnaireId);

return null;
Expand Down
131 changes: 128 additions & 3 deletions tests/integration/questionnaireHistories.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { expect } = require('expect');
const { ObjectId } = require('mongodb');
const sinon = require('sinon');
const omit = require('lodash/omit');
const app = require('../../server');
const {
Expand All @@ -13,7 +14,7 @@ const { getTokenByCredentials } = require('./helpers/authentication');
const { companyWithoutSubscription } = require('../seed/authCompaniesSeed');
const { noRoleNoCompany } = require('../seed/authUsersSeed');
const QuestionnaireHistory = require('../../src/models/QuestionnaireHistory');
const { WEBAPP } = require('../../src/helpers/constants');
const { WEBAPP, START_COURSE, END_COURSE, UNKNOWN } = require('../../src/helpers/constants');

describe('NODE ENV', () => {
it('should be \'test\'', () => {
Expand All @@ -26,8 +27,14 @@ describe('QUESTIONNAIRE HISTORIES ROUTES - POST /questionnairehistories', () =>
beforeEach(populateDB);

describe('NO_ROLE_NO_COMPANY', () => {
let nowStub;
beforeEach(async () => {
authToken = await getTokenByCredentials(noRoleNoCompany.local);
nowStub = sinon.stub(Date, 'now');
});

afterEach(() => {
nowStub.restore();
});

it('should create questionnaireHistory', async () => {
Expand All @@ -54,6 +61,68 @@ describe('QUESTIONNAIRE HISTORIES ROUTES - POST /questionnairehistories', () =>
expect(questionnaireHistoriesCount).toBe(1);
});

it('should create questionnaireHistory with timeline START_COURSE', async () => {
nowStub.returns(new Date('2021-04-20T10:00:00.000Z'));

const payload = {
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[1]._id,
questionnaireAnswersList: [
{ card: cardsList[1]._id, answerList: ['Premier niveau'] },
{ card: cardsList[3]._id, answerList: ['coucou'] },
],
};

const response = await app.inject({
method: 'POST',
url: '/questionnairehistories',
payload,
headers: { 'x-access-token': authToken },
});

expect(response.statusCode).toBe(200);
const qhCount = await QuestionnaireHistory
.countDocuments({
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[1]._id,
timeline: START_COURSE,
});
expect(qhCount).toBe(1);
});

it('should create questionnaireHistory with timeline END_COURSE', async () => {
nowStub.returns(new Date('2021-04-24T10:00:00.000Z'));

const payload = {
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[1]._id,
questionnaireAnswersList: [
{ card: cardsList[1]._id, answerList: ['Premier niveau'] },
{ card: cardsList[3]._id, answerList: ['coucou'] },
],
};

const response = await app.inject({
method: 'POST',
url: '/questionnairehistories',
payload,
headers: { 'x-access-token': authToken },
});

expect(response.statusCode).toBe(200);
const qhCount = await QuestionnaireHistory
.countDocuments({
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[1]._id,
timeline: END_COURSE,
});
expect(qhCount).toBe(1);
});

it('should create questionnaireHistory without questionnaireAnswersList', async () => {
const payload = {
course: coursesList[0]._id,
Expand All @@ -69,8 +138,45 @@ describe('QUESTIONNAIRE HISTORIES ROUTES - POST /questionnairehistories', () =>
});

expect(response.statusCode).toBe(200);
const questionnaireHistoriesCount = await QuestionnaireHistory.countDocuments();
expect(questionnaireHistoriesCount).toBe(2);
const questionnaireHistoriesCount = await QuestionnaireHistory
.countDocuments({
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[0]._id,
});
expect(questionnaireHistoriesCount).toBe(1);
});

it('should set timeline to UNKNOWN if user tries to answer a questionnaire between middle '
+ 'and end of the course', async () => {
nowStub.returns(new Date('2021-04-21T10:00:00.000Z'));

const payload = {
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[1]._id,
questionnaireAnswersList: [
{ card: cardsList[1]._id, answerList: ['Premier niveau'] },
{ card: cardsList[3]._id, answerList: ['coucou'] },
],
};

const response = await app.inject({
method: 'POST',
url: '/questionnairehistories',
payload,
headers: { 'x-access-token': authToken },
});

expect(response.statusCode).toBe(200);
const questionnaireHistoriesCount = await QuestionnaireHistory
.countDocuments({
course: coursesList[0]._id,
user: questionnaireHistoriesUsersList[0],
questionnaire: questionnairesList[1]._id,
timeline: UNKNOWN,
});
expect(questionnaireHistoriesCount).toBe(1);
});

it('should return 400 if questionnaire answer without card', async () => {
Expand Down Expand Up @@ -146,6 +252,25 @@ describe('QUESTIONNAIRE HISTORIES ROUTES - POST /questionnairehistories', () =>
expect(response.statusCode).toBe(409);
});

it('should return a 409 if a questionnaire history already exists for this course, timeline and user', async () => {
nowStub.returns(new Date('2021-04-24T10:00:00.000Z'));

const payload = {
course: coursesList[1]._id,
user: questionnaireHistoriesUsersList[1],
questionnaire: questionnairesList[2]._id,
};

const response = await app.inject({
method: 'POST',
url: '/questionnairehistories',
payload,
headers: { 'x-access-token': authToken },
});

expect(response.statusCode).toBe(409);
});

it('should return a 404 if questionnaire doesn\'t exist', async () => {
const payload = {
course: coursesList[0]._id,
Expand Down
Loading

0 comments on commit d180ce8

Please sign in to comment.