Skip to content

Commit f8b0eee

Browse files
Merge pull request #732 from freeCodeCamp/main
Create a new pull request by comparing changes across two branches
2 parents f22d916 + 786f840 commit f8b0eee

File tree

299 files changed

+8917
-2564
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

299 files changed

+8917
-2564
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ pnpm-lock.yaml
3838
/curriculum/challenges/english/* @freecodecamp/curriculum
3939

4040
# -------------------------------------------------
41-
# Files that need attention from Staff
41+
# Files that need attention from i18n & dev team
4242
# -------------------------------------------------
4343

44-
# README, LICENSE, etc.
45-
/*.md @freeCodeCamp/staff
46-
4744
# i18n Quotes
48-
**/motivation.json @freeCodeCamp/staff @freeCodeCamp/i18n
45+
**/motivation.json @freeCodeCamp/dev-team @freeCodeCamp/i18n
46+
4947

5048
# -------------------------------------------------
5149
# Files that need attention from the mobile team

.github/workflows/node.js-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
- name: Lint Source Files
6969
run: |
7070
echo pnpm version $(pnpm -v)
71-
pnpm turbo lint
71+
pnpm lint
7272
7373
# DONT REMOVE THIS JOB.
7474
# TODO: Refactor and use re-usable workflow and shared artifacts

