Skip to content

Commit

Permalink
feat: setup Playwright e2e test including vFolder create/delete test
Browse files Browse the repository at this point in the history
  • Loading branch information
yomybaby committed Aug 21, 2024
1 parent 01c9e65 commit e4799e3
Show file tree
Hide file tree
Showing 12 changed files with 823 additions and 56 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,8 @@ src/plugins/*

# Ignore all other lock files
package-lock.json
yarn.lock
yarn.lock
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
47 changes: 47 additions & 0 deletions e2e/agent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { test, expect } from "@playwright/test";
import { loginAsAdmin } from "./test-util";
import { checkActiveTab, findColumnIndex } from "./test-util-antd";

test.beforeEach(async ({ page }) => {
await loginAsAdmin(page);
await page.getByRole("menuitem", { name: "hdd Resources" }).click();
await expect(
page.getByRole("heading", { name: "Computation Resources" }),
).toBeVisible();
});

test.describe("Agent list", () => {
let resourcesPageTab;
let agentListTable;

test.beforeEach(async ({ page }) => {
const firstCard = await page
.locator(".ant-layout-content .ant-card")
.first();
resourcesPageTab = await firstCard.locator(".ant-tabs");
agentListTable = await firstCard.locator(".ant-table");
});

test("should have at least one connected agent", async ({ page }) => {
const firstCard = await page
.locator(".ant-layout-content .ant-card")
.first();
await checkActiveTab(firstCard.locator(".ant-tabs"), "Agent");

const selectedSegment = await page.locator(".ant-segmented-item-selected");
await expect(selectedSegment).toContainText("Connected");

const rows = await agentListTable.locator(".ant-table-row");
const rowCount = await rows.count();
expect(rowCount).toBeGreaterThan(0);
const firstRow = rows.first();

const columnIndex = await findColumnIndex(agentListTable, "ID / Endpoint");
const specificColumn = await firstRow
.locator(".ant-table-cell")
.nth(columnIndex);
const columnText = await specificColumn.textContent();
const firstAgentId = columnText?.split("tcp://")[0];
expect(firstAgentId).toBeTruthy();
});
});
27 changes: 27 additions & 0 deletions e2e/login.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { test, expect } from '@playwright/test';
import { loginAsAdmin } from './test-util';

test.beforeEach(async ({ page }) => {
await page.goto('http://127.0.0.1:9081');

});

test.describe('Before login', () => {
test('should display the login form', async ({ page }) => {
await expect(page.getByLabel('E-mail or Username')).toBeVisible();
await expect(page.locator('#id_password label')).toBeVisible();
await expect(page.getByLabel('Login', { exact: true })).toBeVisible();
});
});

test.describe('Login using the admin account', () => {
test.beforeEach(async ({ page }) => {
await loginAsAdmin(page);
});

test('should redirect to the Summary', async ({ page }) => {
await expect(page).toHaveURL(/\/summary/);
await expect(page.getByRole('heading', { name: 'Summary' })).toBeVisible();
});
});

5 changes: 5 additions & 0 deletions e2e/test-1.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
// Recording...
});
25 changes: 25 additions & 0 deletions e2e/test-util-antd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Locator, expect } from "@playwright/test";

export async function checkActiveTab(
tabsLocator: Locator,
expectedTabName: string,
) {
const activeTab = await tabsLocator.locator(".ant-tabs-tab-active");
await expect(activeTab).toContainText(expectedTabName);
}

export async function getTableHeaders(page: Locator) {
return await page.locator(".ant-table-thead th");
}

export async function findColumnIndex(
tableLocator: Locator,
columnTitle: string,
) {
const headers = await tableLocator.locator(".ant-table-thead th");
const columnIndex = await headers.evaluateAll((ths, title) => {
return ths.findIndex((th) => th.textContent?.trim() === title);
}, columnTitle);

return columnIndex;
}
89 changes: 89 additions & 0 deletions e2e/test-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Page, expect } from "@playwright/test";

export async function login(
page: Page,
username: string,
password: string,
endpoint: string,
) {
await page.goto("http://127.0.0.1:9081");
await page.locator("#id_password label").click();
await page.getByLabel("E-mail or Username").click();
await page.getByLabel("E-mail or Username").fill(username);
await page.getByRole("textbox", { name: "Password" }).click();
await page.getByRole("textbox", { name: "Password" }).fill(password);
await page.getByRole("textbox", { name: "Endpoint" }).click();
await page.getByRole("textbox", { name: "Endpoint" }).fill(endpoint);
await page.getByLabel("Login", { exact: true }).click();
await page.waitForSelector('[data-testid="user-dropdown-button"]');

}

export async function loginAsAdmin(page: Page) {
await login(page, "[email protected]", "wJalrXUt", "http://127.0.0.1:8090");
}
export async function loginAsDomainAdmin(page: Page) {
await login(
page,
"[email protected]",
"cWbsM_vB",
"http://127.0.0.1:8090",
);
}
export async function loginAsUser(page: Page) {
await login(page, "[email protected]", "C8qnIo29", "http://127.0.0.1:8090");
}
export async function loginAsUser2(page: Page) {
await login(page, "[email protected]", "P7oxTDdz", "http://127.0.0.1:8090");
}
export async function loginAsMonitor(page: Page) {
await login(page, "[email protected]", "7tuEwF1J", "http://127.0.0.1:8090");
}

export async function logout(page: Page) {
await page.locator("text=Logout").click();
await page.getByTestId("user-dropdown-button").click();
await page.getByText("Log Out").click();
}

export async function navigateTo(page: Page, path: string) {
//merge the base url with the path
const url = new URL(path, "http://127.0.0.1:8090");
await page.goto(url.toString());
}

export async function createVFolderAndVerify(page: Page, folderName: string) {
await navigateTo(page, 'data');

await page.getByRole('button', { name: 'plus Add' }).click();
// TODO: wait for initial rendering without timeout
await page.waitForTimeout(1000);
await page.getByRole('textbox', { name: 'Folder name*' }).click();
await page.getByRole('textbox', { name: 'Folder name*' }).fill(folderName);
await page.getByRole('button', { name: 'Create', exact: true }).click();

await page.locator('#input-vaadin-text-field-18').click();
await page.locator('#input-vaadin-text-field-18').fill(folderName);
await page.waitForSelector(`text=folder_open ${folderName}`);
}

export async function deleteVFolderAndVerify(page: Page, folderName: string) {
await navigateTo(page, 'data');
await page.locator('#input-vaadin-text-field-18').click();
await page.locator('#input-vaadin-text-field-18').fill(folderName);
await page.waitForTimeout(1000);
await page.getByRole('button', { name: 'delete' }).first().click();
await page.locator('#delete-without-confirm-button').getByLabel('delete').click();
await page.getByRole('tab', { name: 'delete' }).click();
await page.locator('#input-vaadin-text-field-84').click();
await page.locator('#input-vaadin-text-field-84').fill(folderName);
await page.getByLabel('delete_forever').click();
await page.getByRole('textbox', { name: 'Type folder name to delete' }).fill(folderName);
await page.waitForTimeout(1000);
await page.getByRole('textbox', { name: 'Type folder name to delete' }).click();

await expect(page.locator('#trash-bin-folder-storage').getByText('e2e-test-folder', { exact: true })).toBeVisible();

await page.getByRole('button', { name: 'Delete forever' }).click();
await expect(page.locator('#trash-bin-folder-storage').getByText('e2e-test-folder', { exact: true })).toBeHidden();
}
11 changes: 11 additions & 0 deletions e2e/vfolder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test } from '@playwright/test';
import { createVFolderAndVerify, deleteVFolderAndVerify, loginAsUser } from './test-util';


test.describe('VFolder ', () => {
test('User can create and delete vFolder', async ({ page }) => {
await loginAsUser(page);
await createVFolderAndVerify(page, 'e2e-test-folder');
await deleteVFolderAndVerify(page, 'e2e-test-folder');
});
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"@babel/preset-typescript": "^7.24.7",
"@babel/types": "^7.25.2",
"@electron/packager": "^18.3.3",
"@playwright/test": "^1.46.1",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.7",
Expand All @@ -123,6 +124,7 @@
"@types/estree": "1.0.5",
"@types/hammerjs": "^2.0.45",
"@types/jest": "^29.5.12",
"@types/node": "^22.4.1",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@web/dev-server": "^0.4.6",
Expand Down
78 changes: 78 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { defineConfig, devices } from '@playwright/test';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// dotenv.config({ path: path.resolve(__dirname, '.env') });

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './e2e',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },

// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});
Loading

0 comments on commit e4799e3

Please sign in to comment.