freeCodeCamp/curriculum/utils.test.ts

184 lines
6.3 KiB
TypeScript
Raw Normal View History

// utils are not typed (yet), so we have to disable some checks
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import fs from 'fs';
import path from 'path';
import { config } from 'dotenv';
import { SuperBlocks } from '../config/superblocks';
import { createSuperOrder, getSuperOrder, getSuperBlockFromDir } from './utils';
config({ path: path.resolve(__dirname, '../.env') });
const mockSuperBlocks = [
SuperBlocks.RespWebDesignNew,
SuperBlocks.JsAlgoDataStruct,
SuperBlocks.FrontEndDevLibs,
SuperBlocks.DataVis,
SuperBlocks.RelationalDb,
SuperBlocks.BackEndDevApis,
SuperBlocks.QualityAssurance,
SuperBlocks.SciCompPy,
SuperBlocks.DataAnalysisPy,
SuperBlocks.InfoSec,
SuperBlocks.MachineLearningPy,
SuperBlocks.CollegeAlgebraPy,
SuperBlocks.CodingInterviewPrep,
SuperBlocks.ProjectEuler,
SuperBlocks.RespWebDesign,
SuperBlocks.JsAlgoDataStructNew,
SuperBlocks.TheOdinProject,
SuperBlocks.FoundationalCSharp,
SuperBlocks.ExampleCertification
];
const fullSuperOrder = {
[SuperBlocks.RespWebDesignNew]: 0,
[SuperBlocks.JsAlgoDataStruct]: 1,
[SuperBlocks.FrontEndDevLibs]: 2,
[SuperBlocks.DataVis]: 3,
[SuperBlocks.RelationalDb]: 4,
[SuperBlocks.BackEndDevApis]: 5,
[SuperBlocks.QualityAssurance]: 6,
[SuperBlocks.SciCompPy]: 7,
[SuperBlocks.DataAnalysisPy]: 8,
[SuperBlocks.InfoSec]: 9,
[SuperBlocks.MachineLearningPy]: 10,
[SuperBlocks.CollegeAlgebraPy]: 11,
[SuperBlocks.CodingInterviewPrep]: 12,
[SuperBlocks.ProjectEuler]: 13,
[SuperBlocks.RespWebDesign]: 14,
[SuperBlocks.JsAlgoDataStructNew]: 15,
[SuperBlocks.TheOdinProject]: 16,
[SuperBlocks.FoundationalCSharp]: 17,
[SuperBlocks.ExampleCertification]: 18
};
describe('createSuperOrder', () => {
const superOrder = createSuperOrder(mockSuperBlocks);
it('should create the correct object given an array of SuperBlocks', () => {
expect(superOrder).toStrictEqual(fullSuperOrder);
});
it('throws when not given an array of SuperBlocks', () => {
expect.assertions(4);
expect(() => getSuperOrder()).toThrow();
expect(() => getSuperOrder(null)).toThrow();
expect(() => getSuperOrder('')).toThrow();
expect(() => getSuperOrder(['respansive-wib-desoin'])).toThrow();
});
});
describe('getSuperOrder', () => {
it('returns a number for valid superblocks', () => {
expect.assertions(1);
expect(typeof getSuperOrder('responsive-web-design')).toBe('number');
});
it('throws for unknown superblocks', () => {
expect.assertions(4);
expect(() => getSuperOrder()).toThrow();
expect(() => getSuperOrder(null)).toThrow();
expect(() => getSuperOrder('')).toThrow();
expect(() => getSuperOrder('respansive-wib-desoin')).toThrow();
});
it('throws for "certifications"', () => {
feat: enable new curriculum (#44183) * feat: use legacy flag chore: reorder challenges fix: linter revert: server change feat: unblock new editor fix: proper order fix: 0-based order fix: broke the order feat: move tribute certification to its own block feat: split the old projects block into 4 fix: put all blocks in order chore: add intro text refactor: use block, not blockName in query fix: project progress indicator * fix: reorder new challenges/certs * fix: reorder legacy challenges * fix: reintroduce legacy certs * feat: add showNewCurriculum flag to env * chore: forgot sample.env * feat: use feature flag for display * fix: rename meta + dirs to match new blocks * fix: add new blocks to help-category-map * fix: update completion-modal for new GQL schema * test: duplicate title/id errors -> warnings * fix: update completion-modal to new GQL schema Mk2 * chore: re-order metas (again) * fix: revert super-block-intro changes The intro needs to show both legacy and new content. We need to decide which pages are created, rather than than what a page shows when rendered. * feat: move upcoming curriculum into own superblock * fix: handle one certification with two superBlocks * fix: remove duplicated intros * fix: remove duplicate projects from /settings * fix: drop 'two' from Responsive Web Design Two * chore: rename slug suffix from two to v2 * feat: control display of new curriculum * feat: control project paths shown on /settings * fix: use new project order for /settings This does mean that /settings will change before the release, but I don't think it's serious. All the projects are there, just not in the legacy order. * fix: claim/show cert button * chore: remove isLegacy Since we have legacy superblocks, we don't currently need individual blocks to be legacy * test: fix utils.test * fix: verifyCanClaim needs certification If Shaun removes the cert claim cards, maybe we can remove this entirely * fix: add hasEditableBoundaries flags where needed * chore: remove isUpcomingChange * chore: v2 -> 22 Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
2021-12-20 18:36:31 +00:00
expect.assertions(1);
expect(() => getSuperOrder('certifications')).toThrow();
});
it('returns unique numbers for all current superblocks', () => {
if (
process.env.SHOW_NEW_CURRICULUM !== 'true' &&
process.env.SHOW_UPCOMING_CHANGES !== 'true'
) {
expect.assertions(15);
} else if (process.env.SHOW_NEW_CURRICULUM !== 'true') {
expect.assertions(15);
} else if (process.env.SHOW_UPCOMING_CHANGES !== 'true') {
expect.assertions(15);
} else {
expect.assertions(19);
}
expect(getSuperOrder(SuperBlocks.RespWebDesignNew)).toBe(0);
expect(getSuperOrder(SuperBlocks.JsAlgoDataStruct)).toBe(1);
expect(getSuperOrder(SuperBlocks.FrontEndDevLibs)).toBe(2);
expect(getSuperOrder(SuperBlocks.DataVis)).toBe(3);
expect(getSuperOrder(SuperBlocks.RelationalDb)).toBe(4);
expect(getSuperOrder(SuperBlocks.BackEndDevApis)).toBe(5);
expect(getSuperOrder(SuperBlocks.QualityAssurance)).toBe(6);
expect(getSuperOrder(SuperBlocks.SciCompPy)).toBe(7);
expect(getSuperOrder(SuperBlocks.DataAnalysisPy)).toBe(8);
expect(getSuperOrder(SuperBlocks.InfoSec)).toBe(9);
expect(getSuperOrder(SuperBlocks.MachineLearningPy)).toBe(10);
expect(getSuperOrder(SuperBlocks.CollegeAlgebraPy)).toBe(11);
expect(getSuperOrder(SuperBlocks.CodingInterviewPrep)).toBe(12);
expect(getSuperOrder(SuperBlocks.ProjectEuler)).toBe(13);
expect(getSuperOrder(SuperBlocks.RespWebDesign)).toBe(14);
if (
process.env.SHOW_NEW_CURRICULUM === 'true' &&
process.env.SHOW_UPCOMING_CHANGES === 'true'
) {
expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(15);
expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(16);
expect(getSuperOrder(SuperBlocks.FoundationalCSharp)).toBe(17);
expect(getSuperOrder(SuperBlocks.ExampleCertification)).toBe(18);
} else if (process.env.SHOW_NEW_CURRICULUM === 'true') {
return;
} else if (process.env.SHOW_UPCOMING_CHANGES === 'true') {
expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(15);
expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(16);
expect(getSuperOrder(SuperBlocks.FoundationalCSharp)).toBe(17);
expect(getSuperOrder(SuperBlocks.ExampleCertification)).toBe(18);
}
});
});
describe('getSuperBlockFromPath', () => {
const directories = fs.readdirSync(
path.join(__dirname, './challenges/english')
);
it('handles all the directories in ./challenges/english', () => {
expect.assertions(20);
for (const directory of directories) {
expect(() => getSuperBlockFromDir(directory)).not.toThrow();
}
});
it("returns valid superblocks (or 'certifications') for all valid arguments", () => {
expect.assertions(20);
const superBlockPaths = directories.filter(x => x !== '00-certifications');
for (const directory of superBlockPaths) {
expect(Object.values(SuperBlocks)).toContain(
getSuperBlockFromDir(directory)
);
}
expect(getSuperBlockFromDir('00-certifications')).toBe('certifications');
});
it("returns all valid superblocks (and 'certifications')", () => {
expect.assertions(1);
const superBlocks = new Set();
for (const directory of directories) {
superBlocks.add(getSuperBlockFromDir(directory));
}
// + 1 for 'certifications'
expect(superBlocks.size).toBe(Object.values(SuperBlocks).length + 1);
});
it('throws if a directory is unknown', () => {
expect.assertions(1);
expect(() => getSuperBlockFromDir('unknown')).toThrow();
});
});