Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-12429-tests-1750996385974.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Clean up VPC unit tests and mock queries over relying on server handlers ([#12429](https://github.com/linode/manager/pull/12429))
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ describe('Event fetching and polling', () => {
// We need access to the `clock` object directly since we cannot call `cy.clock()` inside
// a `should(() => {})` callback because Cypress commands are disallowed there.
cy.clock(mockNow.toJSDate()).then((clock) => {

// Confirm that Cloud manager polls the requests endpoint no more than
// once every 16 seconds.
mockGetEventsPolling([mockEvent], mockNowTimestamp).as('getEventsPoll');
Expand Down Expand Up @@ -196,7 +195,6 @@ describe('Event fetching and polling', () => {
// We need access to the `clock` object directly since we cannot call `cy.clock()` inside
// a `should(() => {})` callback because Cypress commands are disallowed there.
cy.clock(Date.now()).then((clock) => {

// Confirm that Cloud manager polls the requests endpoint no more than once
// every 2 seconds.
mockGetEventsPolling(mockEvents, mockNowTimestamp).as('getEventsPoll');
Expand Down
1 change: 0 additions & 1 deletion packages/manager/src/OAuth/oauth.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ describe('handleOAuthCallback', () => {
params: 'state=fakenonce&code=gyuwyutfetyfew',
})
).rejects.toThrowError('Request to POST /oauth/token was not ok.');

});

it('should throw if the /oauth/token response is not valid JSON', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ describe('Subnet form content', () => {
},
});

getByText('Subnets');
getByText('Subnet Label');
getByText('Subnet IP Address Range');
getByText('Add another Subnet');
expect(getByText('Subnets')).toBeVisible();
expect(getByText('Subnet Label')).toBeVisible();
expect(getByText('Subnet IP Address Range')).toBeVisible();
expect(getByText('Add another Subnet')).toBeVisible();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ describe('VPC Top Section form content', () => {
},
});

getByText('Region');
getByText('VPC Label');
getByText('Description');
expect(getByText('Region')).toBeVisible();
expect(getByText('VPC Label')).toBeVisible();
expect(getByText('Description')).toBeVisible();
});
});
20 changes: 10 additions & 10 deletions packages/manager/src/features/VPCs/VPCCreate/VPCCreate.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ vi.mock('@linode/utilities');

describe('VPC create page', () => {
it('should render the vpc and subnet sections', () => {
const { getAllByText } = renderWithTheme(<VPCCreate />);
const { getByText } = renderWithTheme(<VPCCreate />);

getAllByText('Region');
getAllByText('VPC Label');
getAllByText('Region');
getAllByText('Description');
getAllByText('Subnets');
getAllByText('Subnet Label');
getAllByText('Subnet IP Address Range');
getAllByText('Add another Subnet');
getAllByText('Create VPC');
expect(getByText('Region')).toBeVisible();
expect(getByText('VPC Label')).toBeVisible();
expect(getByText('Region')).toBeVisible();
expect(getByText('Description')).toBeVisible();
expect(getByText('Subnets')).toBeVisible();
expect(getByText('Subnet Label')).toBeVisible();
expect(getByText('Subnet IP Address Range')).toBeVisible();
expect(getByText('Add another Subnet')).toBeVisible();
expect(getByText('Create VPC')).toBeVisible();
});

it('should add and delete subnets correctly', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,21 @@ const formOptions = {

describe('VPC Create Drawer', () => {
it('should render the vpc and subnet sections', () => {
const { getAllByText } = renderWithThemeAndHookFormContext({
const { getByText, getByRole } = renderWithThemeAndHookFormContext({
component: <VPCCreateDrawer {...props} />,
useFormOptions: formOptions,
});

getAllByText('VPC Label');
getAllByText('Region');
getAllByText('Description');
getAllByText('Subnets');
getAllByText('Subnet Label');
getAllByText('Subnet IP Address Range');
getAllByText('Add another Subnet');
getAllByText('Cancel');
getAllByText('Create VPC');
expect(getByText('Region')).toBeVisible();
expect(getByText('VPC Label')).toBeVisible();
expect(getByText('Region')).toBeVisible();
expect(getByText('Description')).toBeVisible();
expect(getByText('Subnets')).toBeVisible();
expect(getByText('Subnet Label')).toBeVisible();
expect(getByText('Subnet IP Address Range')).toBeVisible();
expect(getByText('Add another Subnet')).toBeVisible();
expect(getByRole('button', { name: 'Create VPC' })).toBeVisible();
expect(getByText('Cancel')).toBeVisible();
});

it('should not be able to remove the first subnet', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { PointerEventsCheckLevel } from '@testing-library/user-event';
import * as React from 'react';

import { subnetFactory } from 'src/factories';
Expand All @@ -23,92 +24,96 @@ const props = {
};

describe('SubnetActionMenu', () => {
it('should render the subnet action menu', () => {
const screen = renderWithTheme(<SubnetActionMenu {...props} />);
const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
screen.getByText('Assign Linodes');
screen.getByText('Unassign Linodes');
screen.getByText('Edit');
screen.getByText('Delete');
it('should render the subnet action menu', async () => {
const view = renderWithTheme(<SubnetActionMenu {...props} />);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);
view.getByText('Assign Linodes');
view.getByText('Unassign Linodes');
view.getByText('Edit');
view.getByText('Delete');
});

it('should not allow the delete button to be clicked', () => {
const screen = renderWithTheme(<SubnetActionMenu {...props} />);
const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
it('should not allow the delete button to be clicked', async () => {
const view = renderWithTheme(<SubnetActionMenu {...props} />);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);

const deleteButton = screen.getByText('Delete');
fireEvent.click(deleteButton);
const deleteButton = view.getByRole('menuitem', { name: 'Delete' });
await userEvent.click(deleteButton, {
pointerEventsCheck: PointerEventsCheckLevel.Never,
});
expect(props.handleDelete).not.toHaveBeenCalled();
const tooltipText = screen.getByLabelText(
const tooltipText = view.getByLabelText(
'Linodes assigned to a subnet must be unassigned before the subnet can be deleted.'
);
expect(tooltipText).toBeInTheDocument();
});

it('should not allow the delete button to be clicked when isNodebalancerVPCEnabled is true', () => {
const screen = renderWithTheme(<SubnetActionMenu {...props} />, {
it('should not allow the delete button to be clicked when isNodebalancerVPCEnabled is true', async () => {
const view = renderWithTheme(<SubnetActionMenu {...props} />, {
flags: { nodebalancerVpc: true },
});

const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);

const deleteButton = screen.getByText('Delete');
fireEvent.click(deleteButton);
const deleteButton = view.getByText('Delete');
await userEvent.click(deleteButton, {
pointerEventsCheck: PointerEventsCheckLevel.Never,
});
expect(props.handleDelete).not.toHaveBeenCalled();
const tooltipText = screen.getByLabelText(
const tooltipText = view.getByLabelText(
'Resources assigned to a subnet must be unassigned before the subnet can be deleted.'
);
expect(tooltipText).toBeInTheDocument();
});

it('should allow the delete button to be clicked', () => {
const screen = renderWithTheme(
it('should allow the delete button to be clicked', async () => {
const view = renderWithTheme(
<SubnetActionMenu {...props} numLinodes={0} numNodebalancers={0} />
);
const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);

const deleteButton = screen.getByText('Delete');
fireEvent.click(deleteButton);
const deleteButton = view.getByText('Delete');
await userEvent.click(deleteButton);
expect(props.handleDelete).toHaveBeenCalled();
const tooltipText = screen.queryByLabelText(
const tooltipText = view.queryByLabelText(
'Linodes assigned to a subnet must be unassigned before the subnet can be deleted.'
);
expect(tooltipText).not.toBeInTheDocument();
});

it('should allow the edit button to be clicked', () => {
const screen = renderWithTheme(
it('should allow the edit button to be clicked', async () => {
const view = renderWithTheme(
<SubnetActionMenu {...props} numLinodes={0} numNodebalancers={0} />
);
const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);

const editButton = screen.getByText('Edit');
fireEvent.click(editButton);
const editButton = view.getByText('Edit');
await userEvent.click(editButton);
expect(props.handleEdit).toHaveBeenCalled();
});

it('should allow the Assign Linodes button to be clicked', () => {
const screen = renderWithTheme(<SubnetActionMenu {...props} />);
const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
it('should allow the Assign Linodes button to be clicked', async () => {
const view = renderWithTheme(<SubnetActionMenu {...props} />);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);

const assignButton = screen.getByText('Assign Linodes');
fireEvent.click(assignButton);
const assignButton = view.getByText('Assign Linodes');
await userEvent.click(assignButton);
expect(props.handleAssignLinodes).toHaveBeenCalled();
});

it('should disable action buttons if isVPCLKEEnterpriseCluster is true', () => {
it('should disable action buttons if isVPCLKEEnterpriseCluster is true', async () => {
const updatedProps = { ...props, isVPCLKEEnterpriseCluster: true };
const screen = renderWithTheme(<SubnetActionMenu {...updatedProps} />);
const actionMenu = screen.getByLabelText(`Action menu for Subnet subnet-1`);
fireEvent.click(actionMenu);
const view = renderWithTheme(<SubnetActionMenu {...updatedProps} />);
const actionMenu = view.getByLabelText(`Action menu for Subnet subnet-1`);
await userEvent.click(actionMenu);

const actionButtons = screen.getAllByRole('menuitem');
const actionButtons = view.getAllByRole('menuitem');
actionButtons.forEach((button) =>
expect(button).toHaveAttribute('aria-disabled', 'true')
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { linodeFactory } from '@linode/utilities';
import { fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import * as React from 'react';

import { firewallSettingsFactory } from 'src/factories';
import { makeResourcePage } from 'src/mocks/serverHandlers';
import { http, HttpResponse, server } from 'src/mocks/testServer';
import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers';
Expand All @@ -12,6 +13,18 @@ import type { Subnet } from '@linode/api-v4';

beforeAll(() => mockMatchMedia());

const queryMocks = vi.hoisted(() => ({
useFirewallSettingsQuery: vi.fn().mockReturnValue({}),
}));

vi.mock('@linode/queries', async () => {
const actual = await vi.importActual('@linode/queries');
return {
...actual,
useFirewallSettingsQuery: queryMocks.useFirewallSettingsQuery,
};
});

const props = {
isFetching: false,
onClose: vi.fn(),
Expand All @@ -20,6 +33,10 @@ const props = {
id: 1,
ipv4: '10.0.0.0/24',
label: 'subnet-1',
linodes: [],
nodebalancers: [],
created: '',
updated: '',
} as Subnet,
vpcId: 1,
vpcRegion: 'us-east',
Expand All @@ -38,7 +55,7 @@ describe('Subnet Assign Linodes Drawer', () => {
);

it('should render a subnet assign linodes drawer', () => {
const { getByTestId, getByText, queryAllByText } = renderWithTheme(
const { getByTestId, getByText } = renderWithTheme(
<SubnetAssignLinodesDrawer {...props} />
);

Expand All @@ -52,7 +69,7 @@ describe('Subnet Assign Linodes Drawer', () => {
`Select the Linodes you would like to assign to this subnet. Only Linodes in this VPC's region are displayed.`
);
expect(helperText).toBeVisible();
const linodeSelect = queryAllByText('Linode')[0];
const linodeSelect = getByTestId('add-linode-autocomplete');
expect(linodeSelect).toBeVisible();

const assignButton = getByText('Assign Linode');
Expand All @@ -65,33 +82,18 @@ describe('Subnet Assign Linodes Drawer', () => {
expect(doneButton).toBeVisible();
});

it.skip('should show the IPv4 textbox when the checkmark is clicked', async () => {

@coliu-akamai coliu-akamai Jun 27, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ended up removing this test: it's been skipped for some time (see here). I also tried making it work (tried mocking data, confirmed that the option we were trying to select existed, but had trouble actually selecting that option when using userEvent.selectOptions(....) ?).

Since there are several interactions in this test, it's prob more worth writing an integration test - will make a ticket

--> M3-10253

const { findByText, getByLabelText } = renderWithTheme(
<SubnetAssignLinodesDrawer {...props} />
);

const selectField = getByLabelText('Linode');
fireEvent.change(selectField, { target: { value: 'this-linode' } });

const checkbox = await findByText(
'Auto-assign a VPC IPv4 address for this Linode'
);

await waitFor(() => expect(checkbox).toBeVisible());
fireEvent.click(checkbox);

const ipv4Textbox = await findByText('VPC IPv4');
await waitFor(() => expect(ipv4Textbox).toBeVisible());
});
it('should close the drawer', async () => {
queryMocks.useFirewallSettingsQuery.mockReturnValue({
data: firewallSettingsFactory.build(),
});

it('should close the drawer', () => {
const { getByText } = renderWithTheme(
<SubnetAssignLinodesDrawer {...props} />
);

const doneButton = getByText('Done');
expect(doneButton).toBeVisible();
fireEvent.click(doneButton);
await userEvent.click(doneButton);
expect(props.onClose).toHaveBeenCalled();
});
});
Loading