api/__mocks__/exam-environment-exam.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ export const generatedExam: ExamEnvironmentGeneratedExam = {
255255
export const examAttempt: ExamEnvironmentExamAttempt = {
256256
examId,
257257
generatedExamId: generatedExam.id,
258+
examModerationId: null,
258259
id: oid(),
259260
questionSets: [
260261
{

api/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
"dotenv-cli": "7.3.0",
5252
"eslint": "^9.39.1",
5353
"eslint-plugin-jsdoc": "48.2.1",
54-
"jsdom": "^26.1.0",
5554
"msw": "^2.7.0",
5655
"prisma": "6.16.2",
5756
"supertest": "6.3.3",

api/prisma/exam-environment.prisma

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,26 +118,31 @@ type ExamEnvironmentTagConfig {
118118

119119
/// An attempt at an exam in the Exam Environment App
120120
model ExamEnvironmentExamAttempt {
121-
id String @id @default(auto()) @map("_id") @db.ObjectId
121+
id String @id @default(auto()) @map("_id") @db.ObjectId
122122
/// Foriegn key to user
123-
userId String @db.ObjectId
123+
userId String @db.ObjectId
124124
/// Foreign key to exam
125-
examId String @db.ObjectId
125+
examId String @db.ObjectId
126126
/// Foreign key to generated exam id
127-
generatedExamId String @db.ObjectId
127+
generatedExamId String @db.ObjectId
128+
/// Un-enforced foreign key to moderation
129+
examModerationId String? @db.ObjectId
128130
129131
questionSets ExamEnvironmentQuestionSetAttempt[]
130132
/// Time exam was started
131133
startTime DateTime
132134
/// Version of the record
133135
/// The default must be incremented by 1, if anything in the schema changes
134-
version Int @default(3)
136+
version Int @default(4)
135137
136138
// Relations
137-
user user @relation(fields: [userId], references: [id], onDelete: Cascade)
138-
exam ExamEnvironmentExam @relation(fields: [examId], references: [id], onDelete: Cascade)
139-
generatedExam ExamEnvironmentGeneratedExam @relation(fields: [generatedExamId], references: [id])
140-
ExamEnvironmentExamModeration ExamEnvironmentExamModeration[]
139+
user user @relation(fields: [userId], references: [id], onDelete: Cascade)
140+
exam ExamEnvironmentExam @relation(fields: [examId], references: [id], onDelete: Cascade)
141+
generatedExam ExamEnvironmentGeneratedExam @relation(fields: [generatedExamId], references: [id])
142+
// Ideally, there could be a way to add a one-way optional relation here, but Prisma does not allow that:
143+
// Error parsing attribute "@relation": The relation fields `examAttempt` on Model `ExamEnvironmentExamModeration` and `examModeration` on Model `ExamEnvironmentExamAttempt` both provide the `references` argument in the @relation attribute. You have to provide it only on one of the two fields.
144+
// examModeration ExamEnvironmentExamModeration? @relation(fields: [examModerationId], references: [id])
145+
examEnvironmentExamModeration ExamEnvironmentExamModeration?
141146
}
142147

143148
type ExamEnvironmentQuestionSetAttempt {

api/src/exam-environment/routes/exam-environment.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ describe('/exam-environment/', () => {
590590
userId: defaultUserId,
591591
examId: mock.examId,
592592
generatedExamId: generatedExam!.id,
593+
examModerationId: null,
593594
questionSets: [],
594595
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
595596
startTime: expect.any(Date),

api/src/exam-environment/routes/exam-environment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ async function postExamGeneratedExamHandler(
458458
userId: user.id,
459459
examId: exam.id,
460460
generatedExamId: generatedExam.id,
461+
examModerationId: null,
461462
startTime: new Date(),
462463
questionSets: []
463464
}

api/src/exam-environment/utils/exam-environment.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ describe('Exam Environment Schema', () => {
518518
data: {
519519
examId: oid(),
520520
generatedExamId: oid(),
521+
examModerationId: null,
521522
questionSets: [
522523
{
523524
id: oid(),

api/src/routes/helpers/certificate-utils.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,18 @@
11
import { Prisma } from '@prisma/client';
22
import {
33
certSlugTypeMap,
4-
certIds
4+
certToIdMap,
5+
Certification
56
} from '../../../../shared/config/certification-settings.js';
67
import { normalizeDate } from '../../utils/normalize.js';
78

8-
const {
9-
legacyInfosecQaId,
10-
respWebDesignId,
11-
frontEndDevLibsId,
12-
jsAlgoDataStructId,
13-
dataVis2018Id,
14-
apisMicroservicesId
15-
} = certIds;
16-
179
const fullStackCertificateIds = [
18-
respWebDesignId,
19-
jsAlgoDataStructId,
20-
frontEndDevLibsId,
21-
dataVis2018Id,
22-
apisMicroservicesId,
23-
legacyInfosecQaId
10+
certToIdMap[Certification.RespWebDesign],
11+
certToIdMap[Certification.JsAlgoDataStruct],
12+
certToIdMap[Certification.FrontEndDevLibs],
13+
certToIdMap[Certification.DataVis],
14+
certToIdMap[Certification.BackEndDevApis],
15+
certToIdMap[Certification.LegacyInfoSecQa]
2416
];
2517

2618
/**

api/src/routes/protected/certificate.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
setupServer,
1717
superRequest
1818
} from '../../../vitest.utils.js';
19+
import { getChallenges } from '../../utils/get-challenges.js';
20+
import { createCertLookup } from './certificate.js';
1921

2022
describe('certificate routes', () => {
2123
setupServer();
@@ -461,3 +463,32 @@ describe('certificate routes', () => {
461463
});
462464
});
463465
});
466+
467+
describe('createCertLookup', () => {
468+
let challenges: ReturnType<typeof getChallenges>;
469+
470+
beforeAll(() => {
471+
// TODO: create a mock challenges array specific to these tests.
472+
challenges = getChallenges();
473+
});
474+
475+
test('should create a lookup for all certifications', () => {
476+
const certLookup = createCertLookup(challenges);
477+
478+
for (const cert of Object.values(Certification)) {
479+
const certData = certLookup[cert];
480+
expect(certData).toHaveProperty('id');
481+
expect(certData).toHaveProperty('tests');
482+
expect(certData).toHaveProperty('challengeType');
483+
}
484+
});
485+
486+
test('each certification should have a unique challenge id', () => {
487+
const certLookup = createCertLookup(challenges);
488+
const ids = Object.values(certLookup)
489+
.map(({ id }) => id)
490+
.sort();
491+
const uniqueIds = Array.from(new Set(ids)).sort();
492+
expect(uniqueIds).toEqual(ids);
493+
});
494+
});

0 commit comments

Comments
 (0)