mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat: support beforeEach and afterEach (#60921)
Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
committed by
GitHub
parent
38cd1727e4
commit
2a7b220a4f
@@ -0,0 +1,40 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --after-each--
|
||||
|
||||
```js
|
||||
// after each code
|
||||
function cleanup() {
|
||||
return 'cleaned up';
|
||||
}
|
||||
cleanup();
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --after-each--
|
||||
|
||||
gubbins
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --before-each--
|
||||
|
||||
gubbins
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --before-each--
|
||||
|
||||
```js
|
||||
// before each code
|
||||
function setup() {
|
||||
return 'initialized';
|
||||
}
|
||||
setup();
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --after-each--
|
||||
|
||||
```js
|
||||
// after each code
|
||||
function cleanup() {
|
||||
return 'cleaned up';
|
||||
}
|
||||
cleanup();
|
||||
```
|
||||
|
||||
gubbins
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --before-each--
|
||||
|
||||
```js
|
||||
// before each code
|
||||
function setup() {
|
||||
return 'initialized';
|
||||
}
|
||||
setup();
|
||||
```
|
||||
|
||||
gubbins
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --after-each--
|
||||
|
||||
```ts
|
||||
// after each code
|
||||
function cleanup() {
|
||||
return 'cleaned up';
|
||||
}
|
||||
cleanup();
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# --description--
|
||||
|
||||
Paragraph 1
|
||||
|
||||
```html
|
||||
code example
|
||||
```
|
||||
|
||||
# --before-each--
|
||||
|
||||
```ts
|
||||
// before each code
|
||||
function setup() {
|
||||
return 'initialized';
|
||||
}
|
||||
setup();
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
First hint
|
||||
|
||||
```js
|
||||
// test code
|
||||
```
|
||||
|
||||
Second hint with <code>code</code>
|
||||
|
||||
```js
|
||||
// more test code
|
||||
```
|
||||
|
||||
Third *hint* with <code>code</code> and `inline code`
|
||||
|
||||
```js
|
||||
// more test code
|
||||
if(let x of xs) {
|
||||
console.log(x);
|
||||
}
|
||||
```
|
||||
@@ -7,7 +7,7 @@ const addFillInTheBlank = require('./plugins/add-fill-in-the-blank');
|
||||
const addFrontmatter = require('./plugins/add-frontmatter');
|
||||
const addSeed = require('./plugins/add-seed');
|
||||
const addSolution = require('./plugins/add-solution');
|
||||
const addBeforeHook = require('./plugins/add-before-hook');
|
||||
const addHooks = require('./plugins/add-hooks');
|
||||
const addTests = require('./plugins/add-tests');
|
||||
const addText = require('./plugins/add-text');
|
||||
const addVideoQuestion = require('./plugins/add-video-question');
|
||||
@@ -53,7 +53,7 @@ const processor = unified()
|
||||
.use(addAssignment)
|
||||
.use(addScene)
|
||||
.use(addQuizzes)
|
||||
.use(addBeforeHook)
|
||||
.use(addHooks)
|
||||
.use(addTests)
|
||||
.use(addText, [
|
||||
'description',
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
const { getSection } = require('./utils/get-section');
|
||||
|
||||
function plugin() {
|
||||
return transformer;
|
||||
|
||||
function transformer(tree, file) {
|
||||
const section = getSection(tree, '--before-all--');
|
||||
|
||||
if (section.length === 0) return;
|
||||
if (section.length > 1)
|
||||
throw Error(
|
||||
'#--before-all-- section must only contain a single code block'
|
||||
);
|
||||
|
||||
const codeNode = section[0];
|
||||
|
||||
if (codeNode.type !== 'code')
|
||||
throw Error('#--before-all-- section must contain a code block');
|
||||
if (codeNode.lang !== 'javascript' && codeNode.lang !== 'js')
|
||||
throw Error('#--before-all-- hook must be written in JavaScript');
|
||||
|
||||
const beforeAll = getBeforeAll(codeNode);
|
||||
file.data.hooks = { beforeAll };
|
||||
}
|
||||
}
|
||||
|
||||
function getBeforeAll(codeNode) {
|
||||
const beforeAll = codeNode.value;
|
||||
|
||||
return beforeAll;
|
||||
}
|
||||
|
||||
module.exports = plugin;
|
||||
@@ -1,67 +0,0 @@
|
||||
const parseFixture = require('../__fixtures__/parse-fixture');
|
||||
|
||||
const addBeforeHook = require('./add-before-hook');
|
||||
|
||||
describe('add-before-hook plugin', () => {
|
||||
let withBeforeHookAST,
|
||||
withInvalidHookAST,
|
||||
withAnotherInvalidHookAST,
|
||||
withNonJSHookAST;
|
||||
|
||||
const plugin = addBeforeHook();
|
||||
let file = { data: {} };
|
||||
|
||||
beforeAll(async () => {
|
||||
withBeforeHookAST = await parseFixture('with-before-hook.md');
|
||||
withInvalidHookAST = await parseFixture('with-invalid-before-hook.md');
|
||||
withAnotherInvalidHookAST = await parseFixture(
|
||||
'with-another-invalid-before-hook.md'
|
||||
);
|
||||
withNonJSHookAST = await parseFixture('with-non-js-before-hook.md');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
file = { data: {} };
|
||||
});
|
||||
|
||||
it('returns a function', () => {
|
||||
expect(typeof plugin).toEqual('function');
|
||||
});
|
||||
|
||||
it('adds a `hooks` property to `file.data`', () => {
|
||||
plugin(withBeforeHookAST, file);
|
||||
expect('hooks' in file.data).toBe(true);
|
||||
});
|
||||
|
||||
it('populates `hooks.beforeAll` with the contents of the code block', () => {
|
||||
plugin(withBeforeHookAST, file);
|
||||
expect(file.data.hooks.beforeAll).toBe(`// before all code
|
||||
function foo() {
|
||||
return 'bar';
|
||||
}
|
||||
foo();`);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeAll section has more than one child', () => {
|
||||
expect(() => plugin(withInvalidHookAST, file)).toThrow(
|
||||
`#--before-all-- section must only contain a single code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeAll section does not contain a code block', () => {
|
||||
expect(() => plugin(withAnotherInvalidHookAST, file)).toThrow(
|
||||
`#--before-all-- section must contain a code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the code language is not javascript', () => {
|
||||
expect(() => plugin(withNonJSHookAST, file)).toThrow(
|
||||
`#--before-all-- hook must be written in JavaScript`
|
||||
);
|
||||
});
|
||||
|
||||
it('should have an output to match the snapshot', () => {
|
||||
plugin(withBeforeHookAST, file);
|
||||
expect(file.data).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
const { getSection } = require('./utils/get-section');
|
||||
|
||||
function plugin() {
|
||||
return transformer;
|
||||
|
||||
function transformer(tree, file) {
|
||||
const beforeAll = getHook(tree, '--before-all--');
|
||||
const beforeEach = getHook(tree, '--before-each--');
|
||||
const afterEach = getHook(tree, '--after-each--');
|
||||
|
||||
if (!beforeAll && !beforeEach && !afterEach) return;
|
||||
|
||||
file.data.hooks = file.data.hooks = {
|
||||
...(beforeAll && { beforeAll }),
|
||||
...(beforeEach && { beforeEach }),
|
||||
...(afterEach && { afterEach })
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getHook(tree, sectionName) {
|
||||
const section = getSection(tree, sectionName);
|
||||
|
||||
if (section.length === 0) return;
|
||||
if (section.length > 1)
|
||||
throw Error(
|
||||
`# ${sectionName} section must only contain a single code block`
|
||||
);
|
||||
|
||||
const codeNode = section[0];
|
||||
|
||||
if (codeNode.type !== 'code')
|
||||
throw Error(`# ${sectionName} section must contain a code block`);
|
||||
if (codeNode.lang !== 'javascript' && codeNode.lang !== 'js')
|
||||
throw Error(`# ${sectionName} hook must be written in JavaScript`);
|
||||
|
||||
return codeNode.value;
|
||||
}
|
||||
|
||||
module.exports = plugin;
|
||||
@@ -0,0 +1,149 @@
|
||||
const parseFixture = require('../__fixtures__/parse-fixture');
|
||||
|
||||
const addBeforeHook = require('./add-hooks');
|
||||
|
||||
describe('add-before-hook plugin', () => {
|
||||
let withBeforeHookAST,
|
||||
withInvalidHookAST,
|
||||
withAnotherInvalidHookAST,
|
||||
withNonJSHookAST,
|
||||
withBeforeEachHookAST,
|
||||
withInvalidBeforeEachHookAST,
|
||||
withAnotherInvalidBeforeEachHookAST,
|
||||
withNonJSBeforeEachHookAST,
|
||||
withAfterEachHookAST,
|
||||
withInvalidAfterEachHookAST,
|
||||
withAnotherInvalidAfterEachHookAST,
|
||||
withNonJSAfterEachHookAST;
|
||||
|
||||
const plugin = addBeforeHook();
|
||||
let file = { data: {} };
|
||||
|
||||
beforeAll(async () => {
|
||||
withBeforeHookAST = await parseFixture('with-before-hook.md');
|
||||
withInvalidHookAST = await parseFixture('with-invalid-before-hook.md');
|
||||
withAnotherInvalidHookAST = await parseFixture(
|
||||
'with-another-invalid-before-hook.md'
|
||||
);
|
||||
withNonJSHookAST = await parseFixture('with-non-js-before-hook.md');
|
||||
withBeforeEachHookAST = await parseFixture('with-before-each-hook.md');
|
||||
withInvalidBeforeEachHookAST = await parseFixture(
|
||||
'with-invalid-before-each-hook.md'
|
||||
);
|
||||
withAnotherInvalidBeforeEachHookAST = await parseFixture(
|
||||
'with-another-invalid-before-each-hook.md'
|
||||
);
|
||||
withNonJSBeforeEachHookAST = await parseFixture(
|
||||
'with-non-js-before-each-hook.md'
|
||||
);
|
||||
withAfterEachHookAST = await parseFixture('with-after-each-hook.md');
|
||||
withInvalidAfterEachHookAST = await parseFixture(
|
||||
'with-invalid-after-each-hook.md'
|
||||
);
|
||||
withAnotherInvalidAfterEachHookAST = await parseFixture(
|
||||
'with-another-invalid-after-each-hook.md'
|
||||
);
|
||||
withNonJSAfterEachHookAST = await parseFixture(
|
||||
'with-non-js-after-each-hook.md'
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
file = { data: {} };
|
||||
});
|
||||
|
||||
it('returns a function', () => {
|
||||
expect(typeof plugin).toEqual('function');
|
||||
});
|
||||
|
||||
it('adds a `hooks` property to `file.data`', () => {
|
||||
plugin(withBeforeHookAST, file);
|
||||
expect('hooks' in file.data).toBe(true);
|
||||
});
|
||||
|
||||
it('populates `hooks.beforeAll` with the contents of the code block', () => {
|
||||
plugin(withBeforeHookAST, file);
|
||||
expect(file.data.hooks.beforeAll).toBe(`// before all code
|
||||
function foo() {
|
||||
return 'bar';
|
||||
}
|
||||
foo();`);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeAll section has more than one child', () => {
|
||||
expect(() => plugin(withInvalidHookAST, file)).toThrow(
|
||||
`# --before-all-- section must only contain a single code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeAll section does not contain a code block', () => {
|
||||
expect(() => plugin(withAnotherInvalidHookAST, file)).toThrow(
|
||||
`# --before-all-- section must contain a code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the code language is not javascript', () => {
|
||||
expect(() => plugin(withNonJSHookAST, file)).toThrow(
|
||||
`# --before-all-- hook must be written in JavaScript`
|
||||
);
|
||||
});
|
||||
|
||||
it('should have an output to match the snapshot', () => {
|
||||
plugin(withBeforeHookAST, file);
|
||||
expect(file.data).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('populates `hooks.beforeEach` with the contents of the code block', () => {
|
||||
plugin(withBeforeEachHookAST, file);
|
||||
expect(file.data.hooks.beforeEach).toBe(`// before each code
|
||||
function setup() {
|
||||
return 'initialized';
|
||||
}
|
||||
setup();`);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeEach section has more than one child', () => {
|
||||
expect(() => plugin(withInvalidBeforeEachHookAST, file)).toThrow(
|
||||
`# --before-each-- section must only contain a single code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeEach section does not contain a code block', () => {
|
||||
expect(() => plugin(withAnotherInvalidBeforeEachHookAST, file)).toThrow(
|
||||
`# --before-each-- section must contain a code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the beforeEach code language is not javascript', () => {
|
||||
expect(() => plugin(withNonJSBeforeEachHookAST, file)).toThrow(
|
||||
`# --before-each-- hook must be written in JavaScript`
|
||||
);
|
||||
});
|
||||
|
||||
it('populates `hooks.afterEach` with the contents of the code block', () => {
|
||||
plugin(withAfterEachHookAST, file);
|
||||
expect(file.data.hooks.afterEach).toBe(`// after each code
|
||||
function cleanup() {
|
||||
return 'cleaned up';
|
||||
}
|
||||
cleanup();`);
|
||||
});
|
||||
|
||||
it('should throw an error if the afterEach section has more than one child', () => {
|
||||
expect(() => plugin(withInvalidAfterEachHookAST, file)).toThrow(
|
||||
`# --after-each-- section must only contain a single code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the afterEach section does not contain a code block', () => {
|
||||
expect(() => plugin(withAnotherInvalidAfterEachHookAST, file)).toThrow(
|
||||
`# --after-each-- section must contain a code block`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the afterEach code language is not javascript', () => {
|
||||
expect(() => plugin(withNonJSAfterEachHookAST, file)).toThrow(
|
||||
`# --after-each-- hook must be written in JavaScript`
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user