mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-08-31 01:14:08 +08:00
fix(curriculum): grammar and test fixes in fcc-authors-page workshop (#69589)
Co-authored-by: sembauke <sembauke@users.noreply.github.com>
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ All of the HTML and CSS for this workshop has been provided for you. You can tak
|
||||
|
||||
When you are ready, start by accessing the `#author-container` and `#load-more-btn` elements. Remember you can use the `getElementById` or `querySelector` methods for this.
|
||||
|
||||
Then assign these elements to variables called `authorContainer` and `loadMoreBtn`, respectively.
|
||||
Then assign these elements to variables called `authorContainer` and `loadMoreBtn`, respectively.
|
||||
|
||||
# --hints--
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ assert.match(code, /fetch\(\s*('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculu
|
||||
Your second `.then()` should not have semicolon after it.
|
||||
|
||||
```js
|
||||
assert.notMatch(code, /fetch\(\s*('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\s*\)\s*\.then\(\s(\(\s*res\s*\)|res)\s*=>\s*res\.json\(\s*\)\s*\)\s*\.then\(\s*(\(\s*data\s*\)|data)\s*=>\s*\{\s*\n?\s*?console\.log\(\s*data\s*\)\s*;?\s*\}\s*\)\s*;/)
|
||||
assert.notMatch(code, /fetch\(\s*('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\s*\)\s*\.then\(\s*(\(\s*res\s*\)|res)\s*=>\s*res\.json\(\s*\)\s*\)\s*\.then\(\s*(\(\s*data\s*\)|data)\s*=>\s*\{\s*\n?\s*?console\.log\(\s*data\s*\)\s*;?\s*\}\s*\)\s*;/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
+2
-2
@@ -75,7 +75,7 @@ You should add an `err` parameter to your `.catch()` method.
|
||||
assert.match(code, /fetch\(\s*('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\s*\)\s*\.then\(\s*(\(\s*res\s*\)|res)\s*=>\s*res\.json\(\s*\)\s*\)\s*\.then\(\s*(\(\s*data\s*\)|data)\s*=>\s*\{\s*\n?\s*?console\.log\(\s*data\s*\)\s*;?\n?\s*\}\s*\)\n?\s*\.catch\(\s*(\(\s*err\s*\)|err)/)
|
||||
```
|
||||
|
||||
Your `.catch()` method should have an arrow function syntax.
|
||||
Your `.catch()` method should use arrow function syntax.
|
||||
|
||||
```js
|
||||
assert.match(code, /fetch\(\s*('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\s*\)\s*\.then\(\s*(\(\s*res\s*\)|res)\s*=>\s*res\.json\(\s*\)\s*\)\s*\.then\(\s*(\(\s*data\s*\)|data)\s*=>\s*\{\s*\n?\s*?console\.log\(\s*data\s*\)\s*;?\n?\s*\}\s*\)\n?\s*\.catch\(\s*(\(\s*err\s*\)|err)\s*=>\s*\{?/)
|
||||
@@ -197,7 +197,7 @@ fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
});
|
||||
})
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
+6
-2
@@ -28,7 +28,9 @@ window.fetch = () => Promise.resolve({json: () => Promise.resolve([{ author: 'Wh
|
||||
You should use `let` to declare a variable named `startingIndex`.
|
||||
|
||||
```js
|
||||
assert.match(code, /let\s+startingIndex/);
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { startingIndex } = explorer.variables;
|
||||
assert.isTrue(startingIndex?.toString().startsWith('let'));
|
||||
```
|
||||
|
||||
Your `startingIndex` variable should be a number.
|
||||
@@ -46,7 +48,9 @@ assert.strictEqual(startingIndex, 0);
|
||||
You should use `let` to declare a variable named `endingIndex`.
|
||||
|
||||
```js
|
||||
assert.match(code, /let\s+endingIndex/);
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { endingIndex } = explorer.variables;
|
||||
assert.isTrue(endingIndex?.toString().startsWith('let'));
|
||||
```
|
||||
|
||||
Your `endingIndex` variable should be a number.
|
||||
|
||||
+7
-5
@@ -32,7 +32,7 @@ window.fetch = () => Promise.resolve({json: () => Promise.resolve([{ author: 'Wh
|
||||
|
||||
# --hints--
|
||||
|
||||
`displayAuthors` should be a function.
|
||||
Your `displayAuthors` variable should be a function.
|
||||
|
||||
```js
|
||||
assert.isFunction(displayAuthors)
|
||||
@@ -41,13 +41,15 @@ assert.isFunction(displayAuthors)
|
||||
Your `displayAuthors` function should take an `authors` parameter.
|
||||
|
||||
```js
|
||||
assert.match(
|
||||
code,
|
||||
/(?:function\s+displayAuthors\s*\(\s*authors\s*\)|(?:const|let|var)\s+displayAuthors\s*=\s*(?:async\s*)?(?:\(\s*authors\s*\)|authors)\s*=>)/
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { displayAuthors } = explorer.allFunctions;
|
||||
assert.deepEqual(
|
||||
displayAuthors?.parameters.map((p) => p.toString()),
|
||||
['authors']
|
||||
);
|
||||
```
|
||||
|
||||
When the `displayAuthors` function is called with an author's array, it should add a card for each author to the `#authorContainer` element.
|
||||
Your `displayAuthors` function should add a card for each author to the `authorContainer` element.
|
||||
|
||||
```js
|
||||
const exampleAuthors = [
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ dashedName: step-10
|
||||
|
||||
Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
|
||||
|
||||
Inside your `console.log()` statement, add the text `"Author Data Array:"` as the first argument and `authorDataArr` as the second argument. Use comma to separate the text from `authorDataArr`.
|
||||
Inside your `console.log()` statement, add the text `"Author Data Array:"` as the first argument and `authorDataArr` as the second argument. Use a comma to separate the text from `authorDataArr`.
|
||||
|
||||
# --before-all--
|
||||
|
||||
@@ -31,13 +31,13 @@ You should have a console log with the text `"Author Data Array:"`.
|
||||
assert.match(code, /console\.log\(\s*("|'|`)Author\s+Data\s+Array:\s*\1/)
|
||||
```
|
||||
|
||||
You should use comma to separate your `"Author Data Array:"` text and `authorDataArr`.
|
||||
You should use a comma to separate your `"Author Data Array:"` text and `authorDataArr`.
|
||||
|
||||
```js
|
||||
assert.match(code, /console\.log\(\s*("|'|`)Author\s+Data\s+Array:\s*\1\s*,/)
|
||||
```
|
||||
|
||||
`authorDataArr` should be the second argument of your console log statement.
|
||||
Your `authorDataArr` should be the second argument of the `console.log()` statement.
|
||||
|
||||
```js
|
||||
assert.match(code, /console\.log\(\s*("|'|`)Author\s+Data\s+Array:\s*\1\s*,\s*authorDataArr\s*\)\s*;?/)
|
||||
|
||||
+2
-2
@@ -43,13 +43,13 @@ You should call your `displayAuthors` function and pass in an argument of `autho
|
||||
assert.match(code, /displayAuthors\(\s*authorDataArr\.slice\(/)
|
||||
```
|
||||
|
||||
The first parameter of your `slice()` method should be `startingIndex`.
|
||||
Your first `slice()` argument should be `startingIndex`.
|
||||
|
||||
```js
|
||||
assert.match(code, /displayAuthors\(\s*authorDataArr\.slice\(\s*startingIndex/)
|
||||
```
|
||||
|
||||
The second parameter of your `slice()` method should be `endingIndex`.
|
||||
Your second `slice()` argument should be `endingIndex`.
|
||||
|
||||
```js
|
||||
assert.match(code, /displayAuthors\(\s*authorDataArr\.slice\(\s*startingIndex\s*,\s*endingIndex\s*\)\s*\)\s*;?/)
|
||||
|
||||
+20
-13
@@ -9,7 +9,7 @@ dashedName: step-15
|
||||
|
||||
Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
|
||||
|
||||
Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
|
||||
Use `const` to create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
|
||||
|
||||
# --before-all--
|
||||
|
||||
@@ -22,31 +22,38 @@ window.fetch = () => Promise.resolve({json: () => Promise.resolve([{ author: 'Wh
|
||||
You should use `const` to create a `fetchMoreAuthors` function.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+fetchMoreAuthors\s*=\s*/)
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { fetchMoreAuthors } = explorer.allFunctions;
|
||||
assert.isTrue(fetchMoreAuthors?.toString().startsWith('const'));
|
||||
```
|
||||
|
||||
`fetchMoreAuthors` should be a function.
|
||||
Your `fetchMoreAuthors` variable should be a function.
|
||||
|
||||
```js
|
||||
assert.isFunction(fetchMoreAuthors)
|
||||
```
|
||||
|
||||
Your `fetchMoreAuthors` function should not take any parameter.
|
||||
Your `fetchMoreAuthors` function should not take any parameters.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { fetchMoreAuthors } = explorer.allFunctions;
|
||||
assert.deepEqual(fetchMoreAuthors?.parameters.map((p) => p.toString()), []);
|
||||
```
|
||||
|
||||
Your `fetchMoreAuthors` function should use arrow syntax.
|
||||
Your `fetchMoreAuthors` function should use arrow function syntax and have an empty body.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+fetchMoreAuthors\s*=\s*\(\s*\)\s*=>\s*/)
|
||||
```
|
||||
|
||||
Your `fetchMoreAuthors` function should be empty.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+fetchMoreAuthors\s*=\s*\(\s*\)\s*=>\s*\{\s*\}/)
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { fetchMoreAuthors } = explorer.allFunctions;
|
||||
const validExpressions = [
|
||||
'const fetchMoreAuthors = () => {}',
|
||||
'let fetchMoreAuthors = () => {}',
|
||||
'var fetchMoreAuthors = () => {}'
|
||||
];
|
||||
assert.isTrue(
|
||||
validExpressions.some((expression) => fetchMoreAuthors?.matches(expression))
|
||||
);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ dashedName: step-16
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `fetchMoreAuthors` function, set the `startingIndex` and `endingIndex` variables to `+= 8` each.
|
||||
Inside the `fetchMoreAuthors` function, set the `startingIndex` and `endingIndex` variables to `+=8` each.
|
||||
|
||||
# --before-all--
|
||||
|
||||
|
||||
+2
-2
@@ -33,14 +33,14 @@ const afterAdd = code.split("endingIndex += 8;")[1];
|
||||
assert.match(afterAdd, /displayAuthors\(\s*authorDataArr\.slice\(/)
|
||||
```
|
||||
|
||||
The first argument of your `slice()` method should be `startingIndex`.
|
||||
Your first `slice()` argument should be `startingIndex`.
|
||||
|
||||
```js
|
||||
const afterAdd = code.split("endingIndex += 8;")[1];
|
||||
assert.match(afterAdd, /displayAuthors\(\s*authorDataArr\.slice\(\s*startingIndex/)
|
||||
```
|
||||
|
||||
The second argument of your `slice()` method should be `endingIndex`.
|
||||
Your second `slice()` argument should be `endingIndex`.
|
||||
|
||||
```js
|
||||
const afterAdd = code.split("endingIndex += 8;")[1];
|
||||
|
||||
+2
-2
@@ -37,13 +37,13 @@ You should check if the length of the `bio` text is greater than `50`.
|
||||
assert.match(code, /<p\s*class=("|')bio\1>\s*\$\{\s*bio\.length\s*>\s*50/)
|
||||
```
|
||||
|
||||
If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `"..."`. Don't forget that indexes are zero-based.
|
||||
You should extract the first 50 characters with `slice()` and replace the rest with `"..."` if `bio` is greater than `50` characters. Don't forget that indexes are zero-based.
|
||||
|
||||
```js
|
||||
assert.match(code, /<p\s*class\s*=\s*("|')bio\1\s*>\s*\$\{\s*bio\.length\s*>\s*50\s*\?\s*(?:bio\.slice\(\s*0\s*,\s*50\s*\)\s*\+\s*("|')\.\.\.\2|`\$\{\s*bio\.slice\(\s*0\s*,\s*50\s*\)\s*\}\.\.\.`)\s*:/);
|
||||
```
|
||||
|
||||
If the `bio` text is less than 50 characters, use the `bio` text directly.
|
||||
You should use the `bio` text directly if it is 50 characters or less.
|
||||
|
||||
```js
|
||||
assert.match(code, /<p\s*class\s*=\s*("|')bio\1\s*>\s*\$\{\s*bio\.length\s*>\s*50\s*\?\s*(?:bio\.slice\(\s*0\s*,\s*50\s*\)\s*\+\s*("|')\.\.\.\2|`\$\{\s*bio\.slice\(\s*0\s*,\s*50\s*\)\s*\}\.\.\.`)\s*:\s*bio\s*\}\s*<\/p>/);
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ window.fetch = () => Promise.resolve({json: () => Promise.resolve([{ author: 'Wh
|
||||
|
||||
# --hints--
|
||||
|
||||
You should access the `style` property of `loadMoreBtn` with a dot notation.
|
||||
You should access the `style` property of `loadMoreBtn` with dot notation.
|
||||
|
||||
```js
|
||||
assert.match(code, /loadMoreBtn\.style/)
|
||||
|
||||
+14
-9
@@ -11,7 +11,7 @@ Now that your fCC Authors Page is fully functional, let's refactor it to improve
|
||||
|
||||
Recall that in order to use the `await` operator to wait for a function that returns a `Promise`, you need to wrap the function call in an `async` function (if it is not in the main body of a module).
|
||||
|
||||
Since your `fetch` call is not defined in either an asynchronous function nor in the main body of a module, you cannot use `await` before fixing that.
|
||||
Since your `fetch` call is not defined in either an asynchronous function or the main body of a module, you cannot use `await` before fixing that.
|
||||
|
||||
Wrap the `fetch` statement and the entire sequence of chained then and catch methods as a whole in a new asynchronous arrow function called `initialFetch` which takes no arguments.
|
||||
|
||||
@@ -29,7 +29,7 @@ window.fetch = () => Promise.resolve({json: () => Promise.resolve([{ author: 'Wh
|
||||
|
||||
# --hints--
|
||||
|
||||
`initialFetch` should be a function.
|
||||
Your `initialFetch` variable should be a function.
|
||||
|
||||
```js
|
||||
assert.isFunction(initialFetch)
|
||||
@@ -38,23 +38,28 @@ assert.isFunction(initialFetch)
|
||||
You should use `const` to create an `initialFetch` function.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+initialFetch\s*=\s*/)
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { initialFetch } = explorer.allFunctions;
|
||||
assert.isTrue(initialFetch?.toString().startsWith('const'));
|
||||
```
|
||||
|
||||
`initialFetch` should be an async function.
|
||||
Your `initialFetch` variable should be an async function.
|
||||
|
||||
```js
|
||||
assert.isFunction(initialFetch)
|
||||
assert.match(code, /const\s+initialFetch\s*=\s*async\s*/)
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { initialFetch } = explorer.allFunctions;
|
||||
assert.include(initialFetch?.toString() ?? '', 'async');
|
||||
```
|
||||
|
||||
Your `initialFetch` function should not take any parameter.
|
||||
Your `initialFetch` function should not take any parameters.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+initialFetch\s*=\s*.*\s*\(\s*\)\s*/)
|
||||
const explorer = await __helpers.Explorer(code);
|
||||
const { initialFetch } = explorer.allFunctions;
|
||||
assert.deepEqual(initialFetch?.parameters.map((p) => p.toString()), []);
|
||||
```
|
||||
|
||||
Your `initialFetch` function should use arrow syntax.
|
||||
Your `initialFetch` function should use arrow function syntax.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+initialFetch\s*=\s*.*\s*\(.*\)\s*=>\s*/)
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ You should assign the awaited result of `res.json()` to the `authorDataArr` vari
|
||||
assert.match(code, /^\s*authorDataArr\s*=\s*await\s+res\.json\(\s*\)\s*;?/m)
|
||||
```
|
||||
|
||||
`displayAuthors` should still be called as before
|
||||
Your `displayAuthors` call should remain unchanged.
|
||||
|
||||
```js
|
||||
assert.match(code, /^\s*displayAuthors\(\s*authorDataArr\.slice\(\s*startingIndex\s*,\s*endingIndex\s*\)\s*\)\s*;?/m)
|
||||
@@ -174,7 +174,7 @@ const initialFetch = async () => {
|
||||
.catch((err) => {
|
||||
authorContainer.innerHTML = '<p class="error-msg">There was an error loading the authors</p>';
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const fetchMoreAuthors = () => {
|
||||
startingIndex += 8;
|
||||
|
||||
+5
-5
@@ -36,13 +36,13 @@ You should create a `try/catch` block
|
||||
assert.match(code, /try\s*\{[\s\S]*?\}\s*catch\s*\([^)]*\)\s*\{/);
|
||||
```
|
||||
|
||||
The `catch` should no longer be a chained method
|
||||
Your `catch` should no longer be a chained method.
|
||||
|
||||
```js
|
||||
assert.notMatch(code, /\.catch/);
|
||||
```
|
||||
|
||||
The `try` block should contain the three statements that fetch the data, create the `json` and then display it.
|
||||
Your `try` block should contain the three statements that fetch the data, create the `json`, and then display it.
|
||||
|
||||
```js
|
||||
const tryBlockRegex =
|
||||
@@ -68,7 +68,7 @@ assert.isTrue(jsonLineRegex.test(tryBlockContents));
|
||||
assert.isTrue(displayLineRegex.test(tryBlockContents));
|
||||
```
|
||||
|
||||
The fCC Authors Page should be rendering correctly
|
||||
Your fCC Authors Page should render correctly.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('.author-name').innerText, `Whoever`);
|
||||
@@ -195,7 +195,7 @@ const initialFetch = async () => {
|
||||
authorContainer.innerHTML = '<p class="error-msg">There was an error loading the authors</p>';
|
||||
});
|
||||
--fcc-editable-region--
|
||||
}
|
||||
};
|
||||
|
||||
const fetchMoreAuthors = () => {
|
||||
startingIndex += 8;
|
||||
@@ -344,7 +344,7 @@ const initialFetch = async () => {
|
||||
} catch (err) {
|
||||
authorContainer.innerHTML = '<p class="error-msg">There was an error loading the authors</p>';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const fetchMoreAuthors = () => {
|
||||
startingIndex += 8;
|
||||
|
||||
Reference in New Issue
Block a user