refactor: migrate challenge parser tests to vitest (#62186)

This commit is contained in:
Oliver Eyton-Williams
2025-09-12 18:50:02 +02:00
committed by GitHub
parent 2590c1c820
commit 28411a2cec
36 changed files with 257 additions and 288 deletions

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`process-frontmatter plugin should have an output to match the snapshot 1`] = `
exports[`process-frontmatter plugin > should have an output to match the snapshot 1`] = `
{
"challengeType": 0,
"forumTopicId": 18276,

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add-before-hook plugin should have an output to match the snapshot 1`] = `
exports[`add-before-hook plugin > should have an output to match the snapshot 1`] = `
{
"hooks": {
"beforeAll": "// before all code

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add-quizzes plugin should match the quizzes snapshot 1`] = `
exports[`add-quizzes plugin > should match the quizzes snapshot 1`] = `
{
"quizzes": [
{

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add-seed plugin should have an output to match the snapshot 1`] = `
exports[`add-seed plugin > should have an output to match the snapshot 1`] = `
{
"challengeFiles": [
{

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add solution plugin should have an output to match the snapshot 1`] = `
exports[`add solution plugin > should have an output to match the snapshot 1`] = `
{
"solutions": [
[

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add-tests plugin should have an output to match the snapshot 1`] = `
exports[`add-tests plugin > should have an output to match the snapshot 1`] = `
{
"tests": [
{

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add-text should have an output to match the snapshot 1`] = `
exports[`add-text > should have an output to match the snapshot 1`] = `
{
"description": "<section id="description">
<p>Paragraph 1</p>

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`add-video-question plugin should match the video snapshot 1`] = `
exports[`add-video-question plugin > should match the video snapshot 1`] = `
{
"questions": [
{

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`replace-imports should have an output to match the snapshot 1`] = `
exports[`replace-imports > should have an output to match the snapshot 1`] = `
{
"children": [
{

View File

@@ -1,5 +1,6 @@
const parseFixture = require('../__fixtures__/parse-fixture');
const addFillInTheBlankQuestion = require('./add-fill-in-the-blank');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import parseFixture from '../__fixtures__/parse-fixture';
import addFillInTheBlankQuestion from './add-fill-in-the-blank';
describe('fill-in-the-blanks plugin', () => {
let mockFillInTheBlankAST,

View File

@@ -1,7 +1,8 @@
const { isObject } = require('lodash');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import { isObject } from 'lodash';
const parse = require('../__fixtures__/parse-fixture');
const processFrontmatter = require('./add-frontmatter');
import parse from '../__fixtures__/parse-fixture';
import processFrontmatter from './add-frontmatter';
describe('process-frontmatter plugin', () => {
let mockAST;

View File

@@ -1,6 +1,7 @@
const parseFixture = require('../__fixtures__/parse-fixture');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import parseFixture from '../__fixtures__/parse-fixture';
const addBeforeHook = require('./add-hooks');
import addBeforeHook from './add-hooks';
describe('add-before-hook plugin', () => {
let withBeforeHookAST,

View File

@@ -1,5 +1,6 @@
const parseFixture = require('./../__fixtures__/parse-fixture');
const addQuizzes = require('./add-quizzes');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import parseFixture from './../__fixtures__/parse-fixture';
import addQuizzes from './add-quizzes';
describe('add-quizzes plugin', () => {
let mockQuizzesAST;

View File

@@ -1,7 +1,8 @@
const isArray = require('lodash/isArray');
const parseFixture = require('../__fixtures__/parse-fixture');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import isArray from 'lodash/isArray';
import parseFixture from '../__fixtures__/parse-fixture';
const addSeed = require('./add-seed');
import addSeed from './add-seed';
describe('add-seed plugin', () => {
let adjacentKeysAST,

View File

@@ -1,6 +1,7 @@
const { isObject } = require('lodash');
const parseFixture = require('../__fixtures__/parse-fixture');
const addSolution = require('./add-solution');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import { isObject } from 'lodash';
import parseFixture from '../__fixtures__/parse-fixture';
import addSolution from './add-solution';
describe('add solution plugin', () => {
let mockAST, multiSolnsAST, editableSolutionAST;

View File

@@ -1,5 +1,6 @@
const parseFixture = require('../__fixtures__/parse-fixture');
const addTests = require('./add-tests');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import parseFixture from '../__fixtures__/parse-fixture';
import addTests from './add-tests';
describe('add-tests plugin', () => {
let brokenHintsAST, simpleAST, missingTestStringAST;

View File

@@ -1,5 +1,6 @@
const parseFixture = require('../__fixtures__/parse-fixture');
const addText = require('./add-text');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import parseFixture from '../__fixtures__/parse-fixture';
import addText from './add-text';
describe('add-text', () => {
let realisticAST, mockAST, withSubSectionAST;

View File

@@ -1,5 +1,6 @@
const parseFixture = require('../__fixtures__/parse-fixture');
const addVideoQuestion = require('./add-video-question');
import { describe, beforeAll, beforeEach, it, expect } from 'vitest';
import parseFixture from '../__fixtures__/parse-fixture';
import addVideoQuestion from './add-video-question';
describe('add-video-question plugin', () => {
let simpleAST, videoAST, multipleQuestionAST, videoOutOfOrderAST;

View File

@@ -1,10 +1,11 @@
const path = require('path');
const cloneDeep = require('lodash/cloneDeep');
const toVfile = require('to-vfile');
const selectAll = require('unist-util-select').selectAll;
const parseFixture = require('../__fixtures__/parse-fixture');
import { resolve } from 'path';
import { describe, beforeAll, beforeEach, it, expect, vi } from 'vitest';
import cloneDeep from 'lodash/cloneDeep';
import toVfile from 'to-vfile';
import { selectAll } from 'unist-util-select';
import parseFixture from '../__fixtures__/parse-fixture';
const addImports = require('./replace-imports');
import addImports from './replace-imports';
describe('replace-imports', () => {
let importsAST,
@@ -36,10 +37,10 @@ describe('replace-imports', () => {
simpleAST = cloneDeep(originalSimpleAST);
markerAST = cloneDeep(originalMarkerAST);
correctFile = toVfile(
path.resolve(__dirname, '../__fixtures__/with-imports.md')
resolve(__dirname, '../__fixtures__/with-imports.md')
);
incorrectFile = toVfile(
path.resolve(__dirname, '../__fixtures__/incorrect-path/with-imports.md')
resolve(__dirname, '../__fixtures__/incorrect-path/with-imports.md')
);
});
@@ -50,70 +51,66 @@ describe('replace-imports', () => {
expect(typeof plugin).toEqual('function');
});
it('should fail when the imported file is null', done => {
it('should fail when the imported file is null', () => {
const plugin = addImports();
const next = err => {
if (err) {
done();
} else {
done('An error should have been thrown by addImports');
}
};
plugin(importsAST, null, next);
const nextSpy = vi.fn();
plugin(importsAST, null, nextSpy);
expect(nextSpy).toHaveBeenCalledWith(
'replace-imports must be passed a file'
);
});
it('should proceed when the imported file exists', done => {
const plugin = addImports();
plugin(importsAST, correctFile, done);
});
it('should fail when the imported file cannot be found', done => {
expect.assertions(1);
console.error = jest.fn();
it('should proceed when the imported file exists', async () => {
const plugin = addImports();
// we have to rely on the next callback, because that is how you get error
// messages out of transformers
const next = err => {
if (err) {
expect(console.error).toHaveBeenCalledTimes(2);
done();
} else {
done('An error should have been thrown by addImports');
}
};
plugin(importsAST, incorrectFile, next);
await new Promise(resolve => {
plugin(importsAST, correctFile, resolve);
});
});
it('should modify the tree when there are imports', done => {
it('should fail when the imported file cannot be found', async () => {
expect.assertions(2);
console.error = vi.fn();
const plugin = addImports();
await expect(
new Promise((resolve, reject) => {
plugin(importsAST, incorrectFile, err => {
if (err) {
expect(console.error).toHaveBeenCalledTimes(2);
resolve();
} else {
reject('An error should have been thrown by addImports');
}
});
})
).resolves.toBeUndefined();
});
it('should modify the tree when there are imports', async () => {
expect.assertions(1);
const plugin = addImports();
const next = err => {
if (err) {
done(err);
} else {
expect(importsAST).not.toEqual(originalImportsAST);
done();
}
};
plugin(importsAST, correctFile, next);
await new Promise(resolve => {
plugin(importsAST, correctFile, resolve);
});
expect(importsAST).not.toEqual(originalImportsAST);
});
it('should NOT modify the tree when there are NO imports', done => {
it('should NOT modify the tree when there are NO imports', async () => {
expect.assertions(1);
const plugin = addImports();
const next = err => {
if (err) {
done(err);
} else {
expect(simpleAST).toEqual(originalSimpleAST);
done();
}
};
plugin(simpleAST, correctFile, next);
await new Promise(resolve => {
plugin(simpleAST, correctFile, resolve);
});
expect(simpleAST).toEqual(originalSimpleAST);
});
it('should remove all import statements', done => {
it('should remove all import statements', async () => {
expect.assertions(2);
const selector = 'leafDirective[name=import]';
const plugin = addImports();
@@ -121,19 +118,15 @@ describe('replace-imports', () => {
expect(importNodes.length).toBe(1);
const next = err => {
if (err) {
done(err);
} else {
const importNodes = selectAll(selector, importsAST);
expect(importNodes.length).toBe(0);
done();
}
};
plugin(importsAST, correctFile, next);
await new Promise(resolve => {
plugin(importsAST, correctFile, resolve);
});
const importNodesAfter = selectAll(selector, importsAST);
expect(importNodesAfter.length).toBe(0);
});
it('should not remove an ::import without the required attributes', done => {
it('should not remove an ::import without the required attributes', async () => {
expect.assertions(2);
const selector = 'leafDirective[name=import]';
const plugin = addImports();
@@ -141,19 +134,15 @@ describe('replace-imports', () => {
expect(importNodes.length).toBe(3);
const next = err => {
if (err) {
done(err);
} else {
const importNodes = selectAll(selector, importsExtraAST);
expect(importNodes.length).toBe(1);
done();
}
};
plugin(importsExtraAST, correctFile, next);
await new Promise(resolve => {
plugin(importsExtraAST, correctFile, resolve);
});
const importNodesAfter = selectAll(selector, importsExtraAST);
expect(importNodesAfter.length).toBe(1);
});
it('should remove all matching ::use statements', done => {
it('should remove all matching ::use statements', async () => {
expect.assertions(2);
const selector = 'leafDirective[name=use]';
const plugin = addImports();
@@ -162,108 +151,97 @@ describe('replace-imports', () => {
// one matching component and two other jsx nodes
expect(components.length).toBe(1);
const next = err => {
if (err) {
done(err);
} else {
const components = selectAll(selector, importsAST);
expect(components.length).toBe(0);
done();
}
};
plugin(importsAST, correctFile, next);
await new Promise(resolve => {
plugin(importsAST, correctFile, resolve);
});
const componentsAfter = selectAll(selector, importsAST);
expect(componentsAfter.length).toBe(0);
});
it('should replace the ::use statement with the imported content', done => {
it('should replace the ::use statement with the imported content', async () => {
// checks the contents of script.md are there after the import step
expect.assertions(2);
const plugin = addImports();
const next = err => {
if (err) {
done(err);
} else {
const jsNodes = selectAll('code[lang=js]', importsAST);
expect(jsNodes.length).toBe(4);
await new Promise(resolve => {
plugin(importsAST, correctFile, resolve);
});
const codeValues = jsNodes.map(({ value }) => value);
expect(codeValues).toEqual(
expect.arrayContaining([
`for (let index = 0; index < array.length; index++) {
const jsNodes = selectAll('code[lang=js]', importsAST);
expect(jsNodes.length).toBe(4);
const codeValues = jsNodes.map(({ value }) => value);
expect(codeValues).toEqual(
expect.arrayContaining([
`for (let index = 0; index < array.length; index++) {
const element = array[index];
// imported from script.md
}`
])
);
done();
}
};
plugin(importsAST, correctFile, next);
])
);
});
it('should handle multiple import statements', done => {
it('should handle multiple import statements', async () => {
// checks the contents of script.md are there after the import step
expect.assertions(4);
const plugin = addImports();
const next = err => {
if (err) {
done(err);
} else {
const jsNodes = selectAll('code[lang=js]', importsTwoAST);
expect(jsNodes.length).toBe(4);
await new Promise(resolve => {
plugin(importsTwoAST, correctFile, resolve);
});
const codeValues = jsNodes.map(({ value }) => value);
expect(codeValues).toEqual(
expect.arrayContaining([
`for (let index = 0; index < array.length; index++) {
const jsNodes = selectAll('code[lang=js]', importsTwoAST);
expect(jsNodes.length).toBe(4);
const codeValues = jsNodes.map(({ value }) => value);
expect(codeValues).toEqual(
expect.arrayContaining([
`for (let index = 0; index < array.length; index++) {
const element = array[index];
// imported from script.md
}`
])
);
const cssNodes = selectAll('code[lang=css]', importsTwoAST);
expect(cssNodes.length).toBe(2);
])
);
const cssNodes = selectAll('code[lang=css]', importsTwoAST);
expect(cssNodes.length).toBe(2);
const cssValues = cssNodes.map(({ value }) => value);
expect(cssValues).toEqual(
expect.arrayContaining([
`div {
const cssValues = cssNodes.map(({ value }) => value);
expect(cssValues).toEqual(
expect.arrayContaining([
`div {
background: red
}`
])
);
done();
}
};
plugin(importsTwoAST, correctFile, next);
])
);
});
it('should reject imported files with editable region markers', done => {
expect.assertions(1);
console.error = jest.fn();
it('should reject imported files with editable region markers', async () => {
expect.assertions(2); // One inside the callback and one for the outer expect
console.error = vi.fn();
const plugin = addImports();
const next = err => {
if (err) {
expect(console.error).toHaveBeenCalledTimes(2);
done();
} else {
done('An error should have been thrown by addImports');
}
};
plugin(markerAST, correctFile, next);
await expect(
new Promise((resolve, reject) => {
plugin(markerAST, correctFile, err => {
if (err) {
expect(console.error).toHaveBeenCalledTimes(2);
} else {
reject('An error should have been thrown by addImports');
}
resolve();
});
})
).resolves.toBeUndefined();
});
it('should have an output to match the snapshot', done => {
it('should have an output to match the snapshot', async () => {
const plugin = addImports();
const next = err => {
if (err) {
done(err);
} else {
expect(importsAST).toMatchSnapshot();
done();
}
};
plugin(importsAST, correctFile, next);
await new Promise(resolve => {
plugin(importsAST, correctFile, resolve);
});
expect(importsAST).toMatchSnapshot();
});
});

View File

@@ -1,9 +1,10 @@
const cloneDeep = require('lodash/cloneDeep');
const find = require('unist-util-find');
const { selectAll } = require('unist-util-select');
import { describe, beforeEach, beforeAll, it, expect } from 'vitest';
import cloneDeep from 'lodash/cloneDeep';
import find from 'unist-util-find';
import { selectAll } from 'unist-util-select';
const parseFixture = require('../__fixtures__/parse-fixture');
const restoreDirectives = require('./restore-directives');
import parseFixture from '../__fixtures__/parse-fixture';
import restoreDirectives from './restore-directives';
describe('restore-directives', () => {
let directivesAST, directivesOriginalAST;

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`getSection should match the hints snapshot 1`] = `
exports[`getSection > should match the hints snapshot 1`] = `
[
{
"children": [
@@ -338,7 +338,7 @@ if(let x of xs) {
]
`;
exports[`getSection should match the instructions snapshot 1`] = `
exports[`getSection > should match the instructions snapshot 1`] = `
[
{
"children": [

View File

@@ -1,7 +1,8 @@
const isArray = require('lodash/isArray');
import isArray from 'lodash/isArray';
import { describe, beforeAll, it, expect } from 'vitest';
const parseFixture = require('../../__fixtures__/parse-fixture');
const getAllBefore = require('./before-heading');
import parseFixture from '../../__fixtures__/parse-fixture';
import getAllBefore from './before-heading';
describe('before-headings', () => {
let simpleAst;

View File

@@ -1,4 +1,6 @@
const { findAll } = require('./find-all');
import { describe, it, expect } from 'vitest';
import { findAll } from './find-all';
const testTree = {
type: 'root',

View File

@@ -1,33 +0,0 @@
describe('get-file-visitor', () => {
it('should join code with newlines', () => {
/* i.e. if you've got two js code blocks it should do this
```js
one
```
```js
two
```
become
```js
one
two
```
not
```js
onetwo
```
or
```js
one
two
```
*/
});
});

View File

@@ -1,5 +1,7 @@
const parseFixture = require('../../__fixtures__/parse-fixture');
const getId = require('./get-id');
import { describe, beforeAll, it, expect } from 'vitest';
import parseFixture from '../../__fixtures__/parse-fixture';
import getId from './get-id';
describe('get-id', () => {
let idNode, imageNode, multipleChildrenNode;

View File

@@ -1,5 +1,7 @@
const parseFixture = require('../../__fixtures__/parse-fixture');
const { getParagraphContent } = require('./get-paragraph-content');
import { describe, beforeAll, it, expect } from 'vitest';
import parseFixture from '../../__fixtures__/parse-fixture';
import { getParagraphContent } from './get-paragraph-content';
describe('getParagraphContent', () => {
let simpleAST;

View File

@@ -1,9 +1,10 @@
const isArray = require('lodash/isArray');
const { root } = require('mdast-builder');
const find = require('unist-util-find');
import { describe, beforeAll, it, expect } from 'vitest';
import isArray from 'lodash/isArray';
import { root } from 'mdast-builder';
import find from 'unist-util-find';
const parseFixture = require('../../__fixtures__/parse-fixture');
const { getSection } = require('./get-section');
import parseFixture from '../../__fixtures__/parse-fixture';
import { getSection } from './get-section';
describe('getSection', () => {
let simpleAst, extraHeadingAst;

View File

@@ -1,5 +1,6 @@
const parseFixture = require('../../__fixtures__/parse-fixture');
const mdastToHTML = require('./mdast-to-html');
import { describe, beforeAll, it, expect } from 'vitest';
import parseFixture from '../../__fixtures__/parse-fixture';
import mdastToHTML from './mdast-to-html';
describe('mdast-to-html', () => {
let mdastMixedNodes, singleNode, inlineHTMLNodes;

View File

@@ -1,8 +1,10 @@
const unified = require('unified');
const remark = require('remark-parse');
const frontmatter = require('remark-frontmatter');
const addFrontmatter = require('./add-frontmatter');
const validateSections = require('./validate-sections');
import { describe, it, expect } from 'vitest';
import unified from 'unified';
import remark from 'remark-parse';
import frontmatter from 'remark-frontmatter';
import addFrontmatter from './add-frontmatter';
import validateSections from './validate-sections';
const processor = unified()
.use(remark)