-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extending e2e graphical happy path scenario (#1353)
* chore(test): implementing happy-path graphical test flow Signed-off-by: Tibor Dancs <[email protected]> * chore(test): refactoring ai-lab-page.ts Signed-off-by: Tibor Dancs <[email protected]> * chore(test): pr-review - update button locators to use getByRole 'link' Signed-off-by: Tibor Dancs <[email protected]> * chore(test): pr-review - implemented ai-lab-base-page.ts, refactored ai-lab-app-details-page.ts Signed-off-by: Tibor Dancs <[email protected]> * chore(test): pr-review - fixing thisdot Signed-off-by: Tibor Dancs <[email protected]> * chore(test): pr-review - fixing base page abstraction Signed-off-by: Tibor Dancs <[email protected]> --------- Signed-off-by: Tibor Dancs <[email protected]>
- Loading branch information
Showing
7 changed files
with
346 additions
and
10 deletions.
There are no files selected for viewing
This file contains 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 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 |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/********************************************************************** | ||
* Copyright (C) 2024 Red Hat, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
***********************************************************************/ | ||
|
||
import { expect as playExpect } from '@playwright/test'; | ||
import type { Locator, Page } from '@playwright/test'; | ||
import { AILabBasePage } from './ai-lab-base-page'; | ||
import { AILabStartRecipePage } from './ai-lab-start-recipe-page'; | ||
|
||
export class AILabAppDetailsPage extends AILabBasePage { | ||
readonly appName: string; | ||
readonly startRecipeButton: Locator; | ||
|
||
constructor(page: Page, webview: Page, appName: string) { | ||
super(page, webview, appName); | ||
this.appName = appName; | ||
this.startRecipeButton = this.webview.getByRole('button', { name: 'Start recipe' }); | ||
} | ||
|
||
async waitForLoad(): Promise<void> { | ||
await playExpect(this.heading).toBeVisible(); | ||
} | ||
|
||
async deleteLocalClone(): Promise<void> { | ||
throw new Error('Method Not implemented'); | ||
} | ||
|
||
async startNewDeployment(): Promise<void> { | ||
await playExpect(this.startRecipeButton).toBeEnabled(); | ||
await this.startRecipeButton.click(); | ||
const starRecipePage: AILabStartRecipePage = new AILabStartRecipePage(this.page, this.webview); | ||
await starRecipePage.waitForLoad(); | ||
await starRecipePage.startRecipe(); | ||
} | ||
|
||
async openRunningApps(): Promise<void> { | ||
throw new Error('Method Not implemented'); | ||
} | ||
|
||
async deleteRunningApp(_containerName: string): Promise<void> { | ||
throw new Error('Method Not implemented'); | ||
} | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/********************************************************************** | ||
* Copyright (C) 2024 Red Hat, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
***********************************************************************/ | ||
|
||
import type { Locator, Page } from '@playwright/test'; | ||
|
||
export abstract class AILabBasePage { | ||
readonly page: Page; | ||
readonly webview: Page; | ||
heading: Locator; | ||
|
||
constructor(page: Page, webview: Page, heading: string | undefined) { | ||
this.page = page; | ||
this.webview = webview; | ||
this.heading = webview.getByRole('heading', { name: heading }); | ||
} | ||
|
||
abstract waitForLoad(): Promise<void>; | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/********************************************************************** | ||
* Copyright (C) 2024 Red Hat, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
***********************************************************************/ | ||
|
||
import { expect as playExpect } from '@playwright/test'; | ||
import type { Locator, Page } from '@playwright/test'; | ||
import { AILabBasePage } from './ai-lab-base-page'; | ||
import { AILabRecipesCatalogPage } from './ai-lab-recipes-catalog-page'; | ||
|
||
export class AILabNavigationBar extends AILabBasePage { | ||
readonly navigationBar: Locator; | ||
readonly recipesCatalogButton: Locator; | ||
readonly runningAppsButton: Locator; | ||
readonly catalogButton: Locator; | ||
readonly servicesButton: Locator; | ||
readonly playgroundsButton: Locator; | ||
|
||
constructor(page: Page, webview: Page) { | ||
super(page, webview, undefined); | ||
this.navigationBar = this.webview.getByRole('navigation', { name: 'PreferencesNavigation' }); | ||
this.recipesCatalogButton = this.navigationBar.getByRole('link', { name: 'Recipes Catalog', exact: true }); | ||
this.runningAppsButton = this.navigationBar.getByRole('link', { name: 'Running' }); | ||
this.catalogButton = this.navigationBar.getByRole('link', { name: 'Catalog', exact: true }); | ||
this.servicesButton = this.navigationBar.getByRole('link', { name: 'Services' }); | ||
this.playgroundsButton = this.navigationBar.getByRole('link', { name: 'Playgrounds' }); | ||
} | ||
|
||
async waitForLoad(): Promise<void> { | ||
await playExpect(this.navigationBar).toBeVisible(); | ||
} | ||
|
||
async openRecipesCatalog(): Promise<AILabRecipesCatalogPage> { | ||
await playExpect(this.recipesCatalogButton).toBeEnabled(); | ||
await this.recipesCatalogButton.click(); | ||
return new AILabRecipesCatalogPage(this.page, this.webview); | ||
} | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/********************************************************************** | ||
* Copyright (C) 2024 Red Hat, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
***********************************************************************/ | ||
|
||
import type { Page } from '@playwright/test'; | ||
import { expect as playExpect } from '@playwright/test'; | ||
import { AILabBasePage } from './ai-lab-base-page'; | ||
import { AILabNavigationBar } from './ai-lab-navigation-bar'; | ||
|
||
export class AILabPage extends AILabBasePage { | ||
readonly navigationBar: AILabNavigationBar; | ||
|
||
constructor(page: Page, webview: Page) { | ||
super(page, webview, 'Welcome to Podman AI Lab'); | ||
this.navigationBar = new AILabNavigationBar(this.page, this.webview); | ||
} | ||
|
||
async waitForLoad(): Promise<void> { | ||
await playExpect(this.heading).toBeVisible(); | ||
await this.navigationBar.waitForLoad(); | ||
} | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/********************************************************************** | ||
* Copyright (C) 2024 Red Hat, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
***********************************************************************/ | ||
|
||
import { expect as playExpect } from '@playwright/test'; | ||
import type { Locator, Page } from '@playwright/test'; | ||
import { AILabBasePage } from './ai-lab-base-page'; | ||
import { AILabAppDetailsPage } from './ai-lab-app-details-page'; | ||
|
||
export class AILabRecipesCatalogPage extends AILabBasePage { | ||
readonly recipesCatalogPage: Locator; | ||
readonly recipesCatalogContent: Locator; | ||
readonly recipesCatalogNaturalLanguageProcessing: Locator; | ||
readonly recipesCatalogAudio: Locator; | ||
readonly recipesCatalogComputerVision: Locator; | ||
|
||
constructor(page: Page, webview: Page) { | ||
super(page, webview, 'Recipe Catalog'); | ||
this.recipesCatalogPage = this.webview.getByRole('region', { name: 'Recipe Catalog' }); | ||
this.recipesCatalogContent = this.recipesCatalogPage.getByRole('region', { name: 'content', exact: true }).first(); | ||
this.recipesCatalogNaturalLanguageProcessing = this.recipesCatalogContent.getByRole('region', { | ||
name: 'Natural Language Processing', | ||
exact: true, | ||
}); | ||
this.recipesCatalogAudio = this.recipesCatalogContent.getByRole('region', { name: 'Audio', exact: true }); | ||
this.recipesCatalogComputerVision = this.recipesCatalogContent.getByRole('region', { | ||
name: 'Computer Vision', | ||
exact: true, | ||
}); | ||
} | ||
|
||
async waitForLoad(): Promise<void> { | ||
await playExpect(this.heading).toBeVisible(); | ||
await playExpect(this.recipesCatalogPage).toBeVisible(); | ||
} | ||
|
||
async openRecipesCatalogApp(category: Locator, appName: string): Promise<AILabAppDetailsPage> { | ||
await playExpect(category).toBeVisible(); | ||
await playExpect(this.getAppDetailsLocator(appName)).toBeEnabled(); | ||
await this.getAppDetailsLocator(appName).click(); | ||
return new AILabAppDetailsPage(this.page, this.webview, appName); | ||
} | ||
|
||
private getAppDetailsLocator(appName: string): Locator { | ||
return this.recipesCatalogContent | ||
.getByRole('region', { name: appName, exact: true }) | ||
.getByRole('button', { name: 'More details' }); | ||
} | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/********************************************************************** | ||
* Copyright (C) 2024 Red Hat, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
***********************************************************************/ | ||
|
||
import { expect as playExpect } from '@playwright/test'; | ||
import type { Locator, Page } from '@playwright/test'; | ||
import { AILabBasePage } from './ai-lab-base-page'; | ||
import { handleConfirmationDialog } from '@podman-desktop/tests-playwright'; | ||
|
||
export class AILabStartRecipePage extends AILabBasePage { | ||
readonly recipeStatus: Locator; | ||
readonly applicationDetailsPanel: Locator; | ||
readonly startRecipeButton: Locator; | ||
readonly openAIAppButton: Locator; | ||
readonly deleteAIAppButton: Locator; | ||
|
||
constructor(page: Page, webview: Page) { | ||
super(page, webview, 'Start Recipe'); | ||
this.recipeStatus = this.webview.getByRole('status'); | ||
this.applicationDetailsPanel = this.webview.getByLabel('application details panel'); | ||
this.startRecipeButton = this.webview.getByRole('button', { name: /Start(\s+([A-Za-z]+\s+)+)recipe/i }); | ||
this.openAIAppButton = this.applicationDetailsPanel.getByRole('button', { name: 'Open AI App' }); | ||
this.deleteAIAppButton = this.applicationDetailsPanel.getByRole('button', { name: 'Delete AI App' }); | ||
} | ||
|
||
async waitForLoad(): Promise<void> { | ||
await playExpect(this.heading).toBeVisible(); | ||
} | ||
|
||
async startRecipe(): Promise<void> { | ||
await playExpect(this.startRecipeButton).toBeEnabled(); | ||
await this.startRecipeButton.click(); | ||
try { | ||
await handleConfirmationDialog(this.page, 'Podman AI Lab', true, 'Reset'); | ||
} catch (error) { | ||
console.warn(`Warning: Could not reset the app, repository probably clean.\n\t${error}`); | ||
} | ||
await playExpect(this.recipeStatus).toContainText('AI App is running', { timeout: 720_000 }); | ||
} | ||
} |