Skip to content

Commit

Permalink
test for edit modal
Browse files Browse the repository at this point in the history
  • Loading branch information
david-crespo committed Feb 9, 2022
1 parent 89e1792 commit 3533f7f
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 23 deletions.
130 changes: 111 additions & 19 deletions app/pages/project/networking/VpcPage/VpcPage.spec.ts
@@ -1,9 +1,11 @@
import {
clickByRole,
renderAppAt,
screen,
waitForElementToBeRemoved,
clickByRole,
typeByRole,
waitForElementToBeRemoved,
userEvent,
getByRole,
} from 'app/test-utils'
import { defaultFirewallRules } from '@oxide/api-mocks'

Expand All @@ -22,7 +24,7 @@ describe('VpcPage', () => {
expect(screen.queryByTestId('create-vpc-subnet-modal')).toBeNull()

// click button to open modal
clickByRole('button', 'New subnet')
await clickByRole('button', 'New subnet')

// modal is open
screen.getByRole('dialog', { name: 'Create subnet' })
Expand All @@ -32,7 +34,7 @@ describe('VpcPage', () => {
typeByRole('textbox', 'Name', 'mock-subnet-2')

// submit the form
clickByRole('button', 'Create subnet')
await clickByRole('button', 'Create subnet')

// wait for modal to close
await waitForElementToBeRemoved(() =>
Expand All @@ -48,7 +50,7 @@ describe('VpcPage', () => {
describe('firewall rule', () => {
it('create works', async () => {
renderAppAt('/orgs/maze-war/projects/mock-project/vpcs/mock-vpc')
clickByRole('tab', 'Firewall Rules')
await clickByRole('tab', 'Firewall Rules')

// default rules show up in the table
for (const { name } of defaultFirewallRules) {
Expand All @@ -63,45 +65,45 @@ describe('VpcPage', () => {
).toBeNull()

// click button to open modal
clickByRole('button', 'New rule')
await clickByRole('button', 'New rule')

// modal is open
await screen.findByText('Create firewall rule')
screen.getByRole('dialog', { name: 'Create firewall rule' })

typeByRole('textbox', 'Name', 'my-new-rule')

clickByRole('radio', 'Outgoing')
await clickByRole('radio', 'Outgoing')

// input type="number" becomes spinbutton for some reason
typeByRole('spinbutton', 'Priority', '5')

clickByRole('button', 'Target type')
clickByRole('option', 'VPC')
await clickByRole('button', 'Target type')
await clickByRole('option', 'VPC')
typeByRole('textbox', 'Target name', 'my-target-vpc')
clickByRole('button', 'Add target')
await clickByRole('button', 'Add target')

// target is added to targets table
screen.getByRole('cell', { name: 'my-target-vpc' })

clickByRole('button', 'Host type')
clickByRole('option', 'Instance')
typeByRole('textbox', 'Value', 'my-target-instance')
clickByRole('button', 'Add host filter')
await clickByRole('button', 'Host type')
await clickByRole('option', 'Instance')
typeByRole('textbox', 'Value', 'host-filter-instance')
await clickByRole('button', 'Add host filter')

// host is added to hosts table
screen.getByRole('cell', { name: 'my-target-instance' })
screen.getByRole('cell', { name: 'host-filter-instance' })

// TODO: test invalid port range once I put an error message in there
typeByRole('textbox', 'Port filter', '123-456')
clickByRole('button', 'Add port filter')
await clickByRole('button', 'Add port filter')

// port range is added to port ranges table
screen.getByRole('cell', { name: '123-456' })

clickByRole('checkbox', 'UDP')
await clickByRole('checkbox', 'UDP')

// submit the form
clickByRole('button', 'Create rule')
await clickByRole('button', 'Create rule')

// wait for modal to close
await waitForElementToBeRemoved(
Expand All @@ -112,9 +114,99 @@ describe('VpcPage', () => {

// table refetches and now includes the new rule as well as the originals
await screen.findByText('my-new-rule')
screen.getByRole('cell', {
name: 'instance host-filter-instance UDP 123-456',
})

for (const { name } of defaultFirewallRules) {
screen.getByText(name)
}
}, 10000)

it('edit works', async () => {
renderAppAt('/orgs/maze-war/projects/mock-project/vpcs/mock-vpc')
await clickByRole('tab', 'Firewall Rules')

// default rules show up in the table
for (const { name } of defaultFirewallRules) {
await screen.findByText(name)
}
expect(screen.getAllByRole('row').length).toEqual(5) // 4 + header

// the one we'll be adding is not there
expect(screen.queryByRole('cell', { name: 'new-rule-name' })).toBeNull()

// modal is not already open
expect(
screen.queryByRole('dialog', { name: 'Edit firewall rule' })
).toBeNull()

// click more button on allow-icmp row to get menu, then click Edit
const allowIcmpRow = screen.getByRole('row', { name: /allow-icmp/ })
const more = getByRole(allowIcmpRow, 'button', { name: 'More' })
await userEvent.click(more)
await clickByRole('menuitem', 'Edit')

// now the modal is open
screen.getByRole('dialog', { name: 'Edit firewall rule' })

// name is populated
const name = screen.getByRole('textbox', {
name: 'Name',
}) as HTMLInputElement
expect(name.value).toEqual('allow-icmp')

// priority is populated
const priority = screen.getByRole('spinbutton', {
name: 'Priority',
}) as HTMLInputElement
expect(priority.value).toEqual('65534')

// protocol is populated
expect(screen.getByRole('checkbox', { name: /ICMP/ })).toBeChecked()
expect(screen.getByRole('checkbox', { name: /TCP/ })).not.toBeChecked()
expect(screen.getByRole('checkbox', { name: /UDP/ })).not.toBeChecked()

// targets default vpc
screen.getByRole('cell', { name: 'vpc' })
screen.getByRole('cell', { name: 'default' })

// update name
await userEvent.clear(name)
await userEvent.type(name, 'new-rule-name')

await clickByRole('button', 'Host type')
await clickByRole('option', 'Instance')
typeByRole('textbox', 'Value', 'edit-filter-instance')
await clickByRole('button', 'Add host filter')

// host is added to hosts table
screen.getByRole('cell', { name: 'edit-filter-instance' })

// submit the form
await clickByRole('button', 'Update rule')

// wait for modal to close
await waitForElementToBeRemoved(
() => screen.queryByText('Edit firewall rule'),
// fails in CI without a longer timeout (default 1000). boo
{ timeout: 2000 }
)

// table refetches and now includes the updated rule name, not the old name
await screen.findByText('new-rule-name')
expect(screen.queryByRole('cell', { name: 'allow-icmp' })).toBeNull()
expect(screen.getAllByRole('row').length).toEqual(5) // 4 + header

screen.getByRole('cell', {
name: 'instance edit-filter-instance ICMP',
})

// other 3 rules are still there
const rest = defaultFirewallRules.filter((r) => r.name !== 'allow-icmp')
for (const { name } of rest) {
screen.getByRole('cell', { name })
}
}, 20000)
})
})
Expand Up @@ -498,6 +498,8 @@ type EditProps = {
existingRules: VpcFirewallRule[]
}

// TODO: this whole thing. shouldn't take much to fill in the initialValues
// based on the rule being edited
export function EditFirewallRuleModal({
onDismiss,
orgName,
Expand Down Expand Up @@ -527,7 +529,7 @@ export function EditFirewallRuleModal({
return (
<SideModal
id="edit-firewall-rule-modal"
title="Edit rule"
title="Edit firewall rule"
onDismiss={dismiss}
>
<Formik
Expand Down
7 changes: 4 additions & 3 deletions app/test-utils.tsx
Expand Up @@ -91,15 +91,16 @@ export function renderAppAt(url: string) {
****************************************/

export * from '@testing-library/react'
export { customRender as render }
import userEvent from '@testing-library/user-event'
export { customRender as render, userEvent }

// convenience functions so we can click and type in a one-liner. these were
// initially created to use the user-event library, but it was remarkably slow.
// see if those issues are improved before trying that again

export function clickByRole(role: string, name: string) {
export async function clickByRole(role: string, name: string) {
const element = screen.getByRole(role, { name })
fireEvent.click(element)
await userEvent.click(element)
}

export function typeByRole(role: string, name: string, text: string) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -78,6 +78,7 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.1",
"@testing-library/user-event": "14.0.0-beta.10",
"@types/jscodeshift": "^0.11.2",
"@types/mousetrap": "^1.6.8",
"@types/node": "^16.11.9",
Expand Down
7 changes: 7 additions & 0 deletions yarn.lock
Expand Up @@ -3103,6 +3103,13 @@
"@babel/runtime" "^7.12.5"
"@testing-library/dom" "^8.0.0"

"@testing-library/user-event@14.0.0-beta.10":
version "14.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.0.0-beta.10.tgz#7ac68e9542e30aa1744f354a7f026d7a70647de2"
integrity sha512-a3iA66OE1PfcDc1BlfGm4yqgRid78en4GtAEsn6PwMIteVJzZe1aWztvZsWbEPX85y4JXaPwRiLD9aSloi0cwA==
dependencies:
"@babel/runtime" "^7.12.5"

"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
Expand Down

0 comments on commit 3533f7f

Please sign in to comment.