mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-03 04:46:27 +00:00
PLAYWRIGHT: fix the bulk action playwright flaky playwright test (#21582)
* fix the bulk action playwright flaky playwright test * change entity and service.spec user to custom user and add a retry mechnaism for checking soft deleted entity * try to fix alert not found issue * remove failure * fix bot playwright failure (cherry picked from commit 78f523fd1327a992a39c429281f057b4f770f9fa)
This commit is contained in:
parent
393d869e93
commit
e37b794248
@ -512,7 +512,7 @@ test.describe('Bulk Edit Entity', () => {
|
||||
});
|
||||
|
||||
test('Table', async ({ page }) => {
|
||||
test.slow();
|
||||
test.slow(true);
|
||||
|
||||
const tableEntity = new TableClass();
|
||||
|
||||
|
@ -794,6 +794,8 @@ test.describe('Bulk Import Export', () => {
|
||||
});
|
||||
|
||||
test('Table', async ({ page }) => {
|
||||
test.slow(true);
|
||||
|
||||
const tableEntity = new TableClass();
|
||||
|
||||
const { apiContext, afterAction } = await getApiContext(page);
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { expect, Page, test as base } from '@playwright/test';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { CustomPropertySupportedEntityList } from '../../constant/customProperty';
|
||||
import { ApiEndpointClass } from '../../support/entity/ApiEndpointClass';
|
||||
@ -26,9 +26,9 @@ import { StoredProcedureClass } from '../../support/entity/StoredProcedureClass'
|
||||
import { TableClass } from '../../support/entity/TableClass';
|
||||
import { TopicClass } from '../../support/entity/TopicClass';
|
||||
import { UserClass } from '../../support/user/UserClass';
|
||||
import { performAdminLogin } from '../../utils/admin';
|
||||
import {
|
||||
assignDomain,
|
||||
createNewPage,
|
||||
generateRandomUsername,
|
||||
getApiContext,
|
||||
getAuthContext,
|
||||
@ -59,8 +59,23 @@ const entities = [
|
||||
MetricClass,
|
||||
] as const;
|
||||
|
||||
// use the admin user to login
|
||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||
const adminUser = new UserClass();
|
||||
|
||||
const test = base.extend<{ page: Page }>({
|
||||
page: async ({ browser }, use) => {
|
||||
const adminPage = await browser.newPage();
|
||||
await adminUser.login(adminPage);
|
||||
await use(adminPage);
|
||||
await adminPage.close();
|
||||
},
|
||||
});
|
||||
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await adminUser.create(apiContext);
|
||||
await adminUser.setAdminRole(apiContext);
|
||||
await afterAction();
|
||||
});
|
||||
|
||||
entities.forEach((EntityClass) => {
|
||||
const entity = new EntityClass();
|
||||
@ -72,7 +87,7 @@ entities.forEach((EntityClass) => {
|
||||
entity.type === 'MlModel' ? 'data-testid' : 'data-row-key';
|
||||
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await createNewPage(browser);
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
|
||||
await EntityDataClass.preRequisitesForTests(apiContext);
|
||||
await entity.create(apiContext);
|
||||
@ -380,7 +395,7 @@ entities.forEach((EntityClass) => {
|
||||
test.afterAll('Cleanup', async ({ browser }) => {
|
||||
test.slow();
|
||||
|
||||
const { apiContext, afterAction } = await createNewPage(browser);
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await entity.delete(apiContext);
|
||||
await EntityDataClass.postRequisitesForTests(apiContext);
|
||||
await afterAction();
|
||||
@ -418,3 +433,9 @@ entities.forEach((EntityClass) => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.afterAll('Cleanup', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await adminUser.delete(apiContext);
|
||||
await afterAction();
|
||||
});
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from '@playwright/test';
|
||||
import { Page, test as base } from '@playwright/test';
|
||||
import { CustomPropertySupportedEntityList } from '../../constant/customProperty';
|
||||
import { FollowSupportedServices } from '../../constant/service';
|
||||
import { ApiCollectionClass } from '../../support/entity/ApiCollectionClass';
|
||||
@ -25,8 +25,9 @@ import { MlmodelServiceClass } from '../../support/entity/service/MlmodelService
|
||||
import { PipelineServiceClass } from '../../support/entity/service/PipelineServiceClass';
|
||||
import { SearchIndexServiceClass } from '../../support/entity/service/SearchIndexServiceClass';
|
||||
import { StorageServiceClass } from '../../support/entity/service/StorageServiceClass';
|
||||
import { UserClass } from '../../support/user/UserClass';
|
||||
import { performAdminLogin } from '../../utils/admin';
|
||||
import {
|
||||
createNewPage,
|
||||
getApiContext,
|
||||
getAuthContext,
|
||||
getToken,
|
||||
@ -48,8 +49,23 @@ const entities = [
|
||||
DatabaseSchemaClass,
|
||||
] as const;
|
||||
|
||||
// use the admin user to login
|
||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||
const adminUser = new UserClass();
|
||||
|
||||
const test = base.extend<{ page: Page }>({
|
||||
page: async ({ browser }, use) => {
|
||||
const adminPage = await browser.newPage();
|
||||
await adminUser.login(adminPage);
|
||||
await use(adminPage);
|
||||
await adminPage.close();
|
||||
},
|
||||
});
|
||||
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await adminUser.create(apiContext);
|
||||
await adminUser.setAdminRole(apiContext);
|
||||
await afterAction();
|
||||
});
|
||||
|
||||
entities.forEach((EntityClass) => {
|
||||
const entity = new EntityClass();
|
||||
@ -57,7 +73,7 @@ entities.forEach((EntityClass) => {
|
||||
|
||||
test.describe(entity.getType(), () => {
|
||||
test.beforeAll('Setup pre-requests', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await createNewPage(browser);
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
|
||||
await EntityDataClass.preRequisitesForTests(apiContext);
|
||||
await entity.create(apiContext);
|
||||
@ -173,7 +189,7 @@ entities.forEach((EntityClass) => {
|
||||
});
|
||||
|
||||
test.afterAll('Cleanup', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await createNewPage(browser);
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await entity.delete(apiContext);
|
||||
await EntityDataClass.postRequisitesForTests(apiContext);
|
||||
await afterAction();
|
||||
@ -211,3 +227,9 @@ entities.forEach((EntityClass) => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.afterAll('Cleanup', async ({ browser }) => {
|
||||
const { apiContext, afterAction } = await performAdminLogin(browser);
|
||||
await adminUser.delete(apiContext);
|
||||
await afterAction();
|
||||
});
|
||||
|
@ -114,7 +114,7 @@ export const deleteBot = async (page: Page) => {
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
|
||||
await expect(page.getByTestId('page-layout-v1')).not.toContainText(botName);
|
||||
await expect(page.locator('.ant-table-tbody')).not.toContainText(botName);
|
||||
};
|
||||
|
||||
export const updateBotDetails = async (page: Page) => {
|
||||
|
@ -1280,7 +1280,27 @@ export const softDeleteEntity = async (
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
|
||||
const deletedBadge = page.locator('[data-testid="deleted-badge"]');
|
||||
// Retry mechanism for checking deleted badge
|
||||
let deletedBadge = page.locator('[data-testid="deleted-badge"]');
|
||||
let attempts = 0;
|
||||
const maxAttempts = 5;
|
||||
|
||||
while (attempts < maxAttempts) {
|
||||
const isVisible = await deletedBadge.isVisible();
|
||||
if (isVisible) {
|
||||
break;
|
||||
}
|
||||
|
||||
attempts++;
|
||||
if (attempts < maxAttempts) {
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
deletedBadge = page.locator('[data-testid="deleted-badge"]');
|
||||
}
|
||||
}
|
||||
|
||||
await expect(deletedBadge).toHaveText('Deleted');
|
||||
|
||||
|
@ -713,16 +713,46 @@ export const pressKeyXTimes = async (
|
||||
length: number,
|
||||
key: string
|
||||
) => {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const activeCell = page.locator('.InovuaReactDataGrid__cell--cell-active');
|
||||
const isActive = await activeCell.isVisible();
|
||||
const maxRetries = 3;
|
||||
const retryDelay = 1000; // 1 second delay between retries
|
||||
|
||||
if (!isActive) {
|
||||
await page.click('.InovuaReactDataGrid__cell--cell-active');
|
||||
for (let i = 0; i < length; i++) {
|
||||
let retryCount = 0;
|
||||
let success = false;
|
||||
|
||||
while (!success && retryCount < maxRetries) {
|
||||
try {
|
||||
// Wait for the active cell to be visible
|
||||
const activeCell = page.locator(
|
||||
'.InovuaReactDataGrid__cell--cell-active'
|
||||
);
|
||||
await activeCell.waitFor({ state: 'visible', timeout: 5000 });
|
||||
|
||||
// Ensure the cell is focused
|
||||
if (!(await activeCell.isVisible())) {
|
||||
await activeCell.click({ timeout: 5000 });
|
||||
}
|
||||
|
||||
// Perform the key press with a longer delay
|
||||
await activeCell.press(key, { delay: 200 });
|
||||
|
||||
// Verify the key press was successful by checking if the cell is still active
|
||||
await page.waitForTimeout(100); // Small delay to allow for state updates
|
||||
const isStillActive = await activeCell.isVisible();
|
||||
|
||||
if (isStillActive) {
|
||||
success = true;
|
||||
} else {
|
||||
// If cell lost focus, try to regain it
|
||||
await activeCell.click({ timeout: 5000 });
|
||||
retryCount++;
|
||||
await page.waitForTimeout(retryDelay);
|
||||
}
|
||||
} catch {
|
||||
retryCount++;
|
||||
await page.waitForTimeout(retryDelay);
|
||||
}
|
||||
}
|
||||
await page
|
||||
.locator('.InovuaReactDataGrid__cell--cell-active')
|
||||
.press(key, { delay: 100 });
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user