Files
freeCodeCamp/tools/challenge-parser/parser/plugins/add-text.test.js

225 lines
8.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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,
withNestedInstructionsAST,
withChineseAST,
withEnUsAST,
withEsAST;
const descriptionId = 'description';
const instructionsId = 'instructions';
const missingId = 'missing';
let file = { data: {} };
beforeAll(async () => {
realisticAST = await parseFixture('realistic.md');
mockAST = await parseFixture('simple.md');
withSubSectionAST = await parseFixture('with-subsection.md');
withNestedInstructionsAST = await parseFixture(
'with-nested-instructions.md'
);
withChineseAST = await parseFixture('with-chinese-mcq.md');
withEnUsAST = await parseFixture('with-en-us-mcq.md');
withEsAST = await parseFixture('with-es-mcq.md');
});
beforeEach(() => {
file = { data: {} };
});
it('should return a function', () => {
const plugin = addText(['section']);
expect(typeof plugin).toEqual('function');
});
it('throws when no argument or the incorrect argument is supplied', () => {
expect.assertions(5);
const expectedError = 'addText must have an array of section ids supplied';
expect(() => {
addText();
}).toThrow(expectedError);
expect(() => {
addText('');
}).toThrow(expectedError);
expect(() => {
addText({});
}).toThrow(expectedError);
expect(() => {
addText(1);
}).toThrow(expectedError);
expect(() => {
addText([]);
}).toThrow(expectedError);
});
it('throws when there is a sub-section in one of the sections', () => {
const plugin = addText([instructionsId, descriptionId]);
expect(() => {
plugin(withSubSectionAST, file);
}).toThrow(
'The --description-- section should not have any subsections. Found subsection --not-allowed--'
);
});
it('should add a string relating to the section id to `file.data`', () => {
const plugin = addText([descriptionId]);
plugin(mockAST, file);
const expectedText = 'Paragraph 1';
expect(file.data[descriptionId]).toEqual(
expect.stringContaining(expectedText)
);
});
it('should not add a string relating a different id to `file.data`', () => {
const plugin = addText([descriptionId]);
plugin(mockAST, file);
// the following text is in the AST, but is associated with a different
// marker (instructions)
const expectedText = 'Paragraph 0';
expect(file.data[descriptionId]).not.toEqual(
expect.stringContaining(expectedText)
);
});
// TODO: do we need to add the ids to the section tags? Why not just have
// <section>?
it('should embed the text in sections with appropriate ids', () => {
const plugin = addText([descriptionId, instructionsId]);
plugin(mockAST, file);
// the following text is in the AST, but is associated with a different
// marker (instructions)
const descriptionSectionText = `<section id="description">
<p>Paragraph 1</p>
<pre><code class="language-html">code example
</code></pre>
</section>`;
expect(file.data[descriptionId]).toEqual(descriptionSectionText);
const instructionsSectionText = `<section id="instructions">
<p>Paragraph 0</p>
<pre><code class="language-html">code example 0
</code></pre>
</section>`;
expect(file.data[instructionsId]).toBe(instructionsSectionText);
});
it('should add nothing if a section id does not appear in the md', () => {
const plugin = addText([missingId]);
plugin(mockAST, file);
expect(file.data[descriptionId]).toBeUndefined();
});
it('should not escape html', () => {
const plugin = addText([descriptionId]);
plugin(realisticAST, file);
const expected = `last <code>h2</code> element`;
expect(file.data[descriptionId]).toEqual(expect.stringContaining(expected));
});
it('should preserve nested html', () => {
const plugin = addText([descriptionId]);
plugin(realisticAST, file);
const expected = `<blockquote>
<p>Some text in a blockquote</p>
<p>
Some text in a blockquote, with <code>code</code>
</p>
</blockquote>`;
expect(file.data[descriptionId]).toEqual(expect.stringContaining(expected));
});
it('should not add paragraphs when html elements are separated by whitespace', () => {
const plugin = addText([instructionsId]);
plugin(realisticAST, file);
const expectedText1 = `<code>code</code> <tag>with more after a space</tag>`;
const expectedText2 = `another pair of <strong>elements</strong> <em>with a space</em>`;
expect(file.data[instructionsId]).toEqual(
expect.stringContaining(expectedText1)
);
expect(file.data[instructionsId]).toEqual(
expect.stringContaining(expectedText2)
);
});
it('should ignore --instructions-- markers that are not at depth 1', () => {
const plugin = addText([instructionsId]);
plugin(withNestedInstructionsAST, file);
// Should only include the depth 1 instructions, not the nested ones
const expectedText = `<section id="instructions">
<p>These are the main instructions at depth 1.</p>
<pre><code class="language-html">&#x3C;div>Main instructions code&#x3C;/div>
</code></pre>
</section>`;
expect(file.data[instructionsId]).toEqual(expectedText);
});
it('should have an output to match the snapshot', () => {
const plugin = addText([descriptionId, instructionsId]);
plugin(mockAST, file);
expect(file.data).toMatchSnapshot();
});
it('should render inline code as code elements when lang is undefined', () => {
const plugin = addText(['instructions', 'explanation']);
const defaultFile = { data: {} };
plugin(withChineseAST, defaultFile);
expect(defaultFile.data.instructions).toBe(
'<section id="instructions">\n<p>Instructions containing <code>汉字 (hàn zì)</code>.</p>\n</section>'
);
expect(defaultFile.data.explanation).toBe(
'<section id="explanation">\n<p><code>我是 (wǒ shì) Web 开发者 (kāi fā zhě)。</code> I am a web developer.</p>\n<p><code>你好 (nǐ hǎo),我是王华 (wǒ shì Wang Hua),请问你叫什么名字 (qǐng wèn nǐ jiào shén me míng zi)</code> Hello, I am Wang Hua, may I ask what your name is?</p>\n</section>'
);
});
it('should render Chinese inline code as ruby when lang is zh-CN', () => {
const plugin = addText(['instructions', 'explanation']);
const zhFile = { data: { lang: 'zh-CN' } };
plugin(withChineseAST, zhFile);
expect(zhFile.data.instructions).toBe(
'<section id="instructions">\n<p>Instructions containing <ruby>汉字<rp>(</rp><rt>hàn zì</rt><rp>)</rp></ruby>.</p>\n</section>'
);
expect(zhFile.data.explanation).toBe(
'<section id="explanation">\n<p><ruby>我是<rp>(</rp><rt>wǒ shì</rt><rp>)</rp></ruby> Web <ruby>开发者<rp>(</rp><rt>kāi fā zhě</rt><rp>)</rp></ruby>。 I am a web developer.</p>\n<p><ruby>你好<rp>(</rp><rt>nǐ hǎo</rt><rp>)</rp></ruby><ruby>我是王华<rp>(</rp><rt>wǒ shì Wang Hua</rt><rp>)</rp></ruby><ruby>请问你叫什么名字<rp>(</rp><rt>qǐng wèn nǐ jiào shén me míng zi</rt><rp>)</rp></ruby> Hello, I am Wang Hua, may I ask what your name is?</p>\n</section>'
);
});
it('should render inline code as span elements when lang is en-US', () => {
const plugin = addText(['instructions', 'explanation']);
const enUsFile = { data: { lang: 'en-US' } };
plugin(withEnUsAST, enUsFile);
expect(enUsFile.data.instructions).toBe(
'<section id="instructions">\n<p>Instructions containing <span class="highlighted-text">some code</span>.</p>\n</section>'
);
expect(enUsFile.data.explanation).toBe(
'<section id="explanation">\n<p>Explanation text containing <span class="highlighted-text">highlighted text</span>.</p>\n</section>'
);
});
it('should render inline code as span elements when lang is es', () => {
const plugin = addText(['instructions', 'explanation']);
const esFile = { data: { lang: 'es' } };
plugin(withEsAST, esFile);
expect(esFile.data.instructions).toBe(
'<section id="instructions">\n<p>Instructions containing <span class="highlighted-text">texto resaltado</span>.</p>\n</section>'
);
expect(esFile.data.explanation).toBe(
'<section id="explanation">\n<p>Explanation text containing <span class="highlighted-text">texto resaltado</span>.</p>\n</section>'
);
});
});