Skip to content

Commit 02109cc

Browse files
committed
Store new employers in session
1 parent c45871a commit 02109cc

File tree

5 files changed

+131
-11
lines changed

5 files changed

+131
-11
lines changed

e2e/integration/journey.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,15 @@ it('can create a new employer', () => {
132132
)
133133
cy.findByText('Weyland Yutani').should('exist')
134134
cy.findByText(/Make sure you typed it correctly\./).should('exist')
135+
cy.visit('/')
136+
cy.findByRole('combobox', { name: /hear about code your future/i }).select(
137+
'Employer'
138+
)
139+
cy.findByRole('combobox', { name: /who is your employer/i }).type(
140+
'yutani{enter}'
141+
)
142+
cy.findByText('Weyland Yutani').should('exist')
143+
cy.findByText(/Make sure you typed it correctly\./).should('exist')
135144
})
136145

137146
const setExperience = (topic, level) => {

src/Components/forms/inputs/EmployerDropDown.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
import { useEffect, useMemo, useState } from 'react'
1+
import { useMemo } from 'react'
22
import { Label } from 'reactstrap'
33
import Select from 'react-select/creatable'
44

5+
import useSession from '../../../hooks/useSession'
6+
57
const EmployerDropDown = ({
68
arrayList: employers,
79
isEmpty,
810
onChange,
911
value
1012
}) => {
11-
const [options, setOptions] = useState([])
13+
const [options, setOptions] = useSession('cyfEmployerList', () =>
14+
employers.map(({ _id, name }) => ({
15+
value: _id,
16+
label: name
17+
}))
18+
)
1219

1320
const isCustomEntry = useMemo(
1421
() => value !== '' && !employers.some(({ name }) => name === value),
@@ -20,15 +27,6 @@ const EmployerDropDown = ({
2027
[options, value]
2128
)
2229

23-
useEffect(() => {
24-
setOptions(
25-
employers.map(({ _id, name }) => ({
26-
value: _id,
27-
label: name
28-
}))
29-
)
30-
}, [employers])
31-
3230
const handleChange = value =>
3331
onChange({ target: { name: 'employer', type: 'text', value } })
3432

src/Components/forms/inputs/EmployerDropDown.test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import selectEvent from 'react-select-event'
55
import EmployerDropDown from './EmployerDropDown'
66

77
describe('EmployerDropDown', () => {
8+
beforeEach(() => {
9+
sessionStorage.clear()
10+
})
11+
812
it('shows the label value and place holder value', async () => {
913
renderInForm({ employers: ['Arnold Clark'] })
1014
expect(screen.getByTestId('form')).toHaveTextContent(

src/hooks/useSession.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { useCallback, useState } from 'react'
2+
3+
/**
4+
* Behaves like useState but with the value retained in sessionStorage.
5+
*
6+
* @template T
7+
* @param {string} key
8+
* @param {(T | (() => T))=} initialValue
9+
* @returns {[T | null, (newValue: T | ((oldValue: T) => T)) => void]}
10+
*/
11+
export default function useSession(key, initialValue) {
12+
const [data, setData] = useState(startValue(key, initialValue))
13+
const updateData = useCallback(
14+
newData => {
15+
setData(oldData => stored(key, callIfFunc(newData, oldData)))
16+
},
17+
[key]
18+
)
19+
return [data, updateData]
20+
}
21+
22+
const callIfFunc = (maybeFunc, ...args) =>
23+
typeof maybeFunc === 'function' ? maybeFunc(...args) : maybeFunc
24+
25+
const retrieved = key => {
26+
return JSON.parse(sessionStorage.getItem(key))
27+
}
28+
29+
const startValue = (key, initialValue) => {
30+
return retrieved(key) ?? stored(key, callIfFunc(initialValue))
31+
}
32+
33+
const stored = (key, value = null) => {
34+
sessionStorage.setItem(key, JSON.stringify(value))
35+
return value
36+
}

src/hooks/useSession.test.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { act, renderHook } from '@testing-library/react'
2+
3+
import useSession from './useSession'
4+
5+
describe('useSession', () => {
6+
const key = 'SOME_RANDOM_KEY'
7+
8+
beforeEach(() => {
9+
sessionStorage.clear()
10+
})
11+
12+
describe('initial value', () => {
13+
it('uses the session value if available', () => {
14+
sessionStorage.setItem(key, '{"foo":"bar"}')
15+
const {
16+
result: {
17+
current: [data]
18+
}
19+
} = renderHook(() => useSession(key, { something: 'else' }))
20+
expect(data).toEqual({ foo: 'bar' })
21+
expect(sessionStorage.getItem(key)).toBe('{"foo":"bar"}')
22+
})
23+
24+
it('uses null by default', () => {
25+
const {
26+
result: {
27+
current: [data]
28+
}
29+
} = renderHook(() => useSession(key))
30+
expect(data).toBeNull()
31+
expect(sessionStorage.getItem(key)).toBe('null')
32+
})
33+
34+
it('uses initial value if provided', () => {
35+
const {
36+
result: {
37+
current: [data]
38+
}
39+
} = renderHook(() => useSession(key, { foo: 'bar' }))
40+
expect(data).toEqual({ foo: 'bar' })
41+
expect(sessionStorage.getItem(key)).toBe('{"foo":"bar"}')
42+
})
43+
44+
it('accepts a function returning initial value', () => {
45+
const {
46+
result: {
47+
current: [data]
48+
}
49+
} = renderHook(() => useSession(key, () => ({ foo: 'bar' })))
50+
expect(data).toEqual({ foo: 'bar' })
51+
expect(sessionStorage.getItem(key)).toBe('{"foo":"bar"}')
52+
})
53+
})
54+
55+
describe('updating', () => {
56+
it('updates the value asked', async () => {
57+
const { result } = renderHook(() => useSession(key))
58+
act(() => result.current[1]({ foo: 'bar' }))
59+
expect(result.current[0]).toEqual({ foo: 'bar' })
60+
expect(sessionStorage.getItem(key)).toBe('{"foo":"bar"}')
61+
})
62+
63+
it('accepts a functional update', () => {
64+
const { result } = renderHook(() => useSession(key, { foo: 'bar' }))
65+
act(() => result.current[1](previous => ({ ...previous, baz: 'qux' })))
66+
expect(result.current[0]).toEqual({ foo: 'bar', baz: 'qux' })
67+
expect(JSON.parse(sessionStorage.getItem(key))).toEqual({
68+
foo: 'bar',
69+
baz: 'qux'
70+
})
71+
})
72+
})
73+
})

0 commit comments

Comments
 (0)