-
Notifications
You must be signed in to change notification settings - Fork 13
Firewall rules create/edit modal #630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
62e6e65
stub out firewall rule form based on API (needs design pass)
david-crespo a8a9d49
msw endpoint for get rules
david-crespo 9882b5b
hack in vpcId on firewall rule in anticipation of omicron#663
david-crespo 36dbae3
working but ugly targets subform
david-crespo cfb5eb2
ports, hosts, and targets subforms actually work
david-crespo 6a71251
we can PUT rules!
david-crespo 271bb26
get rid of vestigial subnet copy, move name/description up
david-crespo 03fe20c
include all existing rules when creating one
david-crespo 87a404a
be super sure we're not getting any extra nonsense in the update object
david-crespo e9cc6f8
fucking epic test
david-crespo 3b3a4ca
update API to pull in vpc_id change from omicron main
david-crespo cf440ca
automatically update packer-id
github-actions[bot] 9c755b7
switch back to fireEvent, everything passes, get rid of yarn test:run
david-crespo f98a86e
Merge branch 'main' into firewall-rule-crud
david-crespo 8b74db4
update clear button colors
david-crespo dc7f5f2
lengthen timeout for CI. appalling
david-crespo 9ed9e7c
faster testing through science
david-crespo 3523771
explicit dep on @testing-lib/dom was actually messing me up
david-crespo d078b7f
wait longer for the modal to close because CI
david-crespo 286a1fc
memoize tableData more goodly
david-crespo e1121d6
update API for rules so we get list of rules instead of map
david-crespo 438de04
automatically update packer-id
github-actions[bot] 470d3b0
sort firewall rules by name in msw, fix get to put transformer
david-crespo ab165da
Merge main into firewall-rule-crud
david-crespo 2c3607a
prettier format
david-crespo 89e1792
make editing work
david-crespo 055f2a0
test for edit modal
david-crespo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,209 @@ | ||
import { | ||
fireEvent, | ||
clickByRole, | ||
renderAppAt, | ||
screen, | ||
userEvent, | ||
typeByRole, | ||
waitForElementToBeRemoved, | ||
userEvent, | ||
getByRole, | ||
} from 'app/test-utils' | ||
import { defaultFirewallRules } from '@oxide/api-mocks' | ||
|
||
describe('VpcPage', () => { | ||
describe('subnets tab', () => { | ||
it('creating a subnet works', async () => { | ||
describe('subnet', () => { | ||
it('create works', async () => { | ||
renderAppAt('/orgs/maze-war/projects/mock-project/vpcs/mock-vpc') | ||
screen.getByText('Subnets') | ||
|
||
// wait for subnet to show up in the table | ||
await screen.findByRole('cell', { name: 'mock-subnet' }) | ||
// second one is not there though | ||
await screen.findByText('mock-subnet') | ||
// the one we'll be adding is not there | ||
expect(screen.queryByRole('cell', { name: 'mock-subnet-2' })).toBeNull() | ||
|
||
// modal is not already open | ||
expect(screen.queryByRole('dialog', { name: 'Create subnet' })).toBeNull() | ||
expect(screen.queryByTestId('create-vpc-subnet-modal')).toBeNull() | ||
|
||
// click button to open modal | ||
fireEvent.click(screen.getByRole('button', { name: 'New subnet' })) | ||
await clickByRole('button', 'New subnet') | ||
|
||
// modal is open | ||
screen.getByRole('dialog', { name: 'Create subnet' }) | ||
|
||
const ipv4 = screen.getByRole('textbox', { name: 'IPv4 block' }) | ||
userEvent.type(ipv4, '1.1.1.2/24') | ||
typeByRole('textbox', 'IPv4 block', '1.1.1.2/24') | ||
|
||
typeByRole('textbox', 'Name', 'mock-subnet-2') | ||
|
||
// submit the form | ||
await clickByRole('button', 'Create subnet') | ||
|
||
// wait for modal to close | ||
await waitForElementToBeRemoved(() => | ||
screen.queryByTestId('create-vpc-subnet-modal') | ||
) | ||
|
||
// table refetches and now includes second subnet | ||
await screen.findByText('mock-subnet') | ||
await screen.findByText('mock-subnet-2') | ||
}, 10000) // otherwise it flakes in CI | ||
}) | ||
|
||
describe('firewall rule', () => { | ||
it('create 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) | ||
} | ||
// the one we'll be adding is not there | ||
expect(screen.queryByRole('cell', { name: 'my-new-rule' })).toBeNull() | ||
|
||
// modal is not already open | ||
expect( | ||
screen.queryByRole('dialog', { name: 'Create firewall rule' }) | ||
).toBeNull() | ||
|
||
// click button to open modal | ||
await clickByRole('button', 'New rule') | ||
|
||
// modal is open | ||
screen.getByRole('dialog', { name: 'Create firewall rule' }) | ||
|
||
typeByRole('textbox', 'Name', 'my-new-rule') | ||
|
||
await clickByRole('radio', 'Outgoing') | ||
|
||
// input type="number" becomes spinbutton for some reason | ||
typeByRole('spinbutton', 'Priority', '5') | ||
|
||
await clickByRole('button', 'Target type') | ||
await clickByRole('option', 'VPC') | ||
typeByRole('textbox', 'Target name', 'my-target-vpc') | ||
await clickByRole('button', 'Add target') | ||
|
||
// target is added to targets table | ||
screen.getByRole('cell', { name: 'my-target-vpc' }) | ||
|
||
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: 'host-filter-instance' }) | ||
|
||
// TODO: test invalid port range once I put an error message in there | ||
typeByRole('textbox', 'Port filter', '123-456') | ||
await clickByRole('button', 'Add port filter') | ||
|
||
// port range is added to port ranges table | ||
screen.getByRole('cell', { name: '123-456' }) | ||
|
||
await clickByRole('checkbox', 'UDP') | ||
|
||
// submit the form | ||
await clickByRole('button', 'Create rule') | ||
|
||
// wait for modal to close | ||
await waitForElementToBeRemoved( | ||
() => screen.queryByText('Create firewall rule'), | ||
// fails in CI without a longer timeout (default 1000). boo | ||
{ timeout: 2000 } | ||
) | ||
|
||
// 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) | ||
} | ||
}, 15000) | ||
|
||
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' }) | ||
userEvent.type(name, 'mock-subnet-2') | ||
expect(name).toHaveValue('allow-icmp') | ||
|
||
// priority is populated | ||
const priority = screen.getByRole('spinbutton', { name: 'Priority' }) | ||
expect(priority).toHaveValue(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') | ||
|
||
// add host filter | ||
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 | ||
fireEvent.click(screen.getByRole('button', { name: 'Create subnet' })) | ||
await clickByRole('button', 'Update rule') | ||
|
||
// wait for modal to close | ||
await waitForElementToBeRemoved( | ||
() => screen.queryByRole('dialog', { name: 'Create subnet' }), | ||
() => screen.queryByText('Edit firewall rule'), | ||
// fails in CI without a longer timeout (default 1000). boo | ||
{ timeout: 2000 } | ||
) | ||
|
||
// table refetches and now includes second subnet | ||
screen.getByRole('cell', { name: 'mock-subnet' }) | ||
await screen.findByRole('cell', { name: 'mock-subnet-2' }) | ||
}, 10000) // otherwise it flakes in CI | ||
// 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) | ||
}) | ||
}) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These used to be beautiful role-scoped queries:
But it turns out these were causing all our performance problems. Changing these to *byText cuts the time from from the
onSuccess
on the rules PUT firing to finding the new cell in the table from 2 seconds down to like 150ms.*byRole
is very slow — it's fine forgetByRole
because that runs once and is done, but forfindByRole
, which polls every 50ms until it finds the thing, it messes everything up.There's a PR out on dom-testing-lib that allegedly improves the performance significantly, but when I applied it as a patch using
patch-package
, I was not able to find the improvement. Maybe a slight improvement, but the above 2s delay remained.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth noting that that PR commented out one of the biggest parts of the slow down which is trying to derive the implicit role of an element. Evidently if you pass
{ hidden: true }
as one of the arguments tofindByRole
that increases the speed by ignoring hidden element checks... which may not be what we want. You can read more about that in this issue. Potential performance improvements would likely be required in the downstream in thedom-accessibility-api
which is leveraged by@testing-library/jest-dom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean... it does seem bad to treat hidden elements as present from a user's POV, but if actually did eliminate the bulk of the slowdown I'd consider it