From 8fd00afd9c1adbfe981d338d7d59ce4fb2962831 Mon Sep 17 00:00:00 2001 From: Rex Schrader Date: Fri, 6 Nov 2020 18:23:11 -0800 Subject: [PATCH] feat(learn): Add tests for refactored American/British Translator (#39822) * feat(learn): Add tests for refactored American/British Translator * Move to Markdown formatting Co-authored-by: Shaun Hamilton <51722130+Sky020@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Tom <20648924+moT01@users.noreply.github.com> * Update curriculum/challenges/english/06-quality-assurance/quality-assurance-projects/american-british-translator.md Co-authored-by: Tom <20648924+moT01@users.noreply.github.com> * Update american-british-translator.md With contributions from @mot01 * Apply suggestions from code review Co-authored-by: Randell Dawson <5313213+RandellDawson@users.noreply.github.com> Co-authored-by: Shaun Hamilton <51722130+Sky020@users.noreply.github.com> Co-authored-by: Tom <20648924+moT01@users.noreply.github.com> Co-authored-by: Randell Dawson <5313213+RandellDawson@users.noreply.github.com> --- .../american-british-translator.md | 256 ++++++++++++++++-- 1 file changed, 231 insertions(+), 25 deletions(-) diff --git a/curriculum/challenges/english/06-quality-assurance/quality-assurance-projects/american-british-translator.md b/curriculum/challenges/english/06-quality-assurance/quality-assurance-projects/american-british-translator.md index 6c697f9a9e..c3e78dd663 100644 --- a/curriculum/challenges/english/06-quality-assurance/quality-assurance-projects/american-british-translator.md +++ b/curriculum/challenges/english/06-quality-assurance/quality-assurance-projects/american-british-translator.md @@ -6,16 +6,25 @@ challengeType: 4 ## Description
-Build a full stack JavaScript app that is functionally similar to this: https://american-british-translator.freecodecamp.rocks/. +Build a full stack JavaScript app that is functionally similar to this: https://american-british-translator.freecodecamp.rocks/. Working on this project will involve you writing your code using one of the following methods: -Working on this project will involve you writing your code on Repl.it on our starter project. After completing this project you can copy your public Repl.it URL (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing. +- Clone this GitHub repo and complete your project locally. +- Use our repl.it starter project to complete your project. +- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo. -Start this project on Repl.it using this link or clone this repository on GitHub! If you use Repl.it, remember to save the link to your project somewhere safe! +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
## Instructions
+- All logic can go into `/components/translator.js` +- Complete the `/api/translate` route in `/routes/api.js` +- Create all of the unit/functional tests in `tests/1_unit-tests.js` and `tests/2_functional-tests.js` +- See the JavaScript files in `/components` for the different spelling and terms your application should translate +- To run the tests on Repl.it, set `NODE_ENV` to `test` without quotes in the `.env` file +- To run the tests in the console, use the command `npm run test`. To open the Repl.it console, press Ctrl+Shift+P (Cmd if on a Mac) and type "open shell" +
## Tests @@ -28,28 +37,225 @@ tests: getUserInput => { assert(!/.*\/american-british-translator\.freecodecamp\.rocks/.test(getUserInput('url'))); } - - text: I can enter a simple sentence into the text area and select whether to translate to British or American English from the dropdown menu. - testString: '' - - text: When the "Translate" button is pressed, append the translated sentence to the translated-sentence div. See the JavaScript files in /public for the different spelling and terms your application should translate. - testString: '' - - text: | - Your application should handle the way time is written in American and British English. For example, ten thirty is written as "10.30" in British English and "10:30" in American English. - testString: '' - - text: Your application should also handle the way titles/honorifics are abbreviated in American and British English. For example, Doctor Wright is abbreviated as "Dr Wright" in British English and "Dr. Wright" in American English. See /public/american-to-british-titles.js for the different titles your application should handle. - testString: '' - - text: Wrap any translated spelling or terms with <span class="highlight">...</span> tags so they appear in green. - testString: '' - - text: If the sentence in the text area has no spelling or terms that should be translated, append the message "Everything looks good to me!" to the translated-sentence div. - testString: '' - - text: | - If there is no text in the text area, append the message "Error: No text to translate." to the error-msg div so the text appears in red. - testString: '' - - text: I can press the "Clear Input" button to remove all text from the text area and the translated-sentence div. - testString: '' - - text: All 20 unit tests are complete and passing. See /tests/1_unit-tests.js for the sentences you should write tests for. - testString: '' - - text: All 4 functional tests are complete and passing. See /tests/2_functional-tests.js for the functionality you should write tests for. - testString: '' + + - text: You can POST to /api/translate with a body containing text with the text to translate and locale with either american-to-british or british-to-american. The returned object should contain the submitted text and translation with the translated text. + testString: "async getUserInput => { + try { + const text = 'Mangoes are my favorite fruit.'; + const locale = 'american-to-british'; + const output = { + text: 'Mangoes are my favorite fruit.', + translation: 'Mangoes are my favourite fruit.' + }; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text, locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'text'); + assert.property(parsed, 'translation'); + assert.deepEqual(parsed, output); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: The /api/translate route should handle the way time is written in American and British English. For example, ten thirty is written as "10.30" in British English and "10:30" in American English. + testString: "async getUserInput => { + try { + const text = 'Lunch is at 12:15 today.'; + const locale = 'american-to-british'; + const output = { + text: text, + translation: 'Lunch is at 12.15 today.' + }; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text, locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'text'); + assert.property(parsed, 'translation'); + assert.deepEqual(parsed, output); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: The /api/translate route should also handle the way titles/honorifics are abbreviated in American and British English. For example, Doctor Wright is abbreviated as "Dr Wright" in British English and "Dr. Wright" in American English. See /public/american-to-british-titles.js for the different titles your application should handle. + testString: "async getUserInput => { + try { + const text = 'Dr. Grosh will see you now.'; + const locale = 'american-to-british'; + const output = { + text: text, + translation: 'Dr Grosh will see you now.' + }; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text, locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'text'); + assert.property(parsed, 'translation'); + assert.deepEqual(parsed, output); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: Wrap any translated spelling or terms with <span class="highlight">...</span> tags so they appear in green. + testString: "async getUserInput => { + try { + const text = 'Mangoes are my favorite fruit.'; + const locale = 'american-to-british'; + const output = { + text: 'Mangoes are my favorite fruit.', + translation: 'Mangoes are my favourite fruit.' + }; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text, locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'text'); + assert.property(parsed, 'translation'); + assert.deepEqual(parsed, output); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: If one or more of the required fields is missing, return { error: 'Required field(s) missing' }. + testString: "async getUserInput => { + try { + const locale = 'american-to-british'; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'error'); + assert.equal(parsed.error, 'Required field(s) missing'); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: If text is empty, return { error: 'No text to translate' } + testString: "async getUserInput => { + try { + const locale = 'american-to-british'; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text: '', locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'error'); + assert.equal(parsed.error, 'No text to translate'); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: If locale does not match one of the two specified locales, return { error: 'Invalid value for locale field' }. + testString: "async getUserInput => { + try { + const text = 'Ceci n\\'est pas une pipe'; + const locale = 'french-to-american'; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text, locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.property(parsed, 'error'); + assert.equal(parsed.error, 'Invalid value for locale field'); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: If text requires no translation, return "Everything looks good to me!" for the translation value. + testString: "async getUserInput => { + try { + const locale = 'british-to-american'; + const output = { + text: 'SaintPeter and nhcarrigan give their regards!', + translation: 'Everything looks good to me!' + }; + let data = await fetch(getUserInput('url') + '/api/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ text: output.text, locale}) + }); + let parsed = await data.json(); + assert.isObject(parsed); + assert.isObject(parsed); + assert.property(parsed, 'text'); + assert.property(parsed, 'translation'); + assert.deepEqual(parsed, output); + } catch (err) { + throw new Error(err.responseText || err.message); + } + }" + - text: All 24 unit tests are complete and passing. See `/tests/1_unit-tests.js` for the expected behavior you should write tests for. + testString: "async getUserInput => { + try { + const getTests = await $.get(getUserInput('url') + '/_api/get-tests' ); + assert.isArray(getTests); + const unitTests = getTests.filter((test) => { + return !!test.context.match(/Unit Tests ->/ig); + }); + assert.isAtLeast(unitTests.length, 24, 'At least 24 tests passed'); + unitTests.forEach(test => { + assert.equal(test.state, 'passed', 'Tests in Passed State'); + assert.isAtLeast(test.assertions.length, 1, 'At least one assertion per test'); + }); + } catch(err) { + throw new Error(err.responseText || err.message); + } + }" + - text: All 6 functional tests are complete and passing. See `/tests/2_functional-tests.js` for the functionality you should write tests for. + testString: "async getUserInput => { + try { + const getTests = await $.get(getUserInput('url') + '/_api/get-tests' ); + assert.isArray(getTests); + const functTests = getTests.filter((test) => { + return !!test.context.match(/Functional Tests ->/ig); + }); + assert.isAtLeast(functTests.length, 6, 'At least 6 tests passed'); + functTests.forEach(test => { + assert.equal(test.state, 'passed', 'Tests in Passed State'); + assert.isAtLeast(test.assertions.length, 1, 'At least one assertion per test'); + }); + } catch(err) { + throw new Error(err.responseText || err.message); + } + }" + ```