Skip to content

Commit 38e5b76

Browse files
test: [DPS-34824] - Add cypress tests for logs destinations (linode#12936)
* test: [DPS-34824] - Add cypress tests for logs destinations
1 parent 8630f39 commit 38e5b76

File tree

21 files changed

+730
-10
lines changed

21 files changed

+730
-10
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Tests
3+
---
4+
5+
Add Logs Destination Landing, Create and Edit e2e tests ([#12936](https://github.com/linode/manager/pull/12936))
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import {
2+
mockDestination,
3+
mockDestinationPayload,
4+
} from 'support/constants/delivery';
5+
import {
6+
mockCreateDestination,
7+
mockGetDestinations,
8+
mockTestConnection,
9+
} from 'support/intercepts/delivery';
10+
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
11+
import { ui } from 'support/ui';
12+
import { logsDestinationForm } from 'support/ui/pages/logs-destination-form';
13+
14+
import type { AkamaiObjectStorageDetails } from '@linode/api-v4';
15+
16+
describe('Create Destination', () => {
17+
before(() => {
18+
mockAppendFeatureFlags({
19+
aclpLogs: { enabled: true, beta: true },
20+
});
21+
});
22+
23+
it('create destination with form', () => {
24+
cy.visitWithLogin('/logs/delivery/destinations/create');
25+
26+
// Give Destination a label
27+
logsDestinationForm.setLabel(mockDestinationPayload.label);
28+
29+
logsDestinationForm.fillDestinationDetailsForm(
30+
mockDestinationPayload.details as AkamaiObjectStorageDetails
31+
);
32+
33+
// Create Destination should be disabled before test connection
34+
cy.findByRole('button', { name: 'Create Destination' }).should(
35+
'be.disabled'
36+
);
37+
38+
// Test connection of the destination form - failure
39+
mockTestConnection(400);
40+
ui.button
41+
.findByTitle('Test Connection')
42+
.should('be.enabled')
43+
.should('have.attr', 'type', 'button')
44+
.click();
45+
46+
ui.toast.assertMessage(
47+
'Delivery connection test failed. Verify your delivery settings and try again.'
48+
);
49+
50+
// Create Destination should be disabled after test connection failed
51+
cy.findByRole('button', { name: 'Create Destination' }).should(
52+
'be.disabled'
53+
);
54+
55+
// Test connection of the destination form - success
56+
mockTestConnection(200);
57+
ui.button
58+
.findByTitle('Test Connection')
59+
.should('be.enabled')
60+
.should('have.attr', 'type', 'button')
61+
.click();
62+
63+
ui.toast.assertMessage(
64+
`Delivery connection test completed successfully. Data can now be sent using this configuration.`
65+
);
66+
67+
// Submit the destination create form - failure
68+
mockCreateDestination({}, 400);
69+
cy.findByRole('button', { name: 'Create Destination' })
70+
.should('be.enabled')
71+
.should('have.attr', 'type', 'button')
72+
.click();
73+
74+
ui.toast.assertMessage(`There was an issue creating your destination`);
75+
76+
// Submit the destination create form - success
77+
mockCreateDestination(mockDestination);
78+
mockGetDestinations([mockDestination]);
79+
cy.findByRole('button', { name: 'Create Destination' })
80+
.should('be.enabled')
81+
.should('have.attr', 'type', 'button')
82+
.click();
83+
84+
ui.toast.assertMessage(
85+
`Destination ${mockDestination.label} created successfully`
86+
);
87+
88+
// Verify we redirect to the destinations landing page upon successful creation
89+
cy.url().should('endWith', 'destinations');
90+
91+
// Verify the newly created destination shows on the Destinations landing page
92+
cy.findByText(mockDestination.label)
93+
.closest('tr')
94+
.within(() => {
95+
// Verify Destination label shows
96+
cy.findByText(mockDestination.label).should('be.visible');
97+
});
98+
});
99+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { mockGetDestinations } from 'support/intercepts/delivery';
2+
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
3+
import { ui } from 'support/ui';
4+
5+
describe('Destinations empty landing page', () => {
6+
beforeEach(() => {
7+
mockAppendFeatureFlags({
8+
aclpLogs: {
9+
enabled: true,
10+
beta: true,
11+
},
12+
});
13+
});
14+
15+
/**
16+
* - Confirms Destinations landing page empty state is shown when no Destinations are present:
17+
* - Confirms that clicking "Create Destination" navigates user to create destination page.
18+
*/
19+
it('shows the empty state when there are no destinations', () => {
20+
mockGetDestinations([]).as('getDestinations');
21+
22+
cy.visitWithLogin('/logs/delivery/destinations');
23+
cy.wait(['@getDestinations']);
24+
25+
// Confirm empty Destinations Landing Text
26+
cy.findByText('Create a destination for cloud logs').should('be.visible');
27+
28+
// confirms clicking on 'Create Domain' button
29+
ui.button
30+
.findByTitle('Create Destination')
31+
.should('be.visible')
32+
.should('be.enabled')
33+
.click();
34+
35+
cy.url().should('endWith', '/logs/delivery/destinations/create');
36+
});
37+
});
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import {
2+
interceptDeleteDestination,
3+
mockDeleteDestination,
4+
mockGetDestination,
5+
mockGetDestinations,
6+
} from 'support/intercepts/delivery';
7+
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
8+
import { ui } from 'support/ui';
9+
10+
import { destinationFactory } from 'src/factories';
11+
12+
import type { Destination } from '@linode/api-v4';
13+
14+
function checkActionMenu(tableAlias: string, mockDestinations: Destination[]) {
15+
mockDestinations.forEach((destination) => {
16+
cy.get(tableAlias)
17+
.find('tbody tr')
18+
.should('contain', destination.label)
19+
.then(() => {
20+
// If the row contains the label, proceed with clicking the action menu
21+
ui.actionMenu
22+
.findByTitle(`Action menu for Destination ${destination.label}`)
23+
.should('be.visible')
24+
.click();
25+
26+
// Check that all items are enabled
27+
ui.actionMenuItem
28+
.findByTitle('Edit')
29+
.should('be.visible')
30+
.should('be.enabled');
31+
32+
ui.actionMenuItem
33+
.findByTitle('Delete')
34+
.should('be.visible')
35+
.should('be.enabled');
36+
});
37+
38+
// Close the action menu by clicking on Delivery Title of the screen
39+
cy.get('body').click(0, 0);
40+
});
41+
}
42+
43+
function deleteItem(tableAlias: string, destination: Destination) {
44+
cy.get(tableAlias)
45+
.find('tbody tr')
46+
.should('contain', destination.label)
47+
.then(() => {
48+
// If the row contains the label, proceed with clicking the action menu
49+
ui.actionMenu
50+
.findByTitle(`Action menu for Destination ${destination.label}`)
51+
.should('be.visible')
52+
.click();
53+
54+
mockDeleteDestination(404); // @TODO remove after API release on prod
55+
interceptDeleteDestination().as('deleteDestination');
56+
57+
// Delete destination
58+
ui.actionMenuItem.findByTitle('Delete').click();
59+
60+
// Find confirmation modal
61+
cy.findByText(
62+
`Are you sure you want to delete "${destination.label}" destination?`
63+
);
64+
ui.button.findByTitle('Delete').click();
65+
66+
cy.wait('@deleteDestination');
67+
68+
// Close confirmation modal after failure
69+
ui.button.findByTitle('Cancel').click();
70+
});
71+
}
72+
73+
function editItemViaActionMenu(tableAlias: string, destination: Destination) {
74+
cy.get(tableAlias)
75+
.find('tbody tr')
76+
.should('contain', destination.label)
77+
.then(() => {
78+
// If the row contains the label, proceed with clicking the action menu
79+
ui.actionMenu
80+
.findByTitle(`Action menu for Destination ${destination.label}`)
81+
.should('be.visible')
82+
.click();
83+
84+
mockGetDestination(destination);
85+
// Edit destination redirect
86+
ui.actionMenuItem.findByTitle('Edit').click();
87+
cy.url().should('endWith', `/destinations/${destination.id}/edit`);
88+
});
89+
}
90+
91+
const mockDestinations: Destination[] = new Array(3)
92+
.fill(null)
93+
.map((_item: null, index: number): Destination => {
94+
return destinationFactory.build({
95+
label: `Destination ${index}`,
96+
});
97+
});
98+
99+
describe('destinations landing checks for non-empty state', () => {
100+
beforeEach(() => {
101+
mockAppendFeatureFlags({
102+
aclpLogs: { enabled: true, beta: true },
103+
});
104+
105+
// Mock setup to display the Destinations landing page in a non-empty state
106+
mockGetDestinations(mockDestinations).as('getDestinations');
107+
108+
// Alias the mockDestinations array
109+
cy.wrap(mockDestinations).as('mockDestinations');
110+
});
111+
112+
it('checks create destination button is enabled and user can see existing destinations', () => {
113+
// Login and wait for application to load
114+
cy.visitWithLogin('/logs/delivery/destinations');
115+
cy.wait('@getDestinations');
116+
cy.url().should('endWith', '/destinations');
117+
118+
cy.get('table').should('exist').as('destinationsTable');
119+
120+
// Assert that Create Destination button is visible and enabled
121+
ui.button
122+
.findByTitle('Create Destination')
123+
.should('be.visible')
124+
.and('be.enabled');
125+
126+
// Assert that the correct number of Destinations entries are present in the DestinationsTable
127+
cy.get('@destinationsTable')
128+
.find('tbody tr')
129+
.should('have.length', mockDestinations.length);
130+
131+
checkActionMenu('@destinationsTable', mockDestinations); // For the recovery destination table
132+
});
133+
134+
it('checks actions from destination menu actions', () => {
135+
cy.visitWithLogin('/logs/delivery/destinations');
136+
cy.wait('@getDestinations');
137+
cy.get('table').should('exist').as('destinationsTable');
138+
139+
const exampleDestination = mockDestinations[0];
140+
deleteItem('@destinationsTable', exampleDestination);
141+
142+
mockGetDestination(exampleDestination).as('getDestination');
143+
144+
// Redirect to destination edit page via name
145+
cy.findByText(exampleDestination.label).click();
146+
cy.url().should('endWith', `/destinations/${exampleDestination.id}/edit`);
147+
cy.wait('@getDestination');
148+
149+
cy.visit('/logs/delivery/destinations');
150+
cy.get('table').should('exist').as('destinationsTable');
151+
cy.wait('@getDestinations');
152+
editItemViaActionMenu('@destinationsTable', exampleDestination);
153+
});
154+
});

0 commit comments

Comments
 (0)