Skip to content

Commit

Permalink
test: adds some extra test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
aviemet committed Dec 5, 2024
1 parent 5b9548e commit 5f4253a
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 59 deletions.
2 changes: 0 additions & 2 deletions __mocks__/axios.ts

This file was deleted.

23 changes: 13 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
"react",
"hooks",
"react-hooks",
"inertiajs"
"inertiajs",
"useForm",
"useInertiaForm"
],
"repository": {
"type": "git",
Expand All @@ -39,14 +41,6 @@
"release": "semantic-release",
"cz": "git-cz"
},
"dependencies": {
"@inertiajs/react": "^1.2.0",
"@rollup/plugin-typescript": "^12.1.1",
"axios": "^1.7.8",
"lodash": "^4.17.21",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.25.9",
Expand All @@ -56,11 +50,13 @@
"@commitlint/cli": "^19.6.0",
"@commitlint/config-conventional": "^19.6.0",
"@eslint/compat": "^1.2.3",
"@inertiajs/react": "^1.2.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@stylistic/eslint-plugin": "^2.11.0",
Expand All @@ -75,6 +71,7 @@
"@types/react-dom": "^18.3.1",
"@typescript-eslint/eslint-plugin": "^8.16.0",
"@typescript-eslint/parser": "^8.16.0",
"axios": "^1.7.8",
"axios-mock-adapter": "^2.1.0",
"circular-json": "^0.5.9",
"commitizen": "^4.3.1",
Expand All @@ -96,7 +93,10 @@
"jest-fixed-jsdom": "^0.0.9",
"jest-mock-axios": "^4.8.0",
"lint-staged": "^15.2.10",
"lodash": "^4.17.21",
"msw": "^2.6.6",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-test-renderer": "^18.3.1",
"rimraf": "^6.0.1",
"rollup": "^4.27.4",
Expand All @@ -111,7 +111,10 @@
},
"peerDependencies": {
"@inertiajs/react": "^1.0.0",
"react": "^16.9.0 || ^17.0.0 || ^18.0.0"
"axios": "^1.7.8",
"lodash": "^2.0.0 || ^3.0.0 || ^4.0.0",
"react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0"
},
"husky": {
"hooks": {
Expand Down
2 changes: 1 addition & 1 deletion src/Inputs/Submit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const Submit = React.forwardRef<HTMLButtonElement, ButtonProps>((
if(!requiredFields || requiredFields.length === 0) return false

return requiredFields.some((field) => isUnset(getData(field)))
}, [data])
}, [data, requiredFields])

return (
<Component { ...{
Expand Down
12 changes: 12 additions & 0 deletions src/utils/isUnset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { isEmpty } from 'lodash'
* Returns whether a value should be considered empty in the context of a form input
*/
export const isUnset = (v: any) => {
if(v === undefined || v === null) {
return true
}

if(typeof v === 'string') {
return v === ''
}
Expand All @@ -12,5 +16,13 @@ export const isUnset = (v: any) => {
return v === 0 ? false : !Boolean(v)
}

if(v instanceof Date) {
return isNaN(v.valueOf())
}

if(typeof v === 'boolean') {
return false
}

return isEmpty(v)
}
5 changes: 0 additions & 5 deletions tests/.eslintrc

This file was deleted.

2 changes: 1 addition & 1 deletion tests/server.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ export const server = setupServer(

// Error scenario
http.post('/api/data-error', () => {
return HttpResponse.json(mockErrorResponse, { status: 404 });
return HttpResponse.json(mockErrorResponse, { status: 302 });
})
)
93 changes: 74 additions & 19 deletions tests/useInertiaForm.server.test.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,93 @@
import { setupServer } from 'msw/node'
import { http } from 'msw'
import { router } from '@inertiajs/core'
import { renderHook, act } from '@testing-library/react-hooks'
import { server } from './server.mock'
import { useInertiaForm } from '../src'

const server = setupServer(
http.post('/form', async () => {})
)

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

describe('submit', () => {
it('should handle response details correctly', async () => {
const testData = {
email: 'some name',
}

jest.spyOn(router, 'post').mockImplementation((url, data, options) => {
options.onError({
// @ts-ignore
describe('flat data forms with errors', () => {
it('should handle flat data with one key', async () => {
const testData = {
email: 'some name',
}

jest.spyOn(router, 'post').mockImplementation((url, data, options) => {
options.onError({
// @ts-ignore
email: ['must exist'],
})
})

const { result } = renderHook(() => useInertiaForm(testData))

await act(async () => {
result.current.submit('post', '/api/data-error')
})

expect(result.current.errors).toMatchObject({
email: ['must exist'],
})
})

const { result } = renderHook(() => useInertiaForm(testData))
it('should flat data with more than one key', async () => {
const testData = {
email: 'some email',
user: 'some name',
}

jest.spyOn(router, 'post').mockImplementation((url, data, options) => {
options.onError({
// @ts-ignore
email: ['must exist'],
// @ts-ignore
username: ['must exist'],
})
})

const { result } = renderHook(() => useInertiaForm(testData))

await act(async () => {
result.current.submit('post', '/api/data-error')
})

await act(async () => {
result.current.submit('post', '/form')
expect(result.current.errors).toMatchObject({
email: ['must exist'],
username: ['must exist'],
})
})
})

describe('nested data', () => {
it('should nest errors', async () => {
const testData = {
user: {
email: 'some email',
username: 'some name',
},
}

expect(result.current.errors).toMatchObject({
email: ['must exist'],
jest.spyOn(router, 'post').mockImplementation((url, data, options) => {
options.onError({
// @ts-ignore
email: ['must exist'],
// @ts-ignore
username: ['must exist'],
})
})

const { result } = renderHook(() => useInertiaForm(testData))

await act(async () => {
result.current.submit('post', '/api/data-error')
})

expect(result.current.errors).toMatchObject({
'user.email': ['must exist'],
'user.username': ['must exist'],
})
})
})
})
66 changes: 66 additions & 0 deletions tests/utils/isUnset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { isUnset } from "../../src/utils"

describe('isUnset', () => {
describe('numbers', () => {
it('should be false for any number', () => {
expect(isUnset(0)).toBe(false)
expect(isUnset(-0)).toBe(false)
expect(isUnset(1)).toBe(false)
expect(isUnset(67959516)).toBe(false)
expect(isUnset(-66)).toBe(false)
expect(isUnset(-985619874)).toBe(false)
})

it('should be true for NaN', () => {
expect(isUnset(NaN)).toBe(true)
})
})

describe('strings', () => {
it('should be false for any non-empty string', () => {
expect(isUnset('string')).toBe(false)
expect(isUnset(' ')).toBe(false)
expect(isUnset(`string literal ${1 + 1}`)).toBe(false)
})

it('should be true for empty strings', () => {
expect(isUnset('')).toBe(true)
})
})

describe('dates', () => {
it('should be false for any valid date object', () => {
expect(isUnset(new Date())).toBe(false)
})

it('should be true for any invalid date object', () => {
expect(isUnset(new Date('not a date'))).toBe(true)
})
})

describe('booleans', () => {
it('should be false for true and false', () => {
expect(isUnset(true)).toBe(false)
expect(isUnset(false)).toBe(false)
})

it('should be true if variable is uninitialized', () => {
let b: boolean
expect(isUnset(b)).toBe(true)
})
})

it('should be true for any "empty" primitive or empty object', () => {
expect(isUnset(undefined)).toBe(true)
expect(isUnset(null)).toBe(true)
expect(isUnset([])).toBe(true)
expect(isUnset({})).toBe(true)
})

it('should be false for any non-empty value', () => {
expect(isUnset({ key: "value" })).toBe(false)
expect(isUnset(["one"])).toBe(false)
expect(isUnset([1])).toBe(false)
expect(isUnset([1, "two", { three: "four" }])).toBe(false)
})
})
36 changes: 15 additions & 21 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4550,25 +4550,14 @@ __metadata:
languageName: node
linkType: hard

"axios@npm:^1.6.0":
version: 1.6.8
resolution: "axios@npm:1.6.8"
"axios@npm:^1.6.0, axios@npm:^1.7.8":
version: 1.7.9
resolution: "axios@npm:1.7.9"
dependencies:
follow-redirects: ^1.15.6
form-data: ^4.0.0
proxy-from-env: ^1.1.0
checksum: bf007fa4b207d102459300698620b3b0873503c6d47bf5a8f6e43c0c64c90035a4f698b55027ca1958f61ab43723df2781c38a99711848d232cad7accbcdfcdd
languageName: node
linkType: hard

"axios@npm:^1.7.8":
version: 1.7.8
resolution: "axios@npm:1.7.8"
dependencies:
follow-redirects: ^1.15.6
form-data: ^4.0.0
proxy-from-env: ^1.1.0
checksum: 3d21652faf8e29fb36c47517d2872bb5e2285127a24f5c53ce23082c4eac7f5a88de84dd49d4a1a83068e5301dcfd9067b41e5fbd00b0d20ab7b0a843559273d
checksum: cb8ce291818effda09240cb60f114d5625909b345e10f389a945320e06acf0bc949d0f8422d25720f5dd421362abee302c99f5e97edec4c156c8939814b23d19
languageName: node
linkType: hard

Expand Down Expand Up @@ -7116,12 +7105,12 @@ __metadata:
linkType: hard

"follow-redirects@npm:^1.15.6":
version: 1.15.6
resolution: "follow-redirects@npm:1.15.6"
version: 1.15.9
resolution: "follow-redirects@npm:1.15.9"
peerDependenciesMeta:
debug:
optional: true
checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5
checksum: 859e2bacc7a54506f2bf9aacb10d165df78c8c1b0ceb8023f966621b233717dab56e8d08baadc3ad3b9db58af290413d585c999694b7c146aaf2616340c3d2a6
languageName: node
linkType: hard

Expand Down Expand Up @@ -11666,11 +11655,11 @@ __metadata:
linkType: hard

"qs@npm:^6.9.0":
version: 6.12.1
resolution: "qs@npm:6.12.1"
version: 6.13.1
resolution: "qs@npm:6.13.1"
dependencies:
side-channel: ^1.0.6
checksum: aa761d99e65b6936ba2dd2187f2d9976afbcda38deb3ff1b3fe331d09b0c578ed79ca2abdde1271164b5be619c521ec7db9b34c23f49a074e5921372d16242d5
checksum: 86c5059146955fab76624e95771031541328c171b1d63d48a7ac3b1fdffe262faf8bc5fcadc1684e6f3da3ec87a8dedc8c0009792aceb20c5e94dc34cf468bb9
languageName: node
linkType: hard

Expand Down Expand Up @@ -13939,7 +13928,12 @@ __metadata:
typescript: ^5.7.2
peerDependencies:
"@inertiajs/react": ^1.0.0
axios: ^1.7.8
react: ^16.9.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.9.0 || ^17.0.0 || ^18.0.0
dependenciesMeta:
lodash:
optional: true
languageName: unknown
linkType: soft

Expand Down

0 comments on commit 5f4253a

Please sign in to comment.