Skip to content

Commit d170c19

Browse files
laura-bergoensJeyffreylgoubinrouxxi
committed
tech(api): add method to get eligibile challenge Ids in shared/challenge-repository
Co-authored-by: Geoffroy Begouaussel <geoffroy.begouaussel@pix.fr> Co-authored-by: Lou Goubin <lou.goubin@pix.fr> Co-authored-by: Gwenvael Laskar <gwenvael.laskar@pix.fr>
1 parent 2a40536 commit d170c19

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

api/src/shared/infrastructure/repositories/challenge-repository.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Challenge as ChallengeProxy } from '../../../learning-content/domain/models/Challenge.js';
2+
import { DomainTransaction } from '../../domain/DomainTransaction.js';
23
import { NotFoundError } from '../../domain/errors.js';
34
import { Challenge } from '../../domain/models/Challenge.js';
45
import * as solutionAdapter from '../../infrastructure/adapters/solution-adapter.js';
@@ -113,6 +114,20 @@ export async function findValidatedBySkills(skills, locale) {
113114
return challengesDtosWithSkills.map(([challengeDto, skill]) => toDomain({ challengeDto, skill }));
114115
}
115116

117+
export function findValidatedIdsByTubeIdsAndLocales(tubeIds, locales) {
118+
const knexConn = DomainTransaction.getConnection();
119+
120+
return knexConn
121+
.pluck('challenges.id')
122+
.from({ challenges: 'learningcontent.challenges' })
123+
.join({ skills: 'learningcontent.skills' }, 'skills.id', 'challenges.skillId')
124+
.whereIn('skills.tubeId', tubeIds)
125+
.whereRaw('?? && ?', ['challenges.locales', locales])
126+
.where('skills.status', 'actif')
127+
.where('challenges.status', VALIDATED_STATUS)
128+
.orderBy('challenges.id');
129+
}
130+
116131
export function clearCache(id) {
117132
return getInstance().clearCache(id);
118133
}

api/tests/shared/integration/infrastructure/repositories/challenge-repository_test.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import nock from 'nock';
33
import { ValidatorQCM } from '../../../../../src/evaluation/domain/models/ValidatorQCM.js';
44
import { ValidatorQCU } from '../../../../../src/evaluation/domain/models/ValidatorQCU.js';
55
import { NotFoundError } from '../../../../../src/shared/domain/errors.js';
6+
import { ENGLISH_SPOKEN, FRENCH_SPOKEN } from '../../../../../src/shared/domain/services/locale-service.js';
67
import * as challengeRepository from '../../../../../src/shared/infrastructure/repositories/challenge-repository.js';
78
import { expect } from '../../../../test-helper.js';
89
import { databaseBuilder } from '../../../../tooling/databases.js';
@@ -1570,4 +1571,92 @@ describe('Integration | Repository | challenge-repository', function () {
15701571
});
15711572
});
15721573
});
1574+
1575+
describe('#findValidatedIdsByTubeIdsAndLocales', function () {
1576+
it('returns challenge IDS that belong to given tube IDS and are of the languages given in parameters', async function () {
1577+
databaseBuilder.factory.learningContent.build({
1578+
skills: [
1579+
{ id: 'skillOk1', tubeId: 'tubeOk1', status: 'actif' },
1580+
{ id: 'skillOk2', tubeId: 'tubeOk2', status: 'actif' },
1581+
],
1582+
challenges: [
1583+
{ id: 'challengeOk1', skillId: 'skillOk1', locales: [FRENCH_SPOKEN], status: 'validé' },
1584+
{ id: 'challengeOk2', skillId: 'skillOk2', locales: [FRENCH_SPOKEN], status: 'validé' },
1585+
{ id: 'challengeKo3', skillId: 'skillOk2', locales: [ENGLISH_SPOKEN], status: 'validé' },
1586+
],
1587+
});
1588+
await databaseBuilder.commit();
1589+
1590+
const challengeIds = await challengeRepository.findValidatedIdsByTubeIdsAndLocales(
1591+
['tubeOk1', 'tubeOk2'],
1592+
[FRENCH_SPOKEN],
1593+
);
1594+
1595+
expect(challengeIds).to.deep.equal(['challengeOk1', 'challengeOk2']);
1596+
});
1597+
1598+
it('ignores valid challenges when not in given tube IDS', async function () {
1599+
databaseBuilder.factory.learningContent.build({
1600+
skills: [
1601+
{ id: 'skillOk', tubeId: 'tubeOk', status: 'actif' },
1602+
{ id: 'skillNotInTubeIds', tubeId: 'someOtherTube', status: 'actif' },
1603+
],
1604+
challenges: [
1605+
{ id: 'challengeOk', skillId: 'skillOk', locales: [FRENCH_SPOKEN], status: 'validé' },
1606+
{ id: 'challengeNotInTubeIds', skillId: 'skillNotInTubeIds', locales: [FRENCH_SPOKEN], status: 'validé' },
1607+
],
1608+
});
1609+
await databaseBuilder.commit();
1610+
1611+
const challengeIds = await challengeRepository.findValidatedIdsByTubeIdsAndLocales(['tubeOk'], [FRENCH_SPOKEN]);
1612+
1613+
expect(challengeIds).to.deep.equal(['challengeOk']);
1614+
});
1615+
1616+
it('ignores valid challenges when not in given locales', async function () {
1617+
databaseBuilder.factory.learningContent.build({
1618+
skills: [{ id: 'skillOk', tubeId: 'tubeOk', status: 'actif' }],
1619+
challenges: [
1620+
{ id: 'challengeOkFr', skillId: 'skillOk', locales: [FRENCH_SPOKEN], status: 'validé' },
1621+
{ id: 'challengeOkEn', skillId: 'skillOk', locales: [ENGLISH_SPOKEN], status: 'validé' },
1622+
{ id: 'challengeOkNl', skillId: 'skillOk', locales: ['nl'], status: 'validé' },
1623+
],
1624+
});
1625+
await databaseBuilder.commit();
1626+
1627+
const challengeIds = await challengeRepository.findValidatedIdsByTubeIdsAndLocales(
1628+
['tubeOk'],
1629+
[FRENCH_SPOKEN, 'nl'],
1630+
);
1631+
1632+
expect(challengeIds).to.deep.equal(['challengeOkFr', 'challengeOkNl']);
1633+
});
1634+
1635+
it('ignores challenges when skill is not active', async function () {
1636+
databaseBuilder.factory.learningContent.build({
1637+
skills: [{ id: 'skillKo', tubeId: 'tubeOk', status: 'archivé' }],
1638+
challenges: [{ id: 'challengeOkFr', skillId: 'skillOk', locales: [FRENCH_SPOKEN], status: 'validé' }],
1639+
});
1640+
await databaseBuilder.commit();
1641+
1642+
const challengeIds = await challengeRepository.findValidatedIdsByTubeIdsAndLocales(['tubeOk'], [FRENCH_SPOKEN]);
1643+
1644+
expect(challengeIds).to.deep.equal([]);
1645+
});
1646+
1647+
it('ignores challenges when challenge is not validated', async function () {
1648+
databaseBuilder.factory.learningContent.build({
1649+
skills: [{ id: 'skillOk', tubeId: 'tubeOk', status: 'actif' }],
1650+
challenges: [
1651+
{ id: 'challengeOk', skillId: 'skillOk', locales: [FRENCH_SPOKEN], status: 'validé' },
1652+
{ id: 'challengeKo', skillId: 'skillOk', locales: [FRENCH_SPOKEN], status: 'archivé' },
1653+
],
1654+
});
1655+
await databaseBuilder.commit();
1656+
1657+
const challengeIds = await challengeRepository.findValidatedIdsByTubeIdsAndLocales(['tubeOk'], [FRENCH_SPOKEN]);
1658+
1659+
expect(challengeIds).to.deep.equal(['challengeOk']);
1660+
});
1661+
});
15731662
});

0 commit comments

Comments
 (0)