feat: 🎸 Code cleanup, refactoring, linting and tests

I know this should be a fix but whatever...
This commit is contained in:
Johan Öbrink 2021-02-07 12:08:31 +01:00
parent 3d59035a20
commit d0a0314ae6
13 changed files with 238 additions and 61 deletions

View File

@ -1,9 +1,15 @@
module.exports = {
extends: ['airbnb-typescript'],
extends: [
'airbnb-typescript',
'plugin:jest/recommended'
],
parserOptions: {
project: `./tsconfig.json`
project: `./tsconfig.json`,
},
rules: {
'@typescript-eslint/semi': ['error', 'never']
}
'@typescript-eslint/semi': ['error', 'never'],
'jest/no-mocks-import': [0],
'max-len': [1, 110],
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
},
}

View File

@ -39,6 +39,7 @@
"eslint": "^7.19.0",
"eslint-config-airbnb-typescript": "^12.0.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-react": "^7.20.3",
"eslint-plugin-react-hooks": "^4.0.8",

View File

@ -13,5 +13,10 @@ export default (init = {}, delay = 0) => {
await pause(delay)
cache[key] = val
}
return { getItem, setItem, cache }
const clear = () => {
Object.keys(cache).forEach((key) => { cache[key] = undefined })
}
return {
getItem, setItem, cache, clear,
}
}

146
src/fake.test.js Normal file
View File

@ -0,0 +1,146 @@
import React from 'react'
import { act, renderHook } from '@testing-library/react-hooks'
import { ApiProvider } from '.'
import createStorage from './__mocks__/AsyncStorage'
import {
useCalendar,
useChildList,
useClassmates,
useMenu,
useNews,
useNotifications,
useSchedule,
useUser,
} from './hooks'
const { default: init } = jest.requireActual('@skolplattformen/embedded-api')
describe('hooks with fake data', () => {
let api
let storage
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(async () => {
api = init(() => { }, () => { })
await api.login('121212121212')
storage = createStorage({})
})
it('returns user', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useUser(), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data).toEqual({
firstName: 'Namn',
lastName: 'Namnsson',
})
})
})
it('returns child list', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useChildList(), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data).toHaveLength(2)
})
})
describe('data belonging to one child', () => {
let child
beforeAll(async () => {
[child] = await api.getChildren()
})
it('returns calendar', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useCalendar(child), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data.length).toBeGreaterThan(1)
})
})
it('returns classmates', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useClassmates(child), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data.length).toBeGreaterThan(1)
})
})
it('returns menu', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useMenu(child), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data.length).toBeGreaterThan(1)
})
})
it('returns news', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useNews(child), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data.length).toBeGreaterThan(1)
})
})
it('returns notifications', async () => {
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useNotifications(child), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data.length).toBeGreaterThan(1)
})
})
it('returns schedule', async () => {
const from = '2021-01-01'
const to = '2021-01-08'
await act(async () => {
const {
result,
waitForNextUpdate,
} = renderHook(() => useSchedule(child, from, to), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
// No fake schedule in embedded-api yet
expect(result.current.data.length).not.toBeGreaterThan(1)
})
})
})
})

View File

@ -6,26 +6,26 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useCalendar(child)', () => {
let api
let storage
let result
let response
let child
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getCalendar.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
calendar_10: [{ id: 2 }]
calendar_10: [{ id: 2 }],
}, 2)
child = { id: 10 }
})
@ -69,7 +69,7 @@ describe('useCalendar(child)', () => {
expect(result.current.status).toEqual('loaded')
})
})
it('calls cache', async () => {
it('retrieves data from cache', async () => {
await act(async () => {
api.isLoggedIn = true
const { result, waitForNextUpdate } = renderHook(() => useCalendar(child), { wrapper })
@ -80,6 +80,18 @@ describe('useCalendar(child)', () => {
expect(result.current.data).toEqual([{ id: 2 }])
})
})
it('works when cache is empty', async () => {
storage.clear()
await act(async () => {
api.isLoggedIn = true
const { result, waitForNextUpdate } = renderHook(() => useCalendar(child), { wrapper })
await waitForNextUpdate()
await waitForNextUpdate()
expect(result.current.data).toEqual([{ id: 1 }])
})
})
it('updates status to loading', async () => {
await act(async () => {
api.isLoggedIn = true
@ -115,7 +127,7 @@ describe('useCalendar(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['calendar_10']).toEqual('[{"id":1}]')
expect(storage.cache.calendar_10).toEqual('[{"id":1}]')
})
})
it('does not store in cache if fake', async () => {
@ -130,7 +142,7 @@ describe('useCalendar(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['calendar_10']).toEqual('[{"id":2}]')
expect(storage.cache.calendar_10).toEqual('[{"id":2}]')
})
})
})

View File

@ -6,25 +6,25 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useChildList()', () => {
let api
let storage
let result
let response
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getChildren.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
children: [{ id: 2 }]
children: [{ id: 2 }],
}, 2)
})
afterEach(async () => {
@ -113,7 +113,7 @@ describe('useChildList()', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['children']).toEqual('[{"id":1}]')
expect(storage.cache.children).toEqual('[{"id":1}]')
})
})
it('does not store in cache if fake', async () => {
@ -128,7 +128,7 @@ describe('useChildList()', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['children']).toEqual('[{"id":2}]')
expect(storage.cache.children).toEqual('[{"id":2}]')
})
})
})

View File

@ -6,26 +6,26 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useClassmates(child)', () => {
let api
let storage
let result
let response
let child
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getClassmates.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
classmates_10: [{ id: 2 }]
classmates_10: [{ id: 2 }],
}, 2)
child = { id: 10 }
})
@ -115,7 +115,7 @@ describe('useClassmates(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['classmates_10']).toEqual('[{"id":1}]')
expect(storage.cache.classmates_10).toEqual('[{"id":1}]')
})
})
it('does not store in cache if fake', async () => {
@ -130,7 +130,7 @@ describe('useClassmates(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['classmates_10']).toEqual('[{"id":2}]')
expect(storage.cache.classmates_10).toEqual('[{"id":2}]')
})
})
})

View File

@ -6,26 +6,26 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useMenu(child)', () => {
let api
let storage
let result
let response
let child
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getMenu.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
menu_10: [{ id: 2 }]
menu_10: [{ id: 2 }],
}, 2)
child = { id: 10 }
})
@ -115,7 +115,7 @@ describe('useMenu(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['menu_10']).toEqual('[{"id":1}]')
expect(storage.cache.menu_10).toEqual('[{"id":1}]')
})
})
it('does not store in cache if fake', async () => {
@ -130,7 +130,7 @@ describe('useMenu(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['menu_10']).toEqual('[{"id":2}]')
expect(storage.cache.menu_10).toEqual('[{"id":2}]')
})
})
})

View File

@ -6,26 +6,26 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useNews(child)', () => {
let api
let storage
let result
let response
let child
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getNews.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
news_10: [{ id: 2 }]
news_10: [{ id: 2 }],
}, 2)
child = { id: 10 }
})
@ -115,7 +115,7 @@ describe('useNews(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['news_10']).toEqual('[{"id":1}]')
expect(storage.cache.news_10).toEqual('[{"id":1}]')
})
})
it('does not store in cache if fake', async () => {
@ -130,7 +130,7 @@ describe('useNews(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['news_10']).toEqual('[{"id":2}]')
expect(storage.cache.news_10).toEqual('[{"id":2}]')
})
})
})

View File

@ -6,26 +6,26 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useNotifications(child)', () => {
let api
let storage
let result
let response
let child
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getNotifications.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
notifications_10: [{ id: 2 }]
notifications_10: [{ id: 2 }],
}, 2)
child = { id: 10 }
})
@ -115,7 +115,7 @@ describe('useNotifications(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['notifications_10']).toEqual('[{"id":1}]')
expect(storage.cache.notifications_10).toEqual('[{"id":1}]')
})
})
it('does not store in cache if fake', async () => {
@ -130,7 +130,7 @@ describe('useNotifications(child)', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['notifications_10']).toEqual('[{"id":2}]')
expect(storage.cache.notifications_10).toEqual('[{"id":2}]')
})
})
})

View File

@ -6,12 +6,12 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useSchedule(child, from, to)', () => {
let api
let storage
let result
let response
let child
let from
let to
@ -19,15 +19,15 @@ describe('useSchedule(child, from, to)', () => {
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = [{ id: 1 }]
response = [{ id: 1 }]
api = init()
api.getSchedule.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
'schedule_10_2021-01-01_2021-01-08': [{ id: 2 }]
'schedule_10_2021-01-01_2021-01-08': [{ id: 2 }],
}, 2)
child = { id: 10 }
from = '2021-01-01'

View File

@ -6,25 +6,25 @@ import store from './store'
import init from './__mocks__/@skolplattformen/embedded-api'
import createStorage from './__mocks__/AsyncStorage'
const pause = (ms = 0) => new Promise(r => setTimeout(r, ms))
const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms))
describe('useUser()', () => {
let api
let storage
let result
let response
const wrapper = ({ children }) => (
<ApiProvider api={api} storage={storage}>{children}</ApiProvider>
)
beforeEach(() => {
result = { id: 1 }
response = { id: 1 }
api = init()
api.getUser.mockImplementation(() => (
new Promise((res) => {
setTimeout(() => res(result), 50)
setTimeout(() => res(response), 50)
})
))
storage = createStorage({
user: { id: 2 }
user: { id: 2 },
}, 2)
})
afterEach(async () => {
@ -113,7 +113,7 @@ describe('useUser()', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['user']).toEqual('{"id":1}')
expect(storage.cache.user).toEqual('{"id":1}')
})
})
it('does not store in cache if fake', async () => {
@ -128,7 +128,7 @@ describe('useUser()', () => {
await waitForNextUpdate()
await pause(20)
expect(storage.cache['user']).toEqual('{"id":2}')
expect(storage.cache.user).toEqual('{"id":2}')
})
})
})

View File

@ -1400,7 +1400,7 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@4.14.2":
"@typescript-eslint/experimental-utils@4.14.2", "@typescript-eslint/experimental-utils@^4.0.1":
version "4.14.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.2.tgz#9df35049d1d36b6cbaba534d703648b9e1f05cbb"
integrity sha512-mV9pmET4C2y2WlyHmD+Iun8SAEqkLahHGBkGqDVslHkmoj3VnxnGP4ANlwuxxfq1BsKdl/MPieDbohCEQgKrwA==
@ -2540,6 +2540,13 @@ eslint-plugin-import@^2.22.0:
resolve "^1.17.0"
tsconfig-paths "^3.9.0"
eslint-plugin-jest@^24.1.3:
version "24.1.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz#fa3db864f06c5623ff43485ca6c0e8fc5fe8ba0c"
integrity sha512-dNGGjzuEzCE3d5EPZQ/QGtmlMotqnYWD/QpCZ1UuZlrMAdhG5rldh0N0haCvhGnUkSeuORS5VNROwF9Hrgn3Lg==
dependencies:
"@typescript-eslint/experimental-utils" "^4.0.1"
eslint-plugin-jsx-a11y@^6.3.1:
version "6.4.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd"