Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/scripts/build_playwright_shards.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"chromium",
"Basic",
"Ingestion",
"ImportExport",
"DataAssetRulesEnabled",
"DataAssetRulesDisabled",
"SearchRBAC",
Expand All @@ -32,6 +33,7 @@
"chromium": "chromium",
"Basic": "chromium",
"Ingestion": "ingestion",
"ImportExport": "import-export",
"DataAssetRulesEnabled": "data-asset-rules",
"DataAssetRulesDisabled": "data-asset-rules",
"SearchRBAC": "search-rbac",
Expand All @@ -48,6 +50,7 @@
LANE_WORKERS = {
"domain-isolation": 1,
"global-state": 1,
"import-export": 2,
"ingestion": 1,
"reindex": 1,
"search": 1,
Expand Down Expand Up @@ -347,6 +350,7 @@ def lane_bounds(lane: str, mode: str) -> tuple[int, int]:
if lane in {
"domain-isolation",
"global-state",
"import-export",
"ingestion",
"reindex",
"search",
Expand Down
10 changes: 10 additions & 0 deletions .github/scripts/tests/test_playwright_ci_planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,16 @@ def test_search_rbac_uses_an_isolated_single_worker_lane():
assert planner.lane_bounds("search-rbac", "full") == (1, 8)


def test_import_export_runs_in_its_own_lane_with_two_workers():
planner = load_script("build_playwright_shards")

assert "ImportExport" in planner.FULL_PROJECTS
assert planner.PROJECT_LANES["ImportExport"] == "import-export"
assert planner.LANE_WORKERS["import-export"] == 2
assert planner.lane_bounds("import-export", "full") == (1, 8)
assert planner.lane_bounds("import-export", "targeted") == (1, 2)


def test_source_glob_matching_is_explicit():
selector = load_script("select_playwright_tests")

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/playwright-postgresql-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,15 @@ jobs:
env:
PLAYWRIGHT_IS_OSS: "true"
PW_DEDICATED_INGESTION: "true"
PW_DEDICATED_IMPORT_EXPORT: "true"
Comment thread
greptile-apps[bot] marked this conversation as resolved.
PW_EXECUTION_MODE: ${{ needs.detect-changes.outputs.mode }}
PW_LINEAGE_REPRESENTATIVE_ONLY: ${{ needs.detect-changes.outputs.lineage_representative_only }}
run: |
npx playwright test --list --reporter=json \
--project=chromium \
--project=Basic \
--project=Ingestion \
--project=ImportExport \
--project=DataAssetRulesEnabled \
--project=DataAssetRulesDisabled \
--project=SearchRBAC \
Expand Down Expand Up @@ -799,6 +801,7 @@ jobs:
env:
PLAYWRIGHT_IS_OSS: "true"
PW_DEDICATED_INGESTION: "true"
PW_DEDICATED_IMPORT_EXPORT: "true"
run: |
npx playwright test --project=entity-data-setup --reporter=line
test -s playwright/.auth/admin.json
Expand Down
17 changes: 17 additions & 0 deletions openmetadata-ui/src/main/resources/ui/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const shardPlan = process.env.PW_SHARD_PLAN
: undefined;
const hasDedicatedIngestionLane =
Boolean(shardPlan) || process.env.PW_DEDICATED_INGESTION === 'true';
const hasDedicatedImportExportLane =
Boolean(shardPlan) || process.env.PW_DEDICATED_IMPORT_EXPORT === 'true';
const isPlannedShard = Boolean(shardPlan);
const hasPreseededState = process.env.PW_PRESEEDED_STATE === 'true';
const authDependencies = hasPreseededState ? [] : ['setup'];
Expand Down Expand Up @@ -182,6 +184,7 @@ export default defineConfig({
/@data-insight/,
/@basic/,
...(hasDedicatedIngestionLane ? [/@ingestion/] : []),
...(hasDedicatedImportExportLane ? [/@import-export/] : []),
/@knowledge-graph/,
/@ontology-rdf/,
],
Expand Down Expand Up @@ -313,6 +316,20 @@ export default defineConfig({
},
]
: []),
...(hasDedicatedImportExportLane
? [
{
name: 'ImportExport',
grep: combineGrep(/@import-export/),
testIgnore: '**/nightly/**',
use: { ...devices['Desktop Chrome'] },
dependencies: entityDependencies,
fullyParallel: true,
workers: 2,
teardown: entityTeardown,
},
]
: []),
{
name: 'SearchRBAC',
testMatch: '**/SearchRBAC.spec.ts',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

const test = base.extend<{ bulkEditorPage: Page }>({
bulkEditorPage: async ({ browser }, use) => {
const page = await browser.newPage();

Check warning on line 64 in openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/BulkEditImportPermissions.spec.ts

View workflow job for this annotation

GitHub Actions / checkstyle

Prefer the `page` fixture (test.use({ storageState })) over browser.newPage() + manual login for single-user admin tests. For multi-user tests that need a second non-admin page, this warning is expected — no action needed
await editorUser.login(page);
await use(page);
await page.close();
Expand Down Expand Up @@ -125,81 +125,85 @@
}
};

test.describe('Bulk Edit / Import - Non-admin permissions', () => {
test.describe.configure({ mode: 'serial' });

test.beforeAll(async ({ browser }) => {
test.setTimeout(180_000);
const { apiContext, afterAction } = await performAdminLogin(browser);
await glossary.create(apiContext);
await glossaryTerm.create(apiContext);
await table.create(apiContext);
await editorUser.create(apiContext, false);
const policyResponse = await editorPolicy.create(
apiContext,
BULK_EDIT_RULES
);
const roleResponse = await editorRole.create(apiContext, [
policyResponse.name,
]);
await editorUser.patch({
apiContext,
patchData: [
{
op: 'add',
path: '/roles/0',
value: {
id: roleResponse.id,
type: 'role',
name: roleResponse.name,
test.describe(
'Bulk Edit / Import - Non-admin permissions',
{ tag: '@import-export' },
() => {
test.describe.configure({ mode: 'serial' });

test.beforeAll(async ({ browser }) => {
test.setTimeout(180_000);
const { apiContext, afterAction } = await performAdminLogin(browser);
await glossary.create(apiContext);
await glossaryTerm.create(apiContext);
await table.create(apiContext);
await editorUser.create(apiContext, false);
const policyResponse = await editorPolicy.create(
apiContext,
BULK_EDIT_RULES
);
const roleResponse = await editorRole.create(apiContext, [
policyResponse.name,
]);
await editorUser.patch({
apiContext,
patchData: [
{
op: 'add',
path: '/roles/0',
value: {
id: roleResponse.id,
type: 'role',
name: roleResponse.name,
},
},
},
],
],
});
await afterAction();
});
await afterAction();
});

test.afterAll(async ({ browser }) => {
test.setTimeout(120_000);
const { apiContext, afterAction } = await performAdminLogin(browser);
await table.delete(apiContext);
await glossaryTerm.delete(apiContext);
await glossary.delete(apiContext);
await editorUser.delete(apiContext);
await editorRole.delete(apiContext);
await editorPolicy.delete(apiContext);
await afterAction();
});

test('Editor with EditAll can access every bulk edit and import page', async ({
bulkEditorPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(bulkEditorPage);
await verifyAllBulkRoutes(bulkEditorPage, true);
});

test('Data Consumer is blocked from every bulk edit and import page', async ({
dataConsumerPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(dataConsumerPage);
await verifyAllBulkRoutes(dataConsumerPage, false);
});

test('Data Steward is blocked from every bulk edit and import page', async ({
dataStewardPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(dataStewardPage);
await verifyAllBulkRoutes(dataStewardPage, false);
});

test('View-only user is blocked from every bulk edit and import page', async ({
viewOnlyPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(viewOnlyPage);
await verifyAllBulkRoutes(viewOnlyPage, false);
});
});

test.afterAll(async ({ browser }) => {
test.setTimeout(120_000);
const { apiContext, afterAction } = await performAdminLogin(browser);
await table.delete(apiContext);
await glossaryTerm.delete(apiContext);
await glossary.delete(apiContext);
await editorUser.delete(apiContext);
await editorRole.delete(apiContext);
await editorPolicy.delete(apiContext);
await afterAction();
});

test('Editor with EditAll can access every bulk edit and import page', async ({
bulkEditorPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(bulkEditorPage);
await verifyAllBulkRoutes(bulkEditorPage, true);
});

test('Data Consumer is blocked from every bulk edit and import page', async ({
dataConsumerPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(dataConsumerPage);
await verifyAllBulkRoutes(dataConsumerPage, false);
});

test('Data Steward is blocked from every bulk edit and import page', async ({
dataStewardPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(dataStewardPage);
await verifyAllBulkRoutes(dataStewardPage, false);
});

test('View-only user is blocked from every bulk edit and import page', async ({
viewOnlyPage,
}) => {
test.setTimeout(150_000);
await redirectToHomePage(viewOnlyPage);
await verifyAllBulkRoutes(viewOnlyPage, false);
});
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const storedProcedureDetails = {
glossary: glossaryDetails,
};

test.describe.fixme('Bulk Import Export', () => {
test.describe.fixme('Bulk Import Export', { tag: '@import-export' }, () => {
test.beforeAll('setup pre-test', async ({ browser }) => {
const { apiContext, afterAction } = await createNewPage(browser);

Expand Down
Loading
Loading