-
yarn test ./src/Components/__test__/JobDetail.test.js
for JobDetail component
-
yarn test ./src/Components/__test__/JobListItem.test.js
for JobListItem component
-
API url:
https://jobs.github.com/positions.json?description=javascript
-
new url:
https://us-central1-wands-2017.cloudfunctions.net/githubjobs
-
Data structure for one job
{
"id": "dcf7cacf-ac39-4e6e-a5df-83135f69cff0",
"type": "Full Time",
"url": "https://jobs.github.com/positions/dcf7cacf-ac39-4e6e-a5df-83135f69cff0",
"created_at": "Wed Jan 20 14:03:36 UTC 2021",
"company": "whynow",
"company_url": "https://whynow.co.uk/",
"location": "London",
"title": "Full Stack Developer / WooCommerce Wizard",
"description": "<p>whynow is a new arts and culture digital platform promoting personal, powerful and positive stories in the capital and beyond.</p>\n<p>As a subscription platform, members of whynow get access to a growing range of videos, articles, ...",
"how_to_apply": "<p>Please email your CV and a cover letter to me at <a href=\"mailto:connor@whynow.co.uk\">connor@whynow.co.uk</a></p>\n",
"company_logo": "https://jobs.github.com/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZ1NXIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--65a93ab1c962ad69d2724d5791201cb0f2377646/whynow-login-logo.png"
},
-
First Page
-
1 input + 1 button:
description
|Button
Placeholder:
Use SPACE as plus for multiple searching keywords
-
for input data search pattern:
- use SPACEBAR as
+
:
- use SPACEBAR as
-
Searching results:
-
If result is empty -> expect this:
No jobs found
should be shown as a result -
If result is NOT empty -> Wrap url of each results in
Link
, route to detail page, render out JobItem component
-
-
-
Detail Page(JobItem)
-
For Tests: (at least 10 tests)
type
value: wrapped instrong-element
title
value: wrapped in ah2
company_url
value: wrapped ina
description
value: wrapped inp
->section
⬅️ Use sementic element insteadcompany_logo
value: assrc
for aimg
element
-
TIPS:
Use
dangerouslySetInnerHTML
for description
-
Save results(if there is any) in context to avoid multiple fetching data.
-
Deploy to
GitHub/Netlify/Firebase/Vercel...
-
react-router-dom
-
axios
-
styled-components
-
enzyme
-
@wojtekmaj/enzyme-adapter-react-17
-
react-loadingg
import { BoxLoading } from 'react-loadingg'; // or import BoxLoading from 'react-loadingg/lib/BoxLoading <BoxLoading />;
- Implement nested router
Url will change correspondingly, following this pattern
<Switch> <Route path="/" exact component={FrontPage} /> <Route path="/jobs/:jobtitle" render={({ match: { path } }) => ( <div> <Route exact path={path} component={JobsPage} /> <Route path={`${path}/:id`} component={JobDetailPage} /> </div> )} /> <Route path="/nojobfound" component={NoJobFound} /> <Route path="*" component={Page404} /> </Switch>
/jobs/typescript+react/35842a28-ff88-47ba-99e5-f9960ae901a4
. We can tell exactly queryField and queryId from this path, then we can take that piece of data out of localStorage easily.
-
Use more generic function
Use
fetchData('queryField', 'queryContent')
,createContent(contentField)
instead ofgetJobs(description)
, to increase reusability. -
Pre-process input data In case the user accidentally inputs extra unnecessary space, this function is implemented:
Now added sort to generated array to avoid multiple fetching same piece of data from API.
js export const generateKeywords = (val) => { const regex = /\s+/; return val.trim().split(regex).sort().join("+"); };
- About test
-
Created 3 files, they are 2 files inside of
./src/Components/__test__
andApp.test.js
-
App.test.js
is used to check if app is correctly rendered (only 1 test) -
JobDetail.test.js
is for testing JobDetail component, which includes 10 tests. -
JobListItem.test.js
is for testing JobListItem component, which includes 3 testsExample:
it("should contain text 'Origin Link' with correct url for this job", () => { // find correct node by expected content; // then check if it has the correct href; // the result has two children, we need the first one - a-tag expect( JobWrapper.findWhere((n) => n.text() === "Original Link") .at(0) .prop("href") ).toEqual(JOB_OBJECT.url); });
Here we find that node with content 'Origin Link', then check if it contains a prop
href
is equal to the passed value.it(`'company_url' should be wrapped in an a-tag`, () => { expect(JobWrapper.find(".company-url").closest("a")).toHaveLength(1); });
.company-url
is used as test class (maybe should be changed to some more explicit testId), then we useclosest()
to check if this node with this.company-url
class is wrapped within an a-element. If so, we will get back length === 1.
For js, just change ts/tsx to js/jsx, awesome code for formatting and checking eslint errors.
npx prettier --write src/**/*.{ts,tsx}
npx eslint --fix src/**/*.{ts,tsx}
`firebase`
`npm run build`
`firebase deploy`
- `npm run build`
- `netlify deploy --prod` -> `./build` or `build`