Skip to content

Commit aa61195

Browse files
committed
refactor(Cypress): Splitting commands.ts
support/commands.ts - split into multiple files in a new commands dir that group the commands based on their purpose. support/nav.ts - integrated under the commands/utils.ts command
1 parent 3f9afde commit aa61195

8 files changed

Lines changed: 786 additions & 738 deletions

File tree

web/cypress/support/commands.ts

Lines changed: 0 additions & 711 deletions
This file was deleted.
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import { guidedTour } from '../../views/tour';
2+
import { nav } from '../../views/nav';
3+
4+
5+
6+
export {};
7+
declare global {
8+
namespace Cypress {
9+
interface Chainable {
10+
switchPerspective(perspective: string);
11+
uiLogin(provider: string, username: string, password: string, oauthurl?: string);
12+
uiLogout();
13+
cliLogin(username?, password?, hostapi?);
14+
cliLogout();
15+
login(provider?: string, username?: string, password?: string, oauthurl?: string): Chainable<Element>;
16+
adminCLI(command: string, options?);
17+
executeAndDelete(command: string);
18+
}
19+
}
20+
}
21+
22+
23+
Cypress.Commands.add(
24+
'login',
25+
(
26+
provider: string = Cypress.env('LOGIN_IDP'),
27+
username: string = Cypress.env('LOGIN_USERNAME'),
28+
password: string = Cypress.env('LOGIN_PASSWORD'),
29+
oauthurl: string,
30+
) => {
31+
cy.session(
32+
[provider, username],
33+
() => {
34+
cy.visit(Cypress.config('baseUrl'));
35+
cy.log('Session - after visiting');
36+
cy.window().then(
37+
(
38+
win: any, // eslint-disable-line @typescript-eslint/no-explicit-any
39+
) => {
40+
// Check if auth is disabled (for a local development environment)
41+
if (win.SERVER_FLAGS?.authDisabled) {
42+
cy.task('log', ' skipping login, console is running with auth disabled');
43+
return;
44+
}
45+
cy.exec(
46+
`oc get node --selector=hypershift.openshift.io/managed --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`,
47+
).then((result) => {
48+
cy.log(result.stdout);
49+
cy.task('log', result.stdout);
50+
if (result.stdout.includes('Ready')) {
51+
cy.log(`Attempting login via cy.origin to: ${oauthurl}`);
52+
cy.task('log', `Attempting login via cy.origin to: ${oauthurl}`);
53+
cy.origin(
54+
oauthurl,
55+
{ args: { username, password } },
56+
({ username, password }) => {
57+
cy.get('#inputUsername').type(username);
58+
cy.get('#inputPassword').type(password);
59+
cy.get('button[type=submit]').click();
60+
},
61+
);
62+
} else {
63+
cy.task('log', ` Logging in as ${username} using fallback on ${oauthurl}`);
64+
cy.origin(
65+
oauthurl,
66+
{ args: { provider, username, password } },
67+
({ provider, username, password }) => {
68+
cy.get('[data-test-id="login"]').should('be.visible');
69+
cy.get('body').then(($body) => {
70+
if ($body.text().includes(provider)) {
71+
cy.contains(provider).should('be.visible').click();
72+
}
73+
});
74+
cy.get('#inputUsername').type(username);
75+
cy.get('#inputPassword').type(password);
76+
cy.get('button[type=submit]').click();
77+
}
78+
);
79+
}
80+
});
81+
},
82+
);
83+
},
84+
{
85+
cacheAcrossSpecs: true,
86+
validate() {
87+
cy.byTestID("username", {timeout: 120000}).should('be.visible');
88+
guidedTour.close();
89+
},
90+
},
91+
);
92+
},
93+
);
94+
95+
Cypress.Commands.add('switchPerspective', (perspective: string) => {
96+
/* If side bar is collapsed then expand it
97+
before switching perspecting */
98+
cy.get('body').then((body) => {
99+
if (body.find('.pf-m-collapsed').length > 0) {
100+
cy.get('#nav-toggle').click();
101+
}
102+
});
103+
nav.sidenav.switcher.changePerspectiveTo(perspective);
104+
nav.sidenav.switcher.shouldHaveText(perspective);
105+
});
106+
107+
// To avoid influence from upstream login change
108+
Cypress.Commands.add('uiLogin', (provider: string, username: string, password: string) => {
109+
cy.log('Commands uiLogin');
110+
cy.clearCookie('openshift-session-token');
111+
cy.visit('/');
112+
cy.window().then(
113+
(
114+
win: any, // eslint-disable-line @typescript-eslint/no-explicit-any
115+
) => {
116+
if (win.SERVER_FLAGS?.authDisabled) {
117+
cy.task('log', 'Skipping login, console is running with auth disabled');
118+
return;
119+
}
120+
cy.get('[data-test-id="login"]').should('be.visible');
121+
cy.get('body').then(($body) => {
122+
if ($body.text().includes(provider)) {
123+
cy.contains(provider).should('be.visible').click();
124+
} else if ($body.find('li.idp').length > 0) {
125+
//Using the last idp if doesn't provider idp name
126+
cy.get('li.idp').last().click();
127+
}
128+
});
129+
cy.get('#inputUsername').type(username);
130+
cy.get('#inputPassword').type(password);
131+
cy.get('button[type=submit]').click();
132+
cy.byTestID('username', { timeout: 120000 }).should('be.visible');
133+
},
134+
);
135+
cy.switchPerspective('Administrator');
136+
});
137+
138+
Cypress.Commands.add('uiLogout', () => {
139+
cy.window().then(
140+
(
141+
win: any, // eslint-disable-line @typescript-eslint/no-explicit-any
142+
) => {
143+
if (win.SERVER_FLAGS?.authDisabled) {
144+
cy.log('Skipping logout, console is running with auth disabled');
145+
return;
146+
}
147+
cy.log('Log out UI');
148+
cy.byTestID('username').click();
149+
cy.byTestID('log-out').should('be.visible');
150+
cy.byTestID('log-out').click({ force: true });
151+
},
152+
);
153+
});
154+
155+
Cypress.Commands.add('cliLogin', (username?, password?, hostapi?) => {
156+
const loginUsername = username || Cypress.env('LOGIN_USERNAME');
157+
const loginPassword = password || Cypress.env('LOGIN_PASSWORD');
158+
const hostapiurl = hostapi || Cypress.env('HOST_API');
159+
cy.exec(
160+
`oc login -u ${loginUsername} -p ${loginPassword} ${hostapiurl} --insecure-skip-tls-verify=true`,
161+
{ failOnNonZeroExit: false },
162+
).then((result) => {
163+
cy.log(result.stderr);
164+
cy.log(result.stdout);
165+
});
166+
});
167+
168+
Cypress.Commands.add('cliLogout', () => {
169+
cy.exec(`oc logout`, { failOnNonZeroExit: false }).then((result) => {
170+
cy.log(result.stderr);
171+
cy.log(result.stdout);
172+
});
173+
});
174+
175+
Cypress.Commands.add('adminCLI', (command: string) => {
176+
const kubeconfig = Cypress.env('KUBECONFIG_PATH');
177+
cy.log(`Run admin command: ${command}`);
178+
cy.exec(`${command} --kubeconfig ${kubeconfig}`);
179+
});
180+
181+
Cypress.Commands.add('executeAndDelete', (command: string) => {
182+
cy.exec(command, { failOnNonZeroExit: false })
183+
.then(result => {
184+
if (result.code !== 0) {
185+
cy.task('logError', `Command "${command}" failed: ${result.stderr || result.stdout}`);
186+
} else {
187+
cy.task('log', `Command "${command}" executed successfully`);
188+
}
189+
});
190+
});
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
export {};
2+
3+
declare global {
4+
namespace Cypress {
5+
interface Chainable {
6+
createKubePodCrashLoopingAlert(): Chainable<string>;
7+
cleanupIncidentPrometheusRules(): Chainable<Element>;
8+
}
9+
}
10+
}
11+
12+
13+
// Apply incident fixture manifests to the cluster
14+
Cypress.Commands.add('createKubePodCrashLoopingAlert', () => {
15+
const kubeconfigPath = Cypress.env('KUBECONFIG_PATH');
16+
17+
// Generate a random alert name for this test run
18+
const randomAlertName = `CustomPodCrashLooping_${Math.random().toString(36).substring(2, 15)}`;
19+
20+
// Store the alert name globally so tests can access it
21+
Cypress.env('CURRENT_ALERT_NAME', randomAlertName);
22+
23+
cy.log(`Generated random alert name: ${randomAlertName}`);
24+
25+
// Read the template and replace the placeholder
26+
cy.readFile('./cypress/fixtures/incidents/prometheus_rule_pod_crash_loop.yaml').then((template) => {
27+
const yamlContent = template.replace(/\{\{ALERT_NAME\}\}/g, randomAlertName);
28+
29+
// Write the modified YAML to a temporary file
30+
cy.writeFile('./cypress/fixtures/incidents/temp_prometheus_rule.yaml', yamlContent).then(() => {
31+
// Apply the modified YAML
32+
cy.exec(
33+
`oc apply -f ./cypress/fixtures/incidents/temp_prometheus_rule.yaml --kubeconfig ${kubeconfigPath}`,
34+
);
35+
36+
// Clean up temporary file
37+
cy.exec('rm ./cypress/fixtures/incidents/temp_prometheus_rule.yaml');
38+
});
39+
});
40+
41+
cy.exec(
42+
`oc apply -f ./cypress/fixtures/incidents/pod_crash_loop.yaml --kubeconfig ${kubeconfigPath}`,
43+
);
44+
45+
// Return the alert name for the test to use
46+
return cy.wrap(randomAlertName);
47+
});
48+
49+
// Clean up incident fixture manifests from the cluster
50+
Cypress.Commands.add('cleanupIncidentPrometheusRules', () => {
51+
const kubeconfigPath = Cypress.env('KUBECONFIG_PATH');
52+
53+
// Delete all PrometheusRules that match our pattern (kubernetes-monitoring-podcrash-rules)
54+
// This ensures cleanup before tests and after tests
55+
cy.exec(
56+
`oc delete prometheusrule kubernetes-monitoring-podcrash-rules -n openshift-monitoring --kubeconfig ${kubeconfigPath} --ignore-not-found=true`,
57+
);
58+
59+
// Clear the environment variable if it exists
60+
if (Cypress.env('CURRENT_ALERT_NAME')) {
61+
Cypress.env('CURRENT_ALERT_NAME', null);
62+
}
63+
64+
cy.executeAndDelete(
65+
`oc delete -f ./cypress/fixtures/incidents/pod_crash_loop.yaml --ignore-not-found=true --kubeconfig ${kubeconfigPath}`,
66+
);
67+
});
68+

0 commit comments

Comments
 (0)