Skip to content

Commit 715b209

Browse files
authored
Automate "SSH key with passphrase configuration from the User Dashboard" test-case (#23643)
1 parent 510525d commit 715b209

File tree

3 files changed

+138
-7
lines changed

3 files changed

+138
-7
lines changed

tests/e2e/constants/FACTORY_TEST_CONSTANTS.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const FACTORY_TEST_CONSTANTS: {
3232
TS_GIT_PERSONAL_ACCESS_TOKEN: string;
3333
TS_SELENIUM_SSH_PRIVATE_KEY: string;
3434
TS_SELENIUM_SSH_PUBLIC_KEY: string;
35+
TS_SELENIUM_SSH_KEY_PASSPHRASE: string;
3536
TS_SELENIUM_FACTORY_URL(): string;
3637
} = {
3738
/**
@@ -90,15 +91,20 @@ export const FACTORY_TEST_CONSTANTS: {
9091
TS_GIT_PERSONAL_ACCESS_TOKEN: process.env.TS_GIT_PERSONAL_ACCESS_TOKEN || '',
9192

9293
/**
93-
* sSH private key as string (from environment variable)
94+
* ssh private key as string (from environment variable)
9495
*/
9596
TS_SELENIUM_SSH_PRIVATE_KEY: process.env.TS_SELENIUM_SSH_PRIVATE_KEY || '',
9697

9798
/**
98-
* sSH public key as string (from environment variable)
99+
* ssh public key as string (from environment variable)
99100
*/
100101
TS_SELENIUM_SSH_PUBLIC_KEY: process.env.TS_SELENIUM_SSH_PUBLIC_KEY || '',
101102

103+
/**
104+
* ssh key passphrase as string (from environment variable)
105+
*/
106+
TS_SELENIUM_SSH_KEY_PASSPHRASE: process.env.TS_SELENIUM_SSH_KEY_PASSPHRASE || '',
107+
102108
/**
103109
* full factory URL
104110
*/

tests/e2e/pageobjects/dashboard/UserPreferences.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export class UserPreferences {
4242
private static readonly ADD_SSH_KEYS_POPUP: By = By.xpath('//span[text()="Add SSH Keys"]');
4343
private static readonly PASTE_PRIVATE_SSH_KEY_FIELD: By = By.css('textarea[name="ssh-private-key"]');
4444
private static readonly PASTE_PUBLIC_SSH_KEY_FIELD: By = By.css('textarea[name="ssh-public-key"]');
45+
private static readonly PASTE_SSH_KEY_PASSPHRASE_FIELD: By = By.xpath('//input[@placeholder="Enter passphrase (optional)"]');
4546
private static readonly ADD_SSH_KEYS_BUTTON: By = By.css('.pf-c-button.pf-m-primary');
4647
private static readonly GIT_SSH_KEY_NAME: By = By.css('[data-testid="title"]');
4748
private static readonly GIT_SSH_KEY_ACTIONS_BUTTON: By = By.css('section[id*="SshKeys-user-preferences"] button[aria-label="Actions"]');
@@ -184,7 +185,7 @@ export class UserPreferences {
184185
Logger.info('SSH keys have been added');
185186
}
186187

187-
async addSshKeysFromStrings(privateSshKey: string, publicSshKey: string): Promise<void> {
188+
async addSshKeysFromStrings(privateSshKey: string, publicSshKey: string, passphrase?: string): Promise<void> {
188189
Logger.debug();
189190

190191
if (!privateSshKey || privateSshKey === '') {
@@ -206,6 +207,12 @@ export class UserPreferences {
206207
await this.driverHelper.waitAndClick(UserPreferences.PASTE_PUBLIC_SSH_KEY_FIELD);
207208
await this.driverHelper.getAction().sendKeys(publicSshKey).perform();
208209

210+
if (passphrase) {
211+
Logger.info('Pasting SSH key passphrase');
212+
await this.driverHelper.waitAndClick(UserPreferences.PASTE_SSH_KEY_PASSPHRASE_FIELD);
213+
await this.driverHelper.getAction().sendKeys(passphrase).perform();
214+
}
215+
209216
await this.driverHelper.waitAndClick(UserPreferences.ADD_SSH_KEYS_BUTTON);
210217
await this.driverHelper.waitVisibility(UserPreferences.GIT_SSH_KEY_NAME);
211218
Logger.info('SSH keys have been added');

tests/e2e/specs/factory/SshUrlNoOauthPatFactory.spec.ts

Lines changed: 122 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* SPDX-License-Identifier: EPL-2.0
99
**********************************************************************/
1010

11-
import { ViewSection } from 'monaco-page-objects';
11+
import { ActivityBar, ContextMenu, Key, Locators, NewScmView, SingleScmProvider, ViewControl, ViewSection } from 'monaco-page-objects';
1212
import { ProjectAndFileTests } from '../../tests-library/ProjectAndFileTests';
1313
import { CLASSES, TYPES } from '../../configs/inversify.types';
1414
import { e2eContainer } from '../../configs/inversify.config';
@@ -24,23 +24,45 @@ import { UserPreferences } from '../../pageobjects/dashboard/UserPreferences';
2424
import { Dashboard } from '../../pageobjects/dashboard/Dashboard';
2525
import { ITestWorkspaceUtil } from '../../utils/workspace/ITestWorkspaceUtil';
2626
import { Logger } from '../../utils/Logger';
27+
import { DriverHelper } from '../../utils/DriverHelper';
28+
import { CheCodeLocatorLoader } from '../../pageobjects/ide/CheCodeLocatorLoader';
29+
import { ViewsMoreActionsButton } from '../../pageobjects/ide/ViewsMoreActionsButton';
30+
import { SourceControlView } from '../../pageobjects/ide/SourceControlView';
2731

2832
suite(`The SshUrlNoOauthPatFactory userstory ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void {
2933
const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests);
3034
const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests);
3135
const loginTests: LoginTests = e2eContainer.get(CLASSES.LoginTests);
3236
const browserTabsUtil: BrowserTabsUtil = e2eContainer.get(CLASSES.BrowserTabsUtil);
3337
const userPreferences: UserPreferences = e2eContainer.get(CLASSES.UserPreferences);
38+
const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper);
3439
const dashboard: Dashboard = e2eContainer.get(CLASSES.Dashboard);
3540
const testWorkspaceUtil: ITestWorkspaceUtil = e2eContainer.get(TYPES.WorkspaceUtil);
41+
const cheCodeLocatorLoader: CheCodeLocatorLoader = e2eContainer.get(CLASSES.CheCodeLocatorLoader);
42+
const viewsMoreActionsButton: ViewsMoreActionsButton = e2eContainer.get(CLASSES.ViewsMoreActionsButton);
43+
const sourceControlView: SourceControlView = e2eContainer.get(CLASSES.SourceControlView);
44+
const webCheCodeLocators: Locators = cheCodeLocatorLoader.webCheCodeLocators;
45+
3646
const factoryUrl: string =
3747
FACTORY_TEST_CONSTANTS.TS_SELENIUM_FACTORY_GIT_REPO_URL ||
3848
'ssh://[email protected]/~admin/private-bb-repo.git';
3949
const privateSshKey: string = FACTORY_TEST_CONSTANTS.TS_SELENIUM_SSH_PRIVATE_KEY;
4050
const publicSshKey: string = FACTORY_TEST_CONSTANTS.TS_SELENIUM_SSH_PUBLIC_KEY;
51+
const sshPassphrase: string = FACTORY_TEST_CONSTANTS.TS_SELENIUM_SSH_KEY_PASSPHRASE;
4152
const privateSshKeyPath: string = FACTORY_TEST_CONSTANTS.TS_SELENIUM_SSH_PRIVATE_KEY_PATH;
4253
const publicSshKeyPath: string = FACTORY_TEST_CONSTANTS.TS_SELENIUM_SSH_PUBLIC_KEY_PATH;
54+
4355
let projectSection: ViewSection;
56+
let scmProvider: SingleScmProvider;
57+
let scmContextMenu: ContextMenu;
58+
let viewsActionsButton: boolean;
59+
// test specific data
60+
const timeToRefresh: number = 1500;
61+
const changesToCommit: string = 'Commit ' + new Date().getTime().toString();
62+
const fileToChange: string = 'Date.txt';
63+
const refreshButtonLabel: string = 'Refresh';
64+
const pushItemLabel: string = 'Push';
65+
let testRepoProjectName: string;
4466

4567
async function deleteSshKeys(): Promise<void> {
4668
Logger.debug('Deleting SSH keys if they are present');
@@ -62,7 +84,7 @@ suite(`The SshUrlNoOauthPatFactory userstory ${BASE_TEST_CONSTANTS.TEST_ENVIRONM
6284
// use environment variables if available, otherwise fall back to file paths
6385
if (privateSshKey && publicSshKey) {
6486
Logger.info('Using SSH keys from environment variables');
65-
await userPreferences.addSshKeysFromStrings(privateSshKey, publicSshKey);
87+
await userPreferences.addSshKeysFromStrings(privateSshKey, publicSshKey, sshPassphrase);
6688
} else {
6789
Logger.info('Using SSH keys from file paths');
6890
await userPreferences.addSshKeysFromFiles(privateSshKeyPath, publicSshKeyPath);
@@ -87,19 +109,115 @@ suite(`The SshUrlNoOauthPatFactory userstory ${BASE_TEST_CONSTANTS.TEST_ENVIRONM
87109
.undefined;
88110
});
89111
test('Accept the project as a trusted one', async function (): Promise<void> {
90-
await projectAndFileTests.performTrustAuthorDialog();
112+
await projectAndFileTests.performTrustDialogs();
113+
// it needs to wait here for the Trust dialogs to be closed and the Editor to be ready
114+
await driverHelper.wait(5000);
91115
});
92116
test('Check the project files was imported', async function (): Promise<void> {
93117
expect(
94118
await projectAndFileTests.getProjectTreeItem(projectSection, BASE_TEST_CONSTANTS.TS_SELENIUM_PROJECT_ROOT_FILE_NAME),
95119
'Project files were not imported'
96120
).not.undefined;
121+
testRepoProjectName = StringUtil.getProjectNameFromGitUrl(factoryUrl);
122+
});
123+
124+
test('Make changes to the file', async function (): Promise<void> {
125+
Logger.debug(`projectSection.openItem: "${fileToChange}"`);
126+
await projectSection.openItem(testRepoProjectName, fileToChange);
127+
await driverHelper.waitVisibility(webCheCodeLocators.Editor.inputArea);
128+
await driverHelper.getDriver().findElement(webCheCodeLocators.Editor.inputArea).click();
129+
await driverHelper.wait(1000);
130+
131+
Logger.debug('Clearing the editor with Ctrl+A');
132+
await driverHelper.getDriver().actions().keyDown(Key.CONTROL).sendKeys('a').keyUp(Key.CONTROL).perform();
133+
await driverHelper.wait(1000);
134+
Logger.debug('Deleting selected text');
135+
await driverHelper.getDriver().actions().sendKeys(Key.DELETE).perform();
136+
await driverHelper.wait(1000);
137+
Logger.debug(`Entering text: "${changesToCommit}"`);
138+
await driverHelper.getDriver().actions().sendKeys(changesToCommit).perform();
139+
});
140+
141+
test('Open a source control manager', async function (): Promise<void> {
142+
const viewSourceControl: string = 'Source Control';
143+
const sourceControl: ViewControl = (await new ActivityBar().getViewControl(viewSourceControl)) as ViewControl;
144+
Logger.debug(`sourceControl.openView: "${viewSourceControl}"`);
145+
await sourceControl.openView();
146+
const scmView: NewScmView = new NewScmView();
147+
await driverHelper.waitVisibility(webCheCodeLocators.ScmView.inputField);
148+
let rest: SingleScmProvider[];
149+
[scmProvider, ...rest] = await scmView.getProviders();
150+
Logger.debug(`scmView.getProviders: "${JSON.stringify(scmProvider)}, ${rest}"`);
151+
});
152+
153+
test('Check if the changes are displayed in the source control manager', async function (): Promise<void> {
154+
await driverHelper.waitVisibility(webCheCodeLocators.ScmView.more);
155+
await driverHelper.wait(timeToRefresh);
156+
Logger.debug(`wait and click on: "${refreshButtonLabel}"`);
157+
await driverHelper.waitAndClick(webCheCodeLocators.ScmView.actionConstructor(refreshButtonLabel));
158+
// wait while changes counter will be refreshed
159+
await driverHelper.wait(timeToRefresh);
160+
const changes: number = await scmProvider.getChangeCount();
161+
Logger.debug(`scmProvider.getChangeCount: number of changes is "${changes}"`);
162+
expect(changes).eql(1);
97163
});
164+
165+
test('Stage the changes', async function (): Promise<void> {
166+
await driverHelper.waitVisibility(webCheCodeLocators.ScmView.more);
167+
viewsActionsButton = await viewsMoreActionsButton.viewsAndMoreActionsButtonIsVisible();
168+
if (viewsActionsButton) {
169+
await viewsMoreActionsButton.closeSourceControlGraph();
170+
}
171+
scmContextMenu = await scmProvider.openMoreActions();
172+
await driverHelper.waitVisibility(webCheCodeLocators.ContextMenu.contextView);
173+
Logger.debug('scmContextMenu.select: "Changes" -> "Stage All Changes"');
174+
await scmContextMenu.select('Changes', 'Stage All Changes');
175+
});
176+
177+
test('Commit the changes', async function (): Promise<void> {
178+
Logger.info(`ScmView inputField locator: "${(webCheCodeLocators.ScmView as any).scmEditor}"`);
179+
Logger.debug('Click on the Scm Editor');
180+
await driverHelper
181+
.getDriver()
182+
.findElement((webCheCodeLocators.ScmView as any).scmEditor)
183+
.click();
184+
await sourceControlView.typeCommitMessage(changesToCommit);
185+
await driverHelper.waitVisibility(webCheCodeLocators.ScmView.more);
186+
await driverHelper.wait(timeToRefresh);
187+
Logger.debug(`wait and click on: "${refreshButtonLabel}"`);
188+
await driverHelper.waitAndClick(webCheCodeLocators.ScmView.actionConstructor(refreshButtonLabel));
189+
// wait while changes counter will be refreshed
190+
await driverHelper.wait(timeToRefresh);
191+
const changes: number = await scmProvider.getChangeCount();
192+
Logger.debug(`scmProvider.getChangeCount: number of changes is "${changes}"`);
193+
expect(changes).eql(0);
194+
});
195+
196+
test('Push the changes and check if the changes were pushed', async function (): Promise<void> {
197+
await driverHelper.waitVisibility(webCheCodeLocators.Notification.action);
198+
await driverHelper.waitVisibility(webCheCodeLocators.ScmView.more);
199+
Logger.debug('scmProvider.openMoreActions');
200+
scmContextMenu = await scmProvider.openMoreActions();
201+
await driverHelper.waitVisibility(webCheCodeLocators.ContextMenu.itemConstructor(pushItemLabel));
202+
Logger.debug(`scmContextMenu.select: "${pushItemLabel}"`);
203+
await scmContextMenu.select(pushItemLabel);
204+
205+
await driverHelper.waitVisibility(webCheCodeLocators.ScmView.more);
206+
await driverHelper.wait(timeToRefresh);
207+
Logger.debug(`wait and click on: "${refreshButtonLabel}"`);
208+
await driverHelper.waitAndClick(webCheCodeLocators.ScmView.actionConstructor(refreshButtonLabel));
209+
const isCommitButtonDisabled: string = await driverHelper.waitAndGetElementAttribute(
210+
webCheCodeLocators.Notification.action,
211+
'aria-disabled'
212+
);
213+
expect(isCommitButtonDisabled).to.equal('true');
214+
});
215+
98216
suiteTeardown('Delete SSH keys', async function (): Promise<void> {
99217
await dashboard.openDashboard();
100218
await deleteSshKeys();
101219
});
102-
suiteTeardown('Stop and delete the workspace by APII', async function (): Promise<void> {
220+
suiteTeardown('Stop and delete the workspace by API', async function (): Promise<void> {
103221
await browserTabsUtil.closeAllTabsExceptCurrent();
104222
await testWorkspaceUtil.stopAndDeleteWorkspaceByName(WorkspaceHandlingTests.getWorkspaceName());
105223
});

0 commit comments

Comments
 (0)