Skip to content

Commit

Permalink
proof of concept for making all page-level tests into integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
david-crespo committed Dec 12, 2021
1 parent e34afcb commit 97fe39a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 25 deletions.
32 changes: 14 additions & 18 deletions app/pages/__tests__/InstanceCreateForm.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import React from 'react'
import {
fireEvent,
lastBody,
renderWithRouter,
renderAppAt,
screen,
waitFor,
} from '../../test-utils'
import fetchMock from 'fetch-mock'

import { org, project, instance } from '@oxide/api-mocks'

import { InstanceCreateForm } from '../project/instances/create/InstancesCreatePage'

const submitButton = () =>
screen.getByRole('button', { name: 'Create instance' })

Expand All @@ -20,21 +17,14 @@ const instancesUrl = `${projectUrl}/instances`
const disksUrl = `${projectUrl}/disks`
const vpcsUrl = `${projectUrl}/vpcs`

let successSpy: jest.Mock
const renderPage = () =>
renderAppAt(`/orgs/${org.name}/projects/${project.name}/instances/new`)

describe('InstanceCreateForm', () => {
beforeEach(() => {
// existing disk modal fetches disks on render even if it's not visible
fetchMock.get(disksUrl, 200)
fetchMock.get(vpcsUrl, 200)
successSpy = jest.fn()
renderWithRouter(
<InstanceCreateForm
orgName={org.name}
projectName={project.name}
onSuccess={successSpy}
/>
)
})

afterEach(() => {
Expand All @@ -43,6 +33,7 @@ describe('InstanceCreateForm', () => {

it('disables submit button on submit and enables on response', async () => {
const mock = fetchMock.post(instancesUrl, 201)
renderPage()

const submit = submitButton()
expect(submit).not.toBeDisabled()
Expand All @@ -52,14 +43,14 @@ describe('InstanceCreateForm', () => {
expect(mock.called(instancesUrl)).toBeFalsy()
await waitFor(() => expect(submit).toBeDisabled())
expect(mock.done()).toBeTruthy()
expect(submit).not.toBeDisabled()
})

it('shows specific message for known server error code', async () => {
fetchMock.post(instancesUrl, {
status: 400,
body: { error_code: 'ObjectAlreadyExists' },
})
renderPage()

fireEvent.click(submitButton())

Expand All @@ -73,6 +64,7 @@ describe('InstanceCreateForm', () => {
status: 400,
body: { error_code: 'UnknownCode' },
})
renderPage()

fireEvent.click(submitButton())

Expand All @@ -81,6 +73,7 @@ describe('InstanceCreateForm', () => {

it('posts form on submit', async () => {
const mock = fetchMock.post(instancesUrl, 201)
renderPage()

fireEvent.change(screen.getByLabelText('Choose a name'), {
target: { value: 'new-instance' },
Expand All @@ -99,15 +92,18 @@ describe('InstanceCreateForm', () => {
)
})

it('calls onSuccess on success', async () => {
it('navigates to project instances page on success', async () => {
const mock = fetchMock.post(instancesUrl, { status: 201, body: instance })

expect(successSpy).not.toHaveBeenCalled()
const { history } = renderPage()

fireEvent.click(submitButton())

await waitFor(() => expect(mock.called(instancesUrl)).toBeTruthy())
await waitFor(() => expect(mock.done()).toBeTruthy())
await waitFor(() => expect(successSpy).toHaveBeenCalled())
await waitFor(() =>
expect(history.location.pathname).toEqual(
`/orgs/${org.name}/projects/${project.name}/instances`
)
)
})
})
21 changes: 18 additions & 3 deletions app/test-utils.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import React from 'react'
import { BrowserRouter as Router } from 'react-router-dom'
import {
BrowserRouter,
unstable_HistoryRouter as HistoryRouter,
} from 'react-router-dom'
import { createMemoryHistory } from 'history'
import { render } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from 'react-query'
import type { FetchMockStatic } from 'fetch-mock'
import { routes } from './routes'

const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -22,14 +27,24 @@ const customRender = (ui: React.ReactElement) =>
export const renderWithRouter = (ui: React.ReactElement) =>
render(ui, {
wrapper: ({ children }) => (
<Router>
<BrowserRouter>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</Router>
</BrowserRouter>
),
})

export function renderAppAt(location: string) {
const history = createMemoryHistory({ initialEntries: [location] })
const rendered = render(
<HistoryRouter history={history}>
<QueryClientProvider client={queryClient}>{routes}</QueryClientProvider>
</HistoryRouter>
)
return { history, rendered }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const lastBody = (mock: FetchMockStatic): any =>
JSON.parse(mock.lastOptions()?.body as unknown as string)
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"react-is": "^17.0.2",
"react-popper": "^2.2.5",
"react-query": "^3.13.12",
"react-router": "^6.0.0",
"react-router-dom": "^6.0.0",
"react-router": "^6.1.1",
"react-router-dom": "^6.1.1",
"react-table": "^7.7.0",
"react-transition-group": "^4.4.1",
"recharts": "^2.1.6",
Expand Down
19 changes: 17 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12175,21 +12175,36 @@ react-resize-detector@^6.6.3:
lodash.throttle "^4.1.1"
resize-observer-polyfill "^1.5.1"

react-router-dom@^6.0.0, react-router-dom@^6.0.0-beta.8:
react-router-dom@^6.0.0-beta.8:
version "6.0.2"
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.0.2.tgz"
integrity sha512-cOpJ4B6raFutr0EG8O/M2fEoyQmwvZWomf1c6W2YXBZuFBx8oTk/zqjXghwScyhfrtnt0lANXV2182NQblRxFA==
dependencies:
history "^5.1.0"
react-router "6.0.2"

[email protected], react-router@^6.0.0, react-router@^6.0.0-beta.8:
react-router-dom@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.1.1.tgz#ed59376ff9115bc49227e87982a32e91e9530ca3"
integrity sha512-O3UH89DI4o+swd2q6lF4dSmpuNCxwkUXcj0zAFcVc1H+YoPE6T7uwoFMX0ws1pUvCY8lYDucFpOqCCdal6VFzg==
dependencies:
history "^5.1.0"
react-router "6.1.1"

[email protected], react-router@^6.0.0-beta.8:
version "6.0.2"
resolved "https://registry.npmjs.org/react-router/-/react-router-6.0.2.tgz"
integrity sha512-8/Wm3Ed8t7TuedXjAvV39+c8j0vwrI5qVsYqjFr5WkJjsJpEvNSoLRUbtqSEYzqaTUj1IV+sbPJxvO+accvU0Q==
dependencies:
history "^5.1.0"

[email protected], react-router@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.1.1.tgz#16f41bf54e87d995bcd4d447720a693f77d8fcb9"
integrity sha512-55o96RiDZmC0uD17DPqVmzzfdNd2Dc+EjkYvMAmHl43du/GItaTdFr5WwjTryNWPXZ+OOVQxQhwAX25UwxpHtw==
dependencies:
history "^5.1.0"

react-sizeme@^3.0.1:
version "3.0.2"
resolved "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz"
Expand Down

0 comments on commit 97fe39a

Please sign in to comment.