Skip to content

Commit

Permalink
add a few tests, update README
Browse files Browse the repository at this point in the history
  • Loading branch information
max-berman committed Jun 1, 2021
1 parent a6fa000 commit fe9e663
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 39 deletions.
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,37 @@
# Solution to Vinted FE Code Challenge

[Assignment Instructions](https://gist.github.com/vintedEngineering/c838e906ecc25a52fe91c4a8a11e2916)
### Requirements

- [x] Leverage [Flickr API](https://www.flickr.com/services/api/flickr.photos.getRecent.html)
- [x] Design should be recreated as closely as possible.
- [x] Responsive design with three breakpoints for Desktop, Tablet, Phone.
- [x] Infinite scroll.
- [x] Keep liked photo data persistent with page reload.
- [x] Use React
- [x] No External libraries beside React

[Full Assignment Instructions](https://gist.github.com/vintedEngineering/c838e906ecc25a52fe91c4a8a11e2916)

[Demo](https://maxie-max.github.io/vinted-fe-code-challenge/)

### 🛠 To install dependencies run

```
npm install
```

### 🏗 To run app in the development mode

```
npm start
```

### 👩‍🔬 Testing

Test suite is setup with [Jest](https://jestjs.io) and [react-testing-library](https://github.com/kentcdodds/react-testing-library).

To run all tests:

```bash
npm test
```
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@
"devDependencies": {
"gh-pages": "^3.2.0"
}
}
}
8 changes: 0 additions & 8 deletions src/App.test.js

This file was deleted.

15 changes: 12 additions & 3 deletions src/components/ErrorMessage.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import React from 'react'
import style from './ErrorMessage.module.css'

function ErrorMessage({ errorMessage, type = 'error' }) {
// errorMessage consists of 4 types: error | warning | info | success
const Styles = {
error: 'error',
warning: 'warning',
info: 'info',
success: 'success',
}

function ErrorMessage({ errorMessage, type }) {
const getStyleClass = (type) => Styles[type] || Styles.error //defaulted to 'error'
return (
!!errorMessage && (
<div className={`${style.alert} ${style[type]}`}>{errorMessage}</div>
<div className={`${style.alert} ${style[getStyleClass(type)]}`}>
{errorMessage}
</div>
)
)
}
Expand Down
9 changes: 6 additions & 3 deletions src/components/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ function List() {

return (
<>
<ErrorMessage {...{ errorMessage, type: 'error' }} />
{!!photosData && (
<ul className={style.list}>
<ErrorMessage
data-testid='fetch-error'
{...{ errorMessage, type: 'error' }}
/>
{photosData.length > 0 && (
<ul className={style.list} data-testid='fetch-list'>
{photosData.map((data, i) => (
<Card
key={`${i}-${data?.id}`}
Expand Down
8 changes: 7 additions & 1 deletion src/components/Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import React from 'react'
import style from './Loader.module.css'

function Loader({ loadingText, isFetching }) {
return !isFetching && <div className={style.loader}>{loadingText}</div>
return (
!isFetching && (
<div data-testid='loader' className={style.loader}>
{loadingText}
</div>
)
)
}

export default Loader
26 changes: 26 additions & 0 deletions src/components/__test__/Button.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react'
import { render, fireEvent, cleanup } from '@testing-library/react'
import Button from '../Button'

const defaultProps = {
label: 'Like',
handleLike: jest.fn(),
}

test('button renders with correct label', () => {
const { queryByText, rerender } = render(<Button {...defaultProps} />)
expect(queryByText('Like')).toBeTruthy()

// Change props
rerender(<Button {...defaultProps} label='Dislike' />)
expect(queryByText('Dislike')).toBeTruthy()
})

test('calls correct function on click', () => {
const { handleLike, label } = defaultProps
const { getByText } = render(
<Button {...defaultProps} onClick={handleLike} />
)
fireEvent.click(getByText(label))
expect(handleLike).toHaveBeenCalled()
})
14 changes: 14 additions & 0 deletions src/components/__test__/List.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'
import { render, fireEvent, waitFor, cleanup } from '@testing-library/react'
import List from '../List'

afterEach(cleanup)

test('should not render List on start', () => {
const { queryByTestId } = render(<List />)
expect(queryByTestId('fetch-list')).toBeNull()
})
test('should show Loader on start', () => {
const { queryByTestId } = render(<List />)
expect(queryByTestId('loader').textContent).toBe('Fetching photos ...')
})
2 changes: 1 addition & 1 deletion src/hooks/useInfiniteScroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const useInfiniteScroll = (callback) => {
const [isFetching, setIsFetching] = useState(false)

useEffect(() => {
const debounceHandleScroll = debounce(handleScroll, 1500)
const debounceHandleScroll = debounce(handleScroll, 1000)
window?.addEventListener('scroll', debounceHandleScroll)
return () => {
window?.removeEventListener('scroll', debounceHandleScroll)
Expand Down
20 changes: 0 additions & 20 deletions src/utils/debounce.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,3 @@ const debounce = (callback, wait = 250) => {
}
}
export default debounce

/*
// Testing it:
var d = debounce(() => console.log("CALLED"), 1000);
for (let i = 0; i < 10; i++) {
// call every 100 ms (change to 1500 to see that debouncing will not happen)
let timeOut = 100 * i;
const cb = () => {
const date = new Date();
console.log(`calling at ${date.getSeconds()}.${date.getMilliseconds()}`);
d()
}
setTimeout(cb, timeOut)
}
*/

0 comments on commit fe9e663

Please sign in to comment.