refactor: files{} -> challengeFiles[], and key -> fileKey (#43023)

* fix(client): fix client

* fix propType and add comment

* revert user.json prettification

* slight type refactor and payload correction

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* update ChallengeFile type imports

* add cypress test for code-storage

* update test and storage epic

* fix Shaun's tired brain's logic

* refactor with suggestions

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* update codeReset

* increate cypress timeout because firefox is slow

* remove unused import to make linter happy

* use focus on editor

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* use more specific seletor for cypress editor test

* account for silly null challengeFiles

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Shaun Hamilton
2021-08-12 19:48:28 +01:00
committed by GitHub
parent 1f62dfe2b3
commit 59f17f237b
41 changed files with 916 additions and 910 deletions

View File

@ -13,7 +13,7 @@ a container directive
:::</p>
</section>",
"solutions": Array [
Object {},
Array [],
],
"tests": Array [],
}
@ -44,7 +44,7 @@ Object {
</code></pre>",
},
"solutions": Array [
Object {},
Array [],
],
"tests": Array [],
}
@ -52,38 +52,33 @@ Object {
exports[`challenge parser should import md from other files 1`] = `
Object {
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
</code></pre>
</section>",
"files": Object {
"indexcss": Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';
for (let index = 0; index < array.length; index++) {
const element = array[index];
@ -91,20 +86,25 @@ for (let index = 0; index < array.length; index++) {
}",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "custom-name",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
</code></pre>
</section>",
"instructions": "<section id=\\"instructions\\">
<p>Paragraph 0</p>
<pre><code class=\\"language-html\\">code example 0
</code></pre>
</section>",
"solutions": Array [
Object {},
Array [],
],
"tests": Array [
Object {
@ -121,6 +121,43 @@ for (let index = 0; index < array.length; index++) {
exports[`challenge parser should not mix other YAML with the frontmatter 1`] = `
Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
],
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
@ -130,50 +167,13 @@ Object {
anothersubkey: another value
</code></pre>
</section>",
"files": Object {
"indexcss": Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"head": "",
"id": "",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
"instructions": "<section id=\\"instructions\\">
<p>Paragraph 0</p>
<pre><code class=\\"language-html\\">code example 0
</code></pre>
</section>",
"solutions": Array [
Object {},
Array [],
],
"tests": Array [
Object {
@ -190,42 +190,8 @@ Object {
exports[`challenge parser should parse a more realistic md file 1`] = `
Object {
"description": "<section id=\\"description\\">
<p>When you add a lower rank heading element to the page, it's implied that you're starting a new subsection.</p>
<p>After the last <code>h2</code> element of the second <code>section</code> element, add an <code>h3</code> element with the text <code>Things cats love:</code>.</p>
<blockquote>
<p>Some text in a blockquote</p>
<p>
Some text in a blockquote, with <code>code</code>
</p>
</blockquote>
</section>",
"files": Object {
"indexcss": Object {
"contents": "body {
background: white;
}
h1 {
font-size: 20px;
}
a {
color: green;
}",
"editableRegionBoundaries": Array [
7,
9,
],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
<h1>CatPhotoApp</h1>
@ -256,32 +222,14 @@ a {
23,
],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "html-key",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"head": " // this runs before the user's code is evaluated.",
"id": "final-key",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
"instructions": "<section id=\\"instructions\\">
<p>Do something with the <code>code</code>.</p>
<p>To test that adjacent tags are handled correctly:</p>
<p>a bit of <code>code</code> <tag>with more after a space</tag> and another pair of <strong>elements</strong> <em>with a space</em></p>
</section>",
"solutions": Array [
Object {
"indexcss": Object {
"contents": "body {
"contents": "body {
background: white;
}
@ -293,14 +241,46 @@ h1 {
a {
color: green;
}",
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"editableRegionBoundaries": Array [
7,
9,
],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": " // this runs before the user's code is evaluated.",
"id": "final-key",
"name": "index",
"tail": "",
},
],
"description": "<section id=\\"description\\">
<p>When you add a lower rank heading element to the page, it's implied that you're starting a new subsection.</p>
<p>After the last <code>h2</code> element of the second <code>section</code> element, add an <code>h3</code> element with the text <code>Things cats love:</code>.</p>
<blockquote>
<p>Some text in a blockquote</p>
<p>
Some text in a blockquote, with <code>code</code>
</p>
</blockquote>
</section>",
"instructions": "<section id=\\"instructions\\">
<p>Do something with the <code>code</code>.</p>
<p>To test that adjacent tags are handled correctly:</p>
<p>a bit of <code>code</code> <tag>with more after a space</tag> and another pair of <strong>elements</strong> <em>with a space</em></p>
</section>",
"solutions": Array [
Array [
Object {
"contents": "<html>
<body>
<h1>CatPhotoApp</h1>
@ -327,22 +307,42 @@ a {
</body>
</html>",
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "html-key",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: white;
}
h1 {
font-size: 20px;
}
a {
color: green;
}",
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "final-key",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
],
"tests": Array [
Object {
@ -385,89 +385,89 @@ assert(
exports[`challenge parser should parse a simple md file 1`] = `
Object {
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
</code></pre>
</section>",
"files": Object {
"indexcss": Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
</code></pre>
</section>",
"instructions": "<section id=\\"instructions\\">
<p>Paragraph 0</p>
<pre><code class=\\"language-html\\">code example 0
</code></pre>
</section>",
"solutions": Array [
Object {
"indexcss": Object {
"contents": "body {
background: white;
}",
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "html-key",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: white;
}",
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';
\`\`",
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
],
"tests": Array [
Object {
@ -491,54 +491,54 @@ if(let x of xs) {
exports[`challenge parser should parse frontmatter 1`] = `
Object {
"challengeType": 0,
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
</code></pre>
</section>",
"files": Object {
"indexcss": Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
"challengeType": 0,
"description": "<section id=\\"description\\">
<p>Paragraph 1</p>
<pre><code class=\\"language-html\\">code example
</code></pre>
</section>",
"forumTopicId": 18276,
"id": "bd7123c8c441eddfaeb5bdef",
"isHidden": false,
"solutions": Array [
Object {},
Array [],
],
"tests": Array [
Object {
@ -557,6 +557,43 @@ Object {
exports[`challenge parser should parse gfm strikethrough and frontmatter 1`] = `
Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
],
"description": "<section id=\\"description\\">
<p>Paragraph 1 <del>Strikethrough text</del>. https://should.not.be.autolinked</p>
<pre><code class=\\"language-html\\">code example
@ -576,84 +613,47 @@ Object {
</tbody>
</table>
</section>",
"files": Object {
"indexcss": Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"head": "",
"id": "",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
"instructions": "<section id=\\"instructions\\">
<p>Paragraph 0</p>
<pre><code class=\\"language-html\\">code example 0
</code></pre>
</section>",
"solutions": Array [
Object {
"indexcss": Object {
"contents": "body {
background: white;
}",
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "html-key",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: white;
}",
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';
\`\`",
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
],
"tests": Array [
Object {

View File

@ -2,42 +2,42 @@
exports[`add-seed plugin should have an output to match the snapshot 1`] = `
Object {
"files": Object {
"indexcss": Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
"challengeFiles": Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"editableRegionBoundaries": Array [],
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: green;
}",
"editableRegionBoundaries": Array [],
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';",
"editableRegionBoundaries": Array [],
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
}
`;

View File

@ -3,41 +3,41 @@
exports[`add solution plugin should have an output to match the snapshot 1`] = `
Object {
"solutions": Array [
Object {
"indexcss": Object {
"contents": "body {
background: white;
}",
"ext": "css",
"head": "",
"id": "",
"key": "indexcss",
"name": "index",
"tail": "",
},
"indexhtml": Object {
Array [
Object {
"contents": "<html>
<body>
</body>
</html>",
"ext": "html",
"fileKey": "indexhtml",
"head": "",
"id": "html-key",
"key": "indexhtml",
"name": "index",
"tail": "",
},
"indexjs": Object {
Object {
"contents": "body {
background: white;
}",
"ext": "css",
"fileKey": "indexcss",
"head": "",
"id": "",
"name": "index",
"tail": "",
},
Object {
"contents": "var x = 'y';
\`\`",
"ext": "js",
"fileKey": "indexjs",
"head": "",
"id": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
],
}
`;

View File

@ -7,8 +7,8 @@ const { getFileVisitor } = require('./utils/get-file-visitor');
const editableRegionMarker = '--fcc-editable-region--';
function findRegionMarkers(file) {
const lines = file.contents.split('\n');
function findRegionMarkers(challengeFile) {
const lines = challengeFile.contents.split('\n');
const editableLines = lines
.map((line, id) => (line.trim() === editableRegionMarker ? id : -1))
.filter(id => id >= 0);
@ -55,26 +55,33 @@ function addSeeds() {
visitForContents(contentsTree);
visitForHead(headTree);
visitForTail(tailTree);
const seedVals = Object.values(seeds);
file.data = {
...file.data,
files: seeds
challengeFiles: seedVals
};
// process region markers - remove them from content and add them to data
Object.keys(seeds).forEach(key => {
const fileData = seeds[key];
const editRegionMarkers = findRegionMarkers(fileData);
const challengeFiles = Object.values(seeds).map(data => {
const seed = { ...data };
const editRegionMarkers = findRegionMarkers(seed);
if (editRegionMarkers) {
fileData.contents = removeLines(fileData.contents, editRegionMarkers);
seed.contents = removeLines(seed.contents, editRegionMarkers);
if (editRegionMarkers[1] <= editRegionMarkers[0]) {
throw Error('Editable region must be non zero');
}
fileData.editableRegionBoundaries = editRegionMarkers;
seed.editableRegionBoundaries = editRegionMarkers;
} else {
fileData.editableRegionBoundaries = [];
seed.editableRegionBoundaries = [];
}
return seed;
});
file.data = {
...file.data,
challengeFiles
};
}
return transformer;

View File

@ -1,4 +1,3 @@
const { isObject } = require('lodash');
const isArray = require('lodash/isArray');
const adjacentKeysAST = require('../__fixtures__/ast-adjacent-keys.json');
@ -32,26 +31,26 @@ describe('add-seed plugin', () => {
expect(typeof plugin).toEqual('function');
});
it('adds a `files` property to `file.data`', () => {
it('adds a `challengeFiles` property to `file.data`', () => {
plugin(simpleAST, file);
expect('files' in file.data).toBe(true);
expect('challengeFiles' in file.data).toBe(true);
});
it('ensures that the `files` property is an object', () => {
it('ensures that the `challengeFiles` property is an array', () => {
plugin(simpleAST, file);
expect(isObject(file.data.files)).toBe(true);
expect(isArray(file.data.challengeFiles)).toBe(true);
});
it('adds test objects to the files array following a schema', () => {
it('adds test objects to the challengeFiles array following a schema', () => {
expect.assertions(17);
plugin(simpleAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const testObject = files.indexjs;
const testObject = challengeFiles.find(x => x.fileKey === 'indexjs');
expect(Object.keys(testObject).length).toEqual(8);
expect(testObject).toHaveProperty('key');
expect(typeof testObject['key']).toBe('string');
expect(testObject).toHaveProperty('fileKey');
expect(typeof testObject['fileKey']).toBe('string');
expect(testObject).toHaveProperty('ext');
expect(typeof testObject['ext']).toBe('string');
expect(testObject).toHaveProperty('name');
@ -69,33 +68,32 @@ describe('add-seed plugin', () => {
});
it('parses seeds without ids', () => {
expect.assertions(6);
expect.assertions(3);
plugin(simpleAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexjs, indexhtml, indexcss } = files;
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexjs.contents).toBe(`var x = 'y';`);
expect(indexjs.key).toBe(`indexjs`);
expect(indexhtml.contents).toBe(`<html>
<body>
</body>
</html>`);
expect(indexhtml.key).toBe(`indexhtml`);
expect(indexcss.contents).toBe(`body {
background: green;
}`);
expect(indexcss.key).toBe(`indexcss`);
});
it('removes region markers from contents', () => {
expect.assertions(2);
plugin(withEditableAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexcss } = files;
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexcss.contents).not.toMatch('--fcc-editable-region--');
expect(indexcss.editableRegionBoundaries).toEqual([1, 4]);
@ -107,9 +105,11 @@ describe('add-seed plugin', () => {
expect.assertions(3);
plugin(withSeedKeysAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexhtml, indexcss, indexjs } = files;
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexhtml.id).toBe('');
expect(indexcss.id).toBe('key-for-css');
@ -138,9 +138,11 @@ describe('add-seed plugin', () => {
expect.assertions(3);
plugin(withBeforeAfterAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexjs, indexhtml, indexcss } = files;
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexjs.head).toBe('');
expect(indexhtml.head).toBe(`<!-- comment -->`);
@ -153,9 +155,11 @@ describe('add-seed plugin', () => {
expect.assertions(3);
plugin(withBeforeAfterAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexjs, indexhtml, indexcss } = files;
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexjs.tail).toBe(`function teardown(params) {
// after
@ -188,9 +192,11 @@ describe('add-seed plugin', () => {
expect.assertions(6);
plugin(emptyBeforeAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexjs, indexhtml, indexcss } = files;
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexjs.head).toBe('');
expect(indexjs.tail).toBe('function teardown(params) {\n // after\n}');
@ -204,9 +210,11 @@ describe('add-seed plugin', () => {
expect.assertions(6);
plugin(emptyAfterAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexjs, indexhtml, indexcss } = files;
const indexjs = challengeFiles.find(x => x.fileKey === 'indexjs');
const indexhtml = challengeFiles.find(x => x.fileKey === 'indexhtml');
const indexcss = challengeFiles.find(x => x.fileKey === 'indexcss');
expect(indexjs.head).toBe('');
expect(indexjs.tail).toBe('');
@ -234,9 +242,9 @@ describe('add-seed plugin', () => {
expect.assertions(4);
plugin(jsxSeedAST, file);
const {
data: { files }
data: { challengeFiles }
} = file;
const { indexjsx } = files;
const indexjsx = challengeFiles.find(x => x.fileKey === 'indexjsx');
expect(indexjsx.head).toBe(`function setup() {}`);
expect(indexjsx.tail).toBe(`function teardown(params) {
@ -248,7 +256,7 @@ describe('add-seed plugin', () => {
const Button = () => {
return <button> {/* another comment! */} text </button>;
};`);
expect(indexjsx.key).toBe(`indexjsx`);
expect(indexjsx.fileKey).toBe(`indexjsx`);
});
it('combines all the code of a specific language into a single file', () => {

View File

@ -30,7 +30,7 @@ function createPlugin() {
);
visitForContents(solutionTree);
solutions.push(solution);
solutions.push(Object.values(solution));
});
file.data = {

View File

@ -33,16 +33,18 @@ describe('add solution plugin', () => {
expect(file.data.solutions.every(el => isObject(el))).toBe(true);
});
it('adds solution objects to the files array following a schema', () => {
it('adds solution objects to the challengeFiles array following a schema', () => {
expect.assertions(15);
plugin(mockAST, file);
const {
data: { solutions }
} = file;
const testObject = solutions[0].indexjs;
const testObject = solutions[0].find(
solution => solution.fileKey === 'indexjs'
);
expect(Object.keys(testObject).length).toEqual(7);
expect(testObject).toHaveProperty('key');
expect(typeof testObject['key']).toBe('string');
expect(testObject).toHaveProperty('fileKey');
expect(typeof testObject['fileKey']).toBe('string');
expect(testObject).toHaveProperty('ext');
expect(typeof testObject['ext']).toBe('string');
expect(testObject).toHaveProperty('name');
@ -64,16 +66,24 @@ describe('add solution plugin', () => {
data: { solutions }
} = file;
expect(solutions.length).toBe(3);
expect(solutions[0].indexjs.contents).toBe("var x = 'y';");
expect(solutions[1].indexhtml.contents).toBe(`<html>
expect(
solutions[0].find(solution => solution.fileKey === 'indexjs').contents
).toBe("var x = 'y';");
expect(
solutions[1].find(solution => solution.fileKey === 'indexhtml').contents
).toBe(`<html>
<body>
solution number two
</body>
</html>`);
expect(solutions[1].indexcss.contents).toBe(`body {
expect(
solutions[1].find(solution => solution.fileKey === 'indexcss').contents
).toBe(`body {
background: white;
}`);
expect(solutions[2].indexjs.contents).toBe("var x = 'y3';");
expect(
solutions[2].find(solution => solution.fileKey === 'indexjs').contents
).toBe("var x = 'y3';");
});
it('should reject solutions with editable region markers', () => {

View File

@ -12,7 +12,7 @@ const supportedLanguages = ['js', 'css', 'html', 'jsx', 'py'];
function defaultFile(lang, id) {
return {
key: `index${lang}`,
fileKey: `index${lang}`,
ext: lang,
name: 'index',
contents: '',
@ -43,21 +43,21 @@ function codeToData(node, seeds, seedKey, validate) {
Please use one of js, css, html, jsx or py
`);
const key = `index${lang}`;
const id = seeds[key] ? seeds[key].id : '';
const fileKey = `index${lang}`;
const id = seeds[fileKey] ? seeds[fileKey].id : '';
// the contents will be missing if there is an id preceding this code
// block.
if (!seeds[key]) {
seeds[key] = defaultFile(lang, id);
if (!seeds[fileKey]) {
seeds[fileKey] = defaultFile(lang, id);
}
if (isEmpty(node.value) && seedKey !== 'contents') {
const section = keyToSection[seedKey];
throw Error(`Empty code block in --${section}-- section`);
}
seeds[key][seedKey] = isEmpty(seeds[key][seedKey])
seeds[fileKey][seedKey] = isEmpty(seeds[fileKey][seedKey])
? node.value
: seeds[key][seedKey] + '\n' + node.value;
: seeds[fileKey][seedKey] + '\n' + node.value;
}
function idToData(node, index, parent, seeds) {
@ -73,9 +73,9 @@ function idToData(node, index, parent, seeds) {
}
const codeNode = parent.children[index + 1];
if (codeNode && is(codeNode, 'code')) {
const key = `index${codeNode.lang}`;
if (seeds[key]) throw Error('::id{#id}s must come before code blocks');
seeds[key] = defaultFile(codeNode.lang, id);
const fileKey = `index${codeNode.lang}`;
if (seeds[fileKey]) throw Error('::id{#id}s must come before code blocks');
seeds[fileKey] = defaultFile(codeNode.lang, id);
} else {
throw Error('::id{#id}s must come before code blocks');
}