From 77ee16855e69a09947fe961b6f1879c785ec4f98 Mon Sep 17 00:00:00 2001 From: PRADDZY <64481960+PRADDZY@users.noreply.github.com> Date: Mon, 3 Aug 2026 03:58:41 +0530 Subject: [PATCH 01/83] fix: default data contracts to draft status --- .../AddDataContract/AddDataContract.test.tsx | 35 +++++++++++++++++-- .../AddDataContract/AddDataContract.tsx | 2 +- .../ContractDetailFormTab.test.tsx | 24 ++++++++++++- .../ContractDetailFormTab.tsx | 30 +++++++++++++++- 4 files changed, 85 insertions(+), 6 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx index e297b9fe9a79..76bcb3703b64 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx @@ -17,10 +17,10 @@ import { EDataContractTab } from '../../../constants/DataContract.constants'; import { EntityType } from '../../../enums/entity.enum'; import { DataContract, + EntityStatus, SemanticsRule, } from '../../../generated/entity/data/dataContract'; import { Column, Table } from '../../../generated/entity/data/table'; -import { EntityStatus } from '../../../generated/entity/domains/dataProduct'; import { EntityReference } from '../../../generated/entity/type'; import { createContract, updateContract } from '../../../rest/contractAPI'; import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils'; @@ -96,6 +96,9 @@ jest.mock('../ContractDetailFormTab/ContractDetailFormTab', () => ({ + )), @@ -442,7 +445,7 @@ describe('AddDataContract', () => { type: EntityType.TABLE, }, semantics: undefined, // validSemantics - undefined when no semantics provided - entityStatus: EntityStatus.Approved, + entityStatus: EntityStatus.Draft, }) ); expect(showSuccessToast).toHaveBeenCalledWith( @@ -474,7 +477,7 @@ describe('AddDataContract', () => { type: EntityType.TABLE, }, semantics: undefined, // validSemantics - undefined when no semantics provided - entityStatus: EntityStatus.Approved, + entityStatus: EntityStatus.Draft, }) ); expect(showSuccessToast).toHaveBeenCalledWith( @@ -483,6 +486,32 @@ describe('AddDataContract', () => { expect(mockOnSave).toHaveBeenCalled(); }); + it('should use selected entity status when creating a contract', async () => { + render(); + + const changeButton = screen.getByText('Change'); + await act(async () => { + fireEvent.click(changeButton); + }); + + const statusButton = screen.getByText('Change Status'); + await act(async () => { + fireEvent.click(statusButton); + }); + + const saveButton = screen.getByTestId('save-contract-btn'); + + await act(async () => { + fireEvent.click(saveButton); + }); + + expect(createContract).toHaveBeenCalledWith( + expect.objectContaining({ + entityStatus: EntityStatus.InReview, + }) + ); + }); + it('should call updateContract for existing contract with JSON patch', async () => { render( ({ const translations: Record = { 'label.contract-title': 'Contract Title', 'label.owner-plural': 'Owners', + 'label.status': 'Status', 'label.description': 'Description', 'label.contract-detail-plural': 'Contract Details', 'message.contract-detail-plural-description': 'Enter contract details', @@ -99,6 +104,7 @@ describe('ContractDetailFormTab', () => { expect(screen.getByText('Enter contract details')).toBeInTheDocument(); expect(screen.getByText('Contract Title')).toBeInTheDocument(); + expect(screen.getByText('Status')).toBeInTheDocument(); expect(screen.getByText('Owners')).toBeInTheDocument(); expect(screen.getByText('Description')).toBeInTheDocument(); }); @@ -127,6 +133,7 @@ describe('ContractDetailFormTab', () => { render(); expect(screen.getByText('Contract Title')).toBeInTheDocument(); + expect(screen.getByText('Status')).toBeInTheDocument(); expect(screen.getByText('Description')).toBeInTheDocument(); expect(screen.getByText('Owners')).toBeInTheDocument(); }); @@ -261,6 +268,21 @@ describe('ContractDetailFormTab', () => { name: 'owners', label: 'Owners', }), + expect.objectContaining({ + formItemProps: { + initialValue: EntityStatus.Draft, + }, + name: 'entityStatus', + label: 'Status', + props: expect.objectContaining({ + options: [ + { label: EntityStatus.Draft, value: EntityStatus.Draft }, + { label: EntityStatus.InReview, value: EntityStatus.InReview }, + { label: EntityStatus.Approved, value: EntityStatus.Approved }, + ], + }), + type: FieldTypes.SELECT, + }), expect.objectContaining({ name: 'description', label: 'Description', diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx index 9dd6684c712b..d37cdae61b33 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx @@ -16,13 +16,25 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { ReactComponent as RightIcon } from '../../../assets/svg/right-arrow.svg'; import { EntityType } from '../../../enums/entity.enum'; -import { DataContract } from '../../../generated/entity/data/dataContract'; +import { + DataContract, + EntityStatus, +} from '../../../generated/entity/data/dataContract'; import { useEntityRules } from '../../../hooks/useEntityRules'; import { FieldProp, FieldTypes } from '../../../interface/FormUtils.interface'; import { getEntityName } from '../../../utils/EntityNameUtils'; import { generateFormFields } from '../../../utils/formUtils'; import './contract-detail-form-tab.less'; +const DATA_CONTRACT_STATUS_OPTIONS = [ + EntityStatus.Draft, + EntityStatus.InReview, + EntityStatus.Approved, +].map((status) => ({ + label: status, + value: status, +})); + export const ContractDetailFormTab: React.FC<{ initialValues?: Partial; onNext: () => void; @@ -55,6 +67,21 @@ export const ContractDetailFormTab: React.FC<{ 'data-testid': 'contract-name', }, }, + { + label: t('label.status'), + id: 'entityStatus', + name: 'entityStatus', + type: FieldTypes.SELECT, + required: false, + placeholder: t('label.select-field', { field: t('label.status') }), + props: { + 'data-testid': 'contract-status', + options: DATA_CONTRACT_STATUS_OPTIONS, + }, + formItemProps: { + initialValue: initialValues?.entityStatus ?? EntityStatus.Draft, + }, + }, { label: t('label.owner-plural'), name: 'owners', @@ -95,6 +122,7 @@ export const ContractDetailFormTab: React.FC<{ form.setFieldsValue({ name: getEntityName(initialValues), description: initialValues.description, + entityStatus: initialValues.entityStatus ?? EntityStatus.Draft, owners: initialValues.owners, }); } From 56b443dee0e768a43685e1cb04e23de7f43cf111 Mon Sep 17 00:00:00 2001 From: Teddy Date: Fri, 28 Aug 2026 09:50:22 -0700 Subject: [PATCH 02/83] Apply batched suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../DataContract/AddDataContract/AddDataContract.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx index 76bcb3703b64..fdbfb5394443 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx @@ -96,7 +96,7 @@ jest.mock('../ContractDetailFormTab/ContractDetailFormTab', () => ({ - From 09bb37ee17cec7905b30b75fadb0ecd58989397b Mon Sep 17 00:00:00 2001 From: PRADDZY <64481960+PRADDZY@users.noreply.github.com> Date: Mon, 31 Aug 2026 13:45:19 +0530 Subject: [PATCH 03/83] fix: localize data contract status options --- .../AddDataContract/AddDataContract.test.tsx | 3 +- .../ContractDetailFormTab.test.tsx | 11 ++++--- .../ContractDetailFormTab.tsx | 30 +++++++++++++------ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx index fdbfb5394443..5ffeb2ee7ecc 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/AddDataContract/AddDataContract.test.tsx @@ -96,7 +96,8 @@ jest.mock('../ContractDetailFormTab/ContractDetailFormTab', () => ({ - diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.test.tsx index 18c80993514f..b734e4c647eb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.test.tsx @@ -16,8 +16,8 @@ import { DataContract, EntityStatus, } from '../../../generated/entity/data/dataContract'; -import { FieldTypes } from '../../../interface/FormUtils.interface'; import { EntityReference } from '../../../generated/entity/type'; +import { FieldTypes } from '../../../interface/FormUtils.interface'; import { ContractDetailFormTab } from './ContractDetailFormTab'; jest.mock('../../../utils/formUtils', () => ({ @@ -52,6 +52,9 @@ jest.mock('react-i18next', () => ({ 'label.contract-title': 'Contract Title', 'label.owner-plural': 'Owners', 'label.status': 'Status', + 'label.draft': 'Draft label', + 'label.in-review': 'In Review label', + 'label.approved': 'Approved label', 'label.description': 'Description', 'label.contract-detail-plural': 'Contract Details', 'message.contract-detail-plural-description': 'Enter contract details', @@ -276,9 +279,9 @@ describe('ContractDetailFormTab', () => { label: 'Status', props: expect.objectContaining({ options: [ - { label: EntityStatus.Draft, value: EntityStatus.Draft }, - { label: EntityStatus.InReview, value: EntityStatus.InReview }, - { label: EntityStatus.Approved, value: EntityStatus.Approved }, + { label: 'Draft label', value: EntityStatus.Draft }, + { label: 'In Review label', value: EntityStatus.InReview }, + { label: 'Approved label', value: EntityStatus.Approved }, ], }), type: FieldTypes.SELECT, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx index d37cdae61b33..d53f9b4d3511 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataContract/ContractDetailFormTab/ContractDetailFormTab.tsx @@ -26,14 +26,20 @@ import { getEntityName } from '../../../utils/EntityNameUtils'; import { generateFormFields } from '../../../utils/formUtils'; import './contract-detail-form-tab.less'; -const DATA_CONTRACT_STATUS_OPTIONS = [ - EntityStatus.Draft, - EntityStatus.InReview, - EntityStatus.Approved, -].map((status) => ({ - label: status, - value: status, -})); +const DATA_CONTRACT_STATUS_OPTION_KEYS = [ + { + labelKey: 'label.draft', + value: EntityStatus.Draft, + }, + { + labelKey: 'label.in-review', + value: EntityStatus.InReview, + }, + { + labelKey: 'label.approved', + value: EntityStatus.Approved, + }, +]; export const ContractDetailFormTab: React.FC<{ initialValues?: Partial; @@ -52,6 +58,12 @@ export const ContractDetailFormTab: React.FC<{ const { t } = useTranslation(); const [form] = Form.useForm(); const { entityRules } = useEntityRules(EntityType.TABLE); + const dataContractStatusOptions = DATA_CONTRACT_STATUS_OPTION_KEYS.map( + ({ labelKey, value }) => ({ + label: t(labelKey), + value, + }) + ); const fields: FieldProp[] = [ { @@ -76,7 +88,7 @@ export const ContractDetailFormTab: React.FC<{ placeholder: t('label.select-field', { field: t('label.status') }), props: { 'data-testid': 'contract-status', - options: DATA_CONTRACT_STATUS_OPTIONS, + options: dataContractStatusOptions, }, formItemProps: { initialValue: initialValues?.entityStatus ?? EntityStatus.Draft, From 9c3bdc94f91f9b0f3c3238650db099285f810072 Mon Sep 17 00:00:00 2001 From: Rohit Jain <60229265+Rohit0301@users.noreply.github.com> Date: Mon, 31 Aug 2026 08:53:57 +0000 Subject: [PATCH 04/83] fix(playwright): narrow add-reactions locator to fix strict mode violation (#32275) * fix(playwright): narrow add-reactions locator to avoid strict mode violation The `add-reactions` locator inside `message-container` was resolving to multiple elements (one per thread participant card), causing Playwright's strict mode to abort the Mention notification test. Added `data-testid="feed-card-footer"` to FeedCardFooterNew and scoped the locator to the footer that contains `reply-button` (main message only). Co-Authored-By: Claude Sonnet 4.6 * lint fix --------- Co-authored-by: Claude Sonnet 4.6 --- .../ui/playwright/e2e/Features/ActivityFeed.spec.ts | 6 +++++- .../ActivityFeedCardV2/FeedCardFooter/FeedCardFooterNew.tsx | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts index 37f74df2a36e..2fd65bee3ec1 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts @@ -747,7 +747,11 @@ test.describe('Mention notifications in Notification Box', () => { new URL(response.url()).pathname ) && response.request().method() === 'PUT' ); - await message.locator('[data-testid="add-reactions"]').click(); + await message + .locator('[data-testid="feed-card-footer"]') + .filter({ has: user1Page.locator('[data-testid="reply-button"]') }) + .locator('[data-testid="add-reactions"]') + .click(); await user1Page.locator('[title="rocket"]').click(); await reactionResponse; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCardV2/FeedCardFooter/FeedCardFooterNew.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCardV2/FeedCardFooter/FeedCardFooterNew.tsx index cb071cad0d2e..682338d82571 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCardV2/FeedCardFooter/FeedCardFooterNew.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCardV2/FeedCardFooter/FeedCardFooterNew.tsx @@ -79,7 +79,10 @@ function FeedCardFooterNew({ return ( - +
{postLength > 0 && !isReply && ( From 6cc4dab519baa1c151fa4869acd07283d5c2bffa Mon Sep 17 00:00:00 2001 From: Karan Hotchandani <33024356+karanh37@users.noreply.github.com> Date: Mon, 31 Aug 2026 06:09:56 +0000 Subject: [PATCH 05/83] fix(security): bump httpclient5 to 5.6.4 (#32264) Closes CVE-2026-71290 (CWE-295, Improper Certificate Validation; critical, CVSS 9.1). In httpclient5 5.6.3 and earlier, HostnameVerificationPolicy#BUILTIN has no effect on the async TLS upgrade path, so SSL parameters are not applied and a MITM attacker can impersonate a server with a certificate valid for a different domain. Fixed in 5.6.4. httpclient5 5.6.4 declares httpcore5 5.4.3, identical to 5.6.3, so the client/core pairing pinned above (httpcore5 5.4.3) is preserved and the SingleCoreIOReactor lease-leak failure mode is not reintroduced. Still within the 5.6 line, so the disableContentCompression() requirement on the OpenSearch/Elasticsearch transports is unchanged. Root pom dependencyManagement is the sole authority for this pin. Mirrors open-metadata/openmetadata-collate#6277. Co-authored-by: Claude Opus 4.8 (1M context) --- pom.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 5eb1241840c5..5040e2ad45f1 100644 --- a/pom.xml +++ b/pom.xml @@ -832,12 +832,14 @@ Keep this in step with the httpcore5 pin above - Apache releases the two together and mixing lines breaks search. httpclient5 5.5/5.5.2 are built against httpcore5 5.3.x; on 5.4.x their I/O reactor dispatchers die silently, leaking connection-pool - leases until every request fails with DeadlineTimeoutException. 5.6.3 declares - httpcore5 5.4.3, so client and core match. + leases until every request fails with DeadlineTimeoutException. 5.6.4 declares + httpcore5 5.4.3 (identical to 5.6.3), so client and core match. - 5.6.3 is also the first release outside the CVE-2026-64607 range (affects + 5.6.3 was the first release outside the CVE-2026-64607 range (affects 5.0-alpha1 through 5.6.2: the classic i/o client leaks a connection when a response - carries an invalid Content-Encoding). + carries an invalid Content-Encoding). 5.6.4 additionally closes CVE-2026-71290 + (improper certificate validation: HostnameVerificationPolicy#BUILTIN had no effect on + the async TLS upgrade path, so SSL parameters were not applied). The 5.6 line enables automatic content decompression in the async client, which the search transports also do - see disableContentCompression() in OpenSearchClient and @@ -846,7 +848,7 @@ org.apache.httpcomponents.client5 httpclient5 - 5.6.3 + 5.6.4 org.apache.commons From a522bae08f891e8aa4e6933548fa30cbadf450b1 Mon Sep 17 00:00:00 2001 From: Shailesh Parmar Date: Mon, 31 Aug 2026 06:14:44 +0000 Subject: [PATCH 06/83] ci(playwright): run release-branch nightly E2E with 2 per-test retries (#32267) * ci(playwright): run MySQL nightly E2E with 2 per-test retries playwright.config.ts hardcoded retries to 1 on CI with no way to vary it per workflow. Make it overridable via PLAYWRIGHT_RETRIES, thread a `retries` input through the reusable E2E workflow onto the shard test step's env, and set it to 2 for the MySQL release-branch nightly, where flakes accumulate faster than on main. Empty default keeps every other caller (postgres PR gate, nightlies) at the existing CI default of 1. Co-Authored-By: Claude Fable 5 * ci(playwright): PostgreSQL release-branch nightly also gets 2 retries Same rationale as the MySQL nightly: release branches accumulate flakes faster than main, so the on-demand release-branch runner passes retries: "2" to the reusable. The PR gate (playwright-postgresql-e2e.yml) intentionally stays at the config default of 1. Co-Authored-By: Claude Fable 5 * ci(playwright): type the retries input as number Review feedback: the string + empty-sentinel input forced callers to quote the value and made the contract unclear. Declare it type: number with default 1 (matching playwright.config.ts's CI default, so the PR gate is unchanged) and pass bare `retries: 2` from the nightlies. Co-Authored-By: Claude Fable 5 * ci(playwright): simplify retries fallback to a single ?? expression Review suggestion, corrected: `?? CI ? 1 : 0` alone parses as `(RETRIES ?? CI) ? 1 : 0`, which collapses every override to 1. With parens forcing `RETRIES ?? (CI ? 1 : 0)` plus Number(), the one-liner matches the nested ternary in all scenarios (override, CI default, local 0, explicit 0). Co-Authored-By: Claude Fable 5 --------- Co-authored-by: Claude Fable 5 --- .github/workflows/mysql-nightly-e2e.yml | 3 +++ .github/workflows/playwright-e2e-reusable.yml | 10 ++++++++++ .github/workflows/postgresql-nightly-e2e.yml | 3 +++ .../src/main/resources/ui/playwright.config.ts | 6 ++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mysql-nightly-e2e.yml b/.github/workflows/mysql-nightly-e2e.yml index 5979647d326a..b9ddfdd00e17 100644 --- a/.github/workflows/mysql-nightly-e2e.yml +++ b/.github/workflows/mysql-nightly-e2e.yml @@ -76,5 +76,8 @@ jobs: full_suite: ${{ inputs.full_suite }} protocol: ${{ inputs.protocol }} coarse_bundle: ${{ inputs.coarse_bundle }} + # Release branches accumulate flakes faster than main; give each test + # two retries instead of the config default of one. + retries: 2 send_slack_notification: ${{ inputs.send_slack_notification }} slack_run_title: "MySQL Playwright E2E on ${{ inputs.branch }}" diff --git a/.github/workflows/playwright-e2e-reusable.yml b/.github/workflows/playwright-e2e-reusable.yml index 20ef1e6739ce..d9c2e507afe1 100644 --- a/.github/workflows/playwright-e2e-reusable.yml +++ b/.github/workflows/playwright-e2e-reusable.yml @@ -64,6 +64,15 @@ on: required: false type: boolean default: true + retries: + description: >- + Playwright per-test retry count, exported to playwright.config.ts as + PLAYWRIGHT_RETRIES on the shard test step only (the fixture populator + and bundle-smoke keep the config default). The default matches the + config's CI default of 1; release-branch nightlies raise it to 2. + required: false + type: number + default: 1 send_slack_notification: description: Post a Slack summary once the run finishes. required: false @@ -1482,6 +1491,7 @@ jobs: PW_SHARD_ID: ${{ matrix.shardId }} PW_SHARD_PLAN: ${{ steps.fast-inputs.outputs.plan }} PW_WORKERS: ${{ matrix.workers }} + PLAYWRIGHT_RETRIES: ${{ inputs.retries }} PLAYWRIGHT_IS_OSS: true PLAYWRIGHT_SNOWFLAKE_USERNAME: ${{ secrets.TEST_SNOWFLAKE_USERNAME }} PLAYWRIGHT_SNOWFLAKE_PASSWORD: ${{ secrets.TEST_SNOWFLAKE_PASSWORD }} diff --git a/.github/workflows/postgresql-nightly-e2e.yml b/.github/workflows/postgresql-nightly-e2e.yml index 4d7e1aff21ed..546a5b41df86 100644 --- a/.github/workflows/postgresql-nightly-e2e.yml +++ b/.github/workflows/postgresql-nightly-e2e.yml @@ -77,5 +77,8 @@ jobs: full_suite: ${{ inputs.full_suite }} protocol: ${{ inputs.protocol }} coarse_bundle: ${{ inputs.coarse_bundle }} + # Release branches accumulate flakes faster than main; give each test + # two retries instead of the config default of one. + retries: 2 send_slack_notification: ${{ inputs.send_slack_notification }} slack_run_title: "PostgreSQL Playwright E2E on ${{ inputs.branch }}" diff --git a/openmetadata-ui/src/main/resources/ui/playwright.config.ts b/openmetadata-ui/src/main/resources/ui/playwright.config.ts index 98d78a2c4968..89736ba47303 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright.config.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright.config.ts @@ -132,8 +132,10 @@ export default defineConfig({ 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 ? 1 : 0, + /* Retry on CI only; PLAYWRIGHT_RETRIES (set per workflow via the reusable's + * `retries` input) overrides the CI default of 1. The parens are semantic: + * without them `?? CI ? 1 : 0` collapses every override to 1. */ + retries: Number(process.env.PLAYWRIGHT_RETRIES ?? (process.env.CI ? 1 : 0)), /* Opt out of parallel tests on CI. */ workers: process.env.CI ? Number(process.env.PW_WORKERS ?? shardPlan?.workers ?? 3) From 961d7609d52329f22335f79cbd3c5935b33a2bf4 Mon Sep 17 00:00:00 2001 From: Shailesh Parmar Date: Mon, 31 Aug 2026 06:34:03 +0000 Subject: [PATCH 07/83] fix(ui): re-enable all disabled Jest tests; promote jest/no-disabled-tests to error (#32249) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every `it.skip` / `describe.skip` in the UI test suite was genuinely re-enabled and made to pass against current behavior — no re-skipping, no inline suppressions, no weakened assertions. Highlights: - TestCaseStatusModal: mock the new transitionIncident/incident-refresh submit path; assert real outcomes. - QueryCardExtraOption: set the mock user to the actual voter so the un-vote path executes. - NextPreviousWithOffset: open the hover-triggered antd dropdown via mouseEnter. - MlModelDetail: rebuild mocks for the rewritten component (useRequiredParams, DataAssetsHeader, GenericProvider, tabs) keeping real DETAILS-tab assertions. - SettingsRouter: mount under a `/settings/*` parent so relative routes resolve; fix a wrong route constant. One inner test targeted CustomPageSettings, which was removed from the codebase entirely (feature relocated to another router) — the obsolete test was deleted rather than fake-passed. - AdvanceSearchProvider: restore the real getQbConfigs, handle the lazy modal, and drive userEvent with the global fake timers. - UserPage: restore the wired Users mock; update the getUserByName field list. - TagsPage: rewrite the classification-rename test to the refactored ManageButton -> ClassificationFormDrawer flow; drop a stale file-level eslint-disable directive. 96 tests across the 9 files pass; 0 project-wide ESLint errors. Closes #30982 Co-authored-by: Claude Opus 4.8 (1M context) --- .../src/main/resources/ui/eslint.config.mjs | 2 +- .../AppRouter/SettingsRouter.test.tsx | 180 ++++-------------- .../TestCaseStatusModal.test.tsx | 30 ++- .../QueryCardExtraOption.test.tsx | 32 +++- .../AdvanceSearchProvider.test.tsx | 88 ++++++--- .../GlossaryUpdateConfirmationModal.test.tsx | 2 +- .../MlModelDetail.component.test.tsx | 127 +++++++----- .../NextPreviousWithOffset.test.tsx | 18 +- .../resources/ui/src/mocks/Queries.mock.ts | 12 +- .../ui/src/pages/TagsPage/TagsPage.test.tsx | 37 ++-- .../ui/src/pages/UserPage/UserPage.test.tsx | 19 +- 11 files changed, 280 insertions(+), 267 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/eslint.config.mjs b/openmetadata-ui/src/main/resources/ui/eslint.config.mjs index 090c0f22f582..79151423d89a 100644 --- a/openmetadata-ui/src/main/resources/ui/eslint.config.mjs +++ b/openmetadata-ui/src/main/resources/ui/eslint.config.mjs @@ -172,7 +172,7 @@ export default [ withinDescribe: 'it', }, ], - 'jest/no-disabled-tests': 'warn', + 'jest/no-disabled-tests': 'error', 'jest-formatting/padding-around-all': 'error', // TypeScript rules diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.test.tsx index a2f924879103..c1839fd4b73e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.test.tsx @@ -189,169 +189,109 @@ jest.mock('./AdminProtectedRoute', () => ({ default: jest.fn().mockImplementation(({ children }) => children), })); -describe.skip('SettingsRouter', () => { - it('should render GlobalSettingPage component for exact settings route', async () => { +describe('SettingsRouter', () => { + // SettingsRouter declares its routes relative to ROUTES.SETTINGS (the `/settings` prefix is + // stripped off each path), so it only resolves them when mounted under a parent route that + // consumes that prefix — rendering it bare at `/settings/...` matches nothing. + const renderAtSettingsPath = (entry: string) => render( - - + + + } path="/settings/*" /> + ); + it('should render GlobalSettingPage component for exact settings route', async () => { + renderAtSettingsPath('/settings'); + expect(await screen.findByText('GlobalSettingPage')).toBeInTheDocument(); }); it('should render AddRolePage component for add role route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.ADD_ROLE); expect(await screen.findByText('AddRolePage')).toBeInTheDocument(); }); it('should render RolesDetailPage component for roles details route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/access/roles/testRole'); expect(await screen.findByText('RolesDetailPage')).toBeInTheDocument(); }); it('should render RolesListPage component for roles list route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/access/roles'); expect(await screen.findByText('RolesListPage')).toBeInTheDocument(); }); it('should render AddPolicyPage component for add policy route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.ADD_POLICY); expect(await screen.findByText('AddPolicyPage')).toBeInTheDocument(); }); it('should render AddRulePage component for add rule route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.ADD_POLICY_RULE); expect(await screen.findByText('AddRulePage')).toBeInTheDocument(); }); it('should render EditRulePage component for edit rule route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.EDIT_POLICY_RULE); expect(await screen.findByText('EditRulePage')).toBeInTheDocument(); }); it('should render PoliciesDetailPage component for policies details route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/access/policies/testPolicy'); expect(await screen.findByText('PoliciesDetailPage')).toBeInTheDocument(); }); it('should render PoliciesListPage component for policies list route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/access/policies'); expect(await screen.findByText('PoliciesListPage')).toBeInTheDocument(); }); it('should render UserListPageV1 component for user list route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/members/users'); expect(await screen.findByText('UserListPageV1')).toBeInTheDocument(); }); it('should render ServicesPage component for services route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/services/databases'); expect(await screen.findByText('ServicesPage')).toBeInTheDocument(); }); it('should render TeamsPage component for teams route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/members/teams/Organization'); expect(await screen.findByText('TeamsPage')).toBeInTheDocument(); }); it('should render ImportTeamsPage component for import teams route', async () => { - render( - - - + renderAtSettingsPath( + '/settings/members/teams/Organization/import?type=teams' ); expect(await screen.findByText('ImportTeamsPage')).toBeInTheDocument(); }); it('should render CustomPropertiesPageV1 component for custom properties route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/customProperties/table'); expect( await screen.findByText('CustomPropertiesPageV1') ).toBeInTheDocument(); }); - it.skip('should render CustomPageSettings component for custom page settings route', async () => { - render( - - - - ); - - expect(await screen.findByText('CustomPageSettings')).toBeInTheDocument(); - }); - it('should render EmailConfigSettingsPage component for email config settings route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/preferences/email'); expect( await screen.findByText('EmailConfigSettingsPage') @@ -359,22 +299,13 @@ describe.skip('SettingsRouter', () => { }); it('should render EditEmailConfigPage component for edit email config route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.SETTINGS_EDIT_EMAIL_CONFIG); expect(await screen.findByText('EditEmailConfigPage')).toBeInTheDocument(); }); it('should render LoginConfigurationPage component for login configuration details route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/preferences/loginConfiguration'); expect( await screen.findByText('LoginConfigurationPage') @@ -382,11 +313,7 @@ describe.skip('SettingsRouter', () => { }); it('should render EditLoginConfigurationPage component for edit login configuration route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.SETTINGS_EDIT_CUSTOM_LOGIN_CONFIG); expect( await screen.findByText('EditLoginConfigurationPage') @@ -394,79 +321,50 @@ describe.skip('SettingsRouter', () => { }); it('should render NotificationListPage component for notification list route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.NOTIFICATION_ALERT_LIST); expect(await screen.findByText('NotificationListPage')).toBeInTheDocument(); }); it('should render AddNotificationPage component for add notification route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.EDIT_NOTIFICATION_ALERTS); expect(await screen.findByText('AddNotificationPage')).toBeInTheDocument(); }); it('should render PersonaPage component for persona list route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/persona'); expect(await screen.findByText('PersonaPage')).toBeInTheDocument(); }); it('should render PersonaDetailsPage component for persona details route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/persona/testPersona'); expect(await screen.findByText('PersonaDetailsPage')).toBeInTheDocument(); }); it('should render BotsPageV1 component for bots route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/bots'); expect(await screen.findByText('BotsPageV1')).toBeInTheDocument(); }); it('should render ApplicationPage component for application route', async () => { - render( - - - - ); + renderAtSettingsPath('/settings/apps'); expect(await screen.findByText('ApplicationPage')).toBeInTheDocument(); }); it('should render AlertDetailsPage component for alert details route', async () => { - render( - - - - ); + renderAtSettingsPath(ROUTES.NOTIFICATION_ALERT_DETAILS_WITH_TAB); expect(await screen.findByText('AlertDetailsPage')).toBeInTheDocument(); }); }); -// The suite above is `describe.skip` at HEAD, so a case added there would never execute. This -// block is separate so the route guard is actually exercised. +// Kept as a separate suite because it additionally mounts a sibling `/404` route and spies on +// connectionsRouterClassBase to exercise the services route guard end to end. describe('SettingsRouter services routes', () => { const renderAt = (entry: string) => render( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/TestCaseStatusModal/TestCaseStatusModal.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/TestCaseStatusModal/TestCaseStatusModal.test.tsx index 229f2405cd97..4c925c69c34d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/TestCaseStatusModal/TestCaseStatusModal.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/TestCaseStatusModal/TestCaseStatusModal.test.tsx @@ -14,6 +14,7 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { forwardRef } from 'react'; import { TestCaseResolutionStatusTypes } from '../../../generated/tests/testCaseResolutionStatus'; +import { transitionIncident } from '../../../rest/incidentManagerAPI'; import { TestCaseStatusModal } from './TestCaseStatusModal.component'; import { TestCaseStatusModalProps } from './TestCaseStatusModal.interface'; @@ -36,6 +37,18 @@ jest.mock('../../../generated/tests/testCase', () => ({ }, })); +const mockLatestIncident = { + id: 'latest-incident-id', + testCaseResolutionStatusType: 'New', +}; + +jest.mock('../../../rest/incidentManagerAPI', () => ({ + transitionIncident: jest.fn().mockResolvedValue({}), + getListTestCaseIncidentByStateId: jest.fn().mockResolvedValue({ + data: [{ id: 'latest-incident-id', testCaseResolutionStatusType: 'New' }], + }), +})); + describe('TestCaseStatusModal component', () => { it('component should render', async () => { render(); @@ -46,7 +59,7 @@ describe('TestCaseStatusModal component', () => { expect(await screen.findByText('label.save')).toBeInTheDocument(); }); - it.skip('should render test case reason and comment field, if status is resolved', async () => { + it('should render test case reason and comment field, if status is resolved', async () => { render( { expect(mockProps.onCancel).toHaveBeenCalled(); }); - it.skip('should call onSubmit function, on click of save button', async () => { - render(); + it('should call onSubmit function, on click of save button', async () => { + render( + + ); const submitBtn = await screen.findByText('label.save'); const status = await screen.findByLabelText('label.status'); @@ -87,16 +102,19 @@ describe('TestCaseStatusModal component', () => { userEvent.click(status); }); - const statusOption = await screen.findAllByText('New'); + const statusOption = await screen.findAllByText('label.new'); await act(async () => { - fireEvent.click(statusOption[1]); + fireEvent.click(statusOption[statusOption.length - 1]); }); await act(async () => { fireEvent.click(submitBtn); }); - expect(mockProps.onSubmit).toHaveBeenCalled(); + expect(transitionIncident).toHaveBeenCalledWith('test-state-id', { + transitionId: 'new', + }); + expect(mockProps.onSubmit).toHaveBeenCalledWith(mockLatestIncident); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCardExtraOption/QueryCardExtraOption.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCardExtraOption/QueryCardExtraOption.test.tsx index c81646d819df..335551fb53b4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCardExtraOption/QueryCardExtraOption.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCardExtraOption/QueryCardExtraOption.test.tsx @@ -56,6 +56,15 @@ jest.mock('react-router-dom', () => { }); describe('QueryCardExtraOption component test', () => { + beforeEach(() => { + mockUserData = { + id: '471353cb-f925-4c4e-be6c-14da2c0b00ce', + name: 'aaron_johnson0', + fullyQualifiedName: 'aaron_johnson0', + email: '', + }; + }); + it('Component should render', async () => { render(); @@ -130,7 +139,14 @@ describe('QueryCardExtraOption component test', () => { ); }); - it.skip('OnClick of Vote up it should un vote if logged-in user has already up voted', async () => { + it('OnClick of Vote up it should un vote if logged-in user has already up voted', async () => { + mockUserData = { + id: 'cdccaedd-ed02-4c89-bc1a-1c4cd679d1e3', + name: 'test-user', + fullyQualifiedName: 'test-user', + displayName: 'Test User', + email: '', + }; render(); const voteUp = await screen.findByTestId('up-vote-btn'); @@ -156,7 +172,13 @@ describe('QueryCardExtraOption component test', () => { ); }); - it.skip('OnClick of Vote down it should un vote if logged-in user has already down voted', async () => { + it('OnClick of Vote down it should un vote if logged-in user has already down voted', async () => { + mockUserData = { + id: '4f277812-6670-4f28-a11b-459d537b7ba9', + name: 'admin', + fullyQualifiedName: 'admin', + email: '', + }; render(); const voteDown = await screen.findByTestId('down-vote-btn'); @@ -172,9 +194,9 @@ describe('QueryCardExtraOption component test', () => { it('OnClick of Vote down it should vote down if logged-in user has already up voted', async () => { mockUserData = { id: 'cdccaedd-ed02-4c89-bc1a-1c4cd679d1e3', - name: 'shailesh.parmar', - fullyQualifiedName: 'shailesh.parmar', - displayName: 'ShaileshParmar', + name: 'test-user', + fullyQualifiedName: 'test-user', + displayName: 'Test User', email: '', }; render(); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.test.tsx index b3fbe1331a21..7245a26db3a5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.test.tsx @@ -47,6 +47,23 @@ jest.mock('../../common/Loader/Loader', () => jest.fn().mockReturnValue(
Loader
) ); +// The global mock in setupTests.js stubs getQbConfigs to return an empty object, +// but this provider feeds the config straight into the react-awesome-query-builder +// utilities, which require a fully-formed config (settings, types, widgets...). +// Restore the real getQbConfigs here so the tree utilities receive a valid config. +jest.mock('../../../utils/AdvancedSearchClassBase', () => { + const actual = jest.requireActual('../../../utils/AdvancedSearchClassBase'); + + return { + __esModule: true, + ...actual, + default: { + ...actual.default, + autocomplete: jest.fn().mockReturnValue(jest.fn()), + }, + }; +}); + const mockNavigate = jest.fn(); jest.mock('../../../hooks/useCustomLocation/useCustomLocation', () => { @@ -63,19 +80,6 @@ jest.mock('react-router-dom', () => ({ useNavigate: jest.fn().mockImplementation(() => mockNavigate), })); -jest.mock('../../../utils/AdvancedSearchClassBase', () => ({ - __esModule: true, - default: { - getURLSearchParams: jest.fn().mockReturnValue({}), - getQueryFilters: jest.fn().mockReturnValue({}), - buildQueryFilter: jest.fn().mockReturnValue({}), - createQueryFilter: jest.fn().mockReturnValue({}), - handleAdvanceSearchClick: jest.fn(), - autocomplete: jest.fn(), - getQbConfigs: jest.fn().mockReturnValue({}), - }, -})); - const Children = () => { const { toggleModal, onResetAllFilters } = useAdvanceSearch(); @@ -101,40 +105,68 @@ const mockWithAdvanceSearch = const ComponentWithProvider = mockWithAdvanceSearch(Children); -describe.skip('AdvanceSearchProvider component', () => { - it('should render the AdvanceSearchModal as close by default', () => { - render(); +describe('AdvanceSearchProvider component', () => { + // Fake timers are enabled globally, so user-event must be told how to advance + // them, otherwise its internal delays never resolve and clicks hang. + const setupUser = () => + userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); - expect(screen.getByText('AdvanceSearchModal Close')).toBeInTheDocument(); + it('should render the provider children with the modal closed by default', async () => { + await act(async () => { + render(); + }); + + expect(screen.getByText('Open AdvanceSearch Modal')).toBeInTheDocument(); + // The modal is only mounted when it is opened, so nothing modal related + // should be present on the initial render. + expect(screen.queryByText('AdvanceSearchModal Open')).toBeNull(); + expect(screen.queryByText('Apply Advance Search')).toBeNull(); }); - it('should call mockPush after submit advance search form', async () => { - render(); + it('should open the AdvanceSearchModal on call of toggleModal with true', async () => { + const user = setupUser(); + await act(async () => { + render(); + }); - userEvent.click(screen.getByText('Apply Advance Search')); + expect(screen.queryByText('AdvanceSearchModal Open')).toBeNull(); - expect(mockNavigate).toHaveBeenCalled(); + await user.click(screen.getByText('Open AdvanceSearch Modal')); + + expect( + await screen.findByText('AdvanceSearchModal Open') + ).toBeInTheDocument(); }); - it('should open the AdvanceSearchModal on call of toggleModal with true', async () => { + it('should call navigate after submitting the advance search form', async () => { + const user = setupUser(); await act(async () => { render(); }); - expect(screen.getByText('AdvanceSearchModal Close')).toBeInTheDocument(); + await user.click(screen.getByText('Open AdvanceSearch Modal')); - userEvent.click(screen.getByText('Open AdvanceSearch Modal')); + const applyButton = await screen.findByText('Apply Advance Search'); - expect(screen.getByText('AdvanceSearchModal Open')).toBeInTheDocument(); + mockNavigate.mockClear(); + + await user.click(applyButton); + + expect(mockNavigate).toHaveBeenCalled(); }); - it('onResetAllFilters call mockPush should be called', async () => { + it('onResetAllFilters should navigate to the reset filters search params', async () => { + const user = setupUser(); await act(async () => { render(); }); - userEvent.click(screen.getByText('Reset All Filters')); + mockNavigate.mockClear(); - expect(mockNavigate).toHaveBeenCalledWith(-1); + await user.click(screen.getByText('Reset All Filters')); + + expect(mockNavigate).toHaveBeenCalledWith( + expect.objectContaining({ pathname: ROUTES.EXPLORE }) + ); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryUpdateConfirmationModal/GlossaryUpdateConfirmationModal.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryUpdateConfirmationModal/GlossaryUpdateConfirmationModal.test.tsx index e60a21f3e36e..27b10c9692f2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryUpdateConfirmationModal/GlossaryUpdateConfirmationModal.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryUpdateConfirmationModal/GlossaryUpdateConfirmationModal.test.tsx @@ -70,7 +70,7 @@ describe('GlossaryUpdateConfirmationModal component', () => { expect(mockOnCancel).toHaveBeenCalled(); }); - it.skip('should call validation api on clicking on yes, confirm button', async () => { + it('should call validation api on clicking on yes, confirm button', async () => { const { findByText } = render( { return jest.fn().mockImplementation(() => ({ pathname: 'mlmodel' })); }); -jest.mock('react-router-dom', () => ({ - useParams: jest.fn().mockImplementation(() => mockParams), +jest.mock('../../../utils/useRequiredParams', () => ({ + useRequiredParams: jest.fn().mockImplementation(() => mockParams), })); -jest.mock('../../common/TabsLabel/TabsLabel.component', () => { - return jest.fn().mockImplementation(({ name }) =>

{name}

); -}); +jest.mock('../../../hooks/useFqn', () => ({ + useFqn: jest.fn().mockReturnValue({ + fqn: 'mlflow_svc.eta_predictions', + entityFqn: 'mlflow_svc.eta_predictions', + }), +})); -jest.mock('../../common/EntityDescription/Description', () => { - return jest.fn().mockReturnValue(

Description

); -}); +jest.mock('../../../hooks/useApplicationStore', () => ({ + useApplicationStore: jest.fn().mockReturnValue({ + currentUser: { id: 'testUser' }, + }), +})); + +jest.mock('../../../hooks/useCustomPages', () => ({ + useCustomPages: jest.fn().mockReturnValue({ + customizedPage: undefined, + isLoading: false, + }), +})); + +jest.mock('../../../context/PermissionProvider/PermissionProvider', () => ({ + usePermissionProvider: jest.fn().mockImplementation(() => ({ + getEntityPermission: jest.fn().mockResolvedValue({ + ViewAll: true, + ViewBasic: true, + }), + })), +})); + +jest.mock('../../../utils/FeedUtilsPure', () => ({ + fetchEntityActivityCountInto: jest.fn(), + fetchEntityTaskCountsInto: jest.fn(), + getFeedCounts: jest.fn(), +})); + +jest.mock('../../AppRouter/withActivityFeed', () => ({ + withActivityFeed: jest.fn().mockImplementation((component) => component), +})); -jest.mock('../../Lineage/Lineage.component', () => { - return jest.fn().mockReturnValue(

EntityLineage.component

); +jest.mock('../../../hoc/LimitWrapper', () => { + return jest.fn().mockImplementation(({ children }) =>
{children}
); }); -jest.mock('./MlModelFeaturesList', () => { - return jest.fn().mockReturnValue(

MlModelFeaturesList

); +jest.mock( + '../../DataAssets/DataAssetsHeader/DataAssetsHeader.component', + () => ({ + DataAssetsHeader: jest.fn().mockReturnValue(
DataAssetsHeader
), + }) +); + +jest.mock('../../Customization/GenericProvider/GenericProvider', () => ({ + GenericProvider: jest + .fn() + .mockImplementation(({ children }) =>
{children}
), +})); + +jest.mock('../../Customization/GenericTab/GenericTab', () => ({ + GenericTab: jest.fn().mockReturnValue(
GenericTab
), +})); + +jest.mock('../../Lineage/EntityLineageTab/EntityLineageTab', () => ({ + EntityLineageTab: jest.fn().mockReturnValue(
EntityLineageTab
), +})); + +jest.mock('../../common/ErrorWithPlaceholder/ErrorPlaceHolder', () => { + return jest.fn().mockReturnValue(
ErrorPlaceHolder
); }); -jest.mock('../../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel', () => { - return jest.fn().mockReturnValue(

ActivityThreadPanel

); +jest.mock('../../common/TabsLabel/TabsLabel.component', () => { + return jest.fn().mockImplementation(({ name }) =>

{name}

); }); jest.mock('../../PageLayoutV1/PageLayoutV1', () => { @@ -225,36 +277,26 @@ jest.mock('../../../utils/TablePureUtils', () => { }; }); -jest.mock('../../ActivityFeed/FeedEditor/FeedEditor', () => { - return jest.fn().mockReturnValue(

FeedEditor.component

); -}); - jest.mock('../../common/CustomPropertyTable/CustomPropertyTable', () => ({ CustomPropertyTable: jest .fn() .mockReturnValue(

CustomPropertyTable.component

), })); -describe.skip('Test MlModel entity detail component', () => { +describe('Test MlModel entity detail component', () => { it('Should render detail component', async () => { + mockParams.tab = EntityTabs.FEATURES; const { container } = render(, { wrapper: MemoryRouter, }); - const detailContainer = await findByTestId(container, 'mlmodel-details'); - + const dataAssetsHeader = await findByText(container, 'DataAssetsHeader'); const entityTabs = await findByTestId(container, 'tabs'); - const entityFeatureList = await findByText( - container, - /MlModelFeaturesList/i - ); - const entityDescription = await findByText(container, /Description/i); - - expect(detailContainer).toBeInTheDocument(); + const featuresTab = await findByText(container, 'GenericTab'); + expect(dataAssetsHeader).toBeInTheDocument(); expect(entityTabs).toBeInTheDocument(); - expect(entityFeatureList).toBeInTheDocument(); - expect(entityDescription).toBeInTheDocument(); + expect(featuresTab).toBeInTheDocument(); }); it('Should render hyper parameter and ml store table for details tab', async () => { @@ -274,13 +316,13 @@ describe.skip('Test MlModel entity detail component', () => { } ); - const detailContainer = await findByTestId(container, 'mlmodel-details'); + const entityTabs = await findByTestId(container, 'tabs'); const emptyTablePlaceholder = await findAllByText( container, 'ErrorPlaceHolder' ); - expect(detailContainer).toBeInTheDocument(); + expect(entityTabs).toBeInTheDocument(); expect(emptyTablePlaceholder).toHaveLength(2); }); @@ -290,7 +332,6 @@ describe.skip('Test MlModel entity detail component', () => { wrapper: MemoryRouter, }); - const detailContainer = await findByTestId(container, 'mlmodel-details'); const hyperMetereTable = await findByTestId( container, 'hyperparameters-table' @@ -298,7 +339,6 @@ describe.skip('Test MlModel entity detail component', () => { const mlStoreTable = await findByTestId(container, 'model-store-table'); - expect(detailContainer).toBeInTheDocument(); expect(hyperMetereTable).toBeInTheDocument(); expect(mlStoreTable).toBeInTheDocument(); }); @@ -309,9 +349,9 @@ describe.skip('Test MlModel entity detail component', () => { wrapper: MemoryRouter, }); - const detailContainer = await findByTestId(container, 'lineage-details'); + const lineageTab = await findByText(container, 'EntityLineageTab'); - expect(detailContainer).toBeInTheDocument(); + expect(lineageTab).toBeInTheDocument(); }); it('Check if active tab is custom properties', async () => { @@ -338,19 +378,12 @@ describe.skip('Test MlModel entity detail component', () => { wrapper: MemoryRouter, } ); - const detailContainer = await findByTestId(container, 'mlmodel-details'); - const entityInfo = await findByText(container, /EntityPageInfo/i); + const dataAssetsHeader = await findByText(container, 'DataAssetsHeader'); const entityTabs = await findByTestId(container, 'tabs'); - const entityFeatureList = await findByText( - container, - /MlModelFeaturesList/i - ); - const entityDescription = await findByText(container, /Description/i); + const featuresTab = await findByText(container, 'GenericTab'); - expect(detailContainer).toBeInTheDocument(); - expect(entityInfo).toBeInTheDocument(); + expect(dataAssetsHeader).toBeInTheDocument(); expect(entityTabs).toBeInTheDocument(); - expect(entityFeatureList).toBeInTheDocument(); - expect(entityDescription).toBeInTheDocument(); + expect(featuresTab).toBeInTheDocument(); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/NextPreviousWithOffset/NextPreviousWithOffset.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/NextPreviousWithOffset/NextPreviousWithOffset.test.tsx index 1dabc4182f6e..8563b4e8931c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/NextPreviousWithOffset/NextPreviousWithOffset.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/NextPreviousWithOffset/NextPreviousWithOffset.test.tsx @@ -82,7 +82,7 @@ describe('NextPreviousWithOffset', () => { expect(screen.getByText('10 / label.page')).toBeInTheDocument(); }); - it.skip('should call onShowSizeChange with correct size when page size is changed', async () => { + it('should call onShowSizeChange with correct size when page size is changed', async () => { const mockOnShowSizeChange = jest.fn(); const props = { ...defaultProps, @@ -91,14 +91,14 @@ describe('NextPreviousWithOffset', () => { }; render(); - const pageSizeButton = screen.getByText('15 / label.page'); + const pageSizeButton = screen.getByTestId('page-size-change-button'); await act(async () => { - fireEvent.click(pageSizeButton); + fireEvent.mouseEnter(pageSizeButton); }); - const pageOption25 = screen.getByText('25 / label.page', { - selector: '.ant-dropdown-menu-item', + const pageOption25 = await screen.findByText('25 / label.page', { + selector: '.ant-dropdown-menu-title-content', }); await act(async () => { @@ -107,13 +107,13 @@ describe('NextPreviousWithOffset', () => { expect(mockOnShowSizeChange).toHaveBeenCalledWith(25); - const pageSizeButton2 = screen.getByText('25 / label.page'); - await act(async () => { - fireEvent.click(pageSizeButton2); + fireEvent.mouseEnter(pageSizeButton); }); - const pageOption50 = await screen.findByText('50 / label.page'); + const pageOption50 = await screen.findByText('50 / label.page', { + selector: '.ant-dropdown-menu-title-content', + }); await act(async () => { fireEvent.click(pageOption50); diff --git a/openmetadata-ui/src/main/resources/ui/src/mocks/Queries.mock.ts b/openmetadata-ui/src/main/resources/ui/src/mocks/Queries.mock.ts index aba962367d1c..6d2ae867419b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/mocks/Queries.mock.ts +++ b/openmetadata-ui/src/main/resources/ui/src/mocks/Queries.mock.ts @@ -56,9 +56,9 @@ export const MOCK_QUERIES = [ { id: 'cdccaedd-ed02-4c89-bc1a-1c4cd679d1e3', type: 'user', - name: 'shailesh.parmar', - fullyQualifiedName: 'shailesh.parmar', - displayName: 'ShaileshParmar', + name: 'test-user', + fullyQualifiedName: 'test-user', + displayName: 'Test User', deleted: false, }, ], @@ -213,9 +213,9 @@ export const MOCK_QUERIES = [ { id: 'cdccaedd-ed02-4c89-bc1a-1c4cd679d1e3', type: 'user', - name: 'shailesh.parmar', - fullyQualifiedName: 'shailesh.parmar', - displayName: 'ShaileshParmar', + name: 'test-user', + fullyQualifiedName: 'test-user', + displayName: 'Test User', deleted: false, }, ], diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.test.tsx index 022402c26baa..8cd6050a2bf1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.test.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jest/no-disabled-tests */ /* * Copyright 2022 Collate. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +23,6 @@ import { waitFor, waitForElementToBeRemoved, } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; import { MemoryRouter } from 'react-router-dom'; import ResizableLeftPanels from '../../components/common/ResizablePanels/ResizableLeftPanels'; import { deleteTag, getAllClassifications } from '../../rest/tagAPI'; @@ -680,8 +678,7 @@ describe('Test TagsPage page', () => { expect(editIcon).not.toBeInTheDocument(); }); - // api is not working for this feature - it.skip('User classification should be renamed', async () => { + it('User classification should be renamed', async () => { (getClassifications as jest.Mock).mockImplementationOnce(() => Promise.resolve({ data: [mockCategory[1]] }) ); @@ -691,31 +688,29 @@ describe('Test TagsPage page', () => { const tagsComponent = screen.getByTestId('tags-container'); const header = screen.getByTestId('header'); const leftPanelContent = screen.getByTestId('tags-left-panel'); - const editIcon = screen.getByTestId('name-edit-icon'); - const tagCategoryName = screen.getByTestId('classification-name'); expect(tagsComponent).toBeInTheDocument(); expect(header).toBeInTheDocument(); expect(leftPanelContent).toBeInTheDocument(); - expect(editIcon).toBeInTheDocument(); - expect(tagCategoryName).toBeInTheDocument(); - fireEvent.click(editIcon); + // A user (non-system) classification exposes the Edit action in the + // manage dropdown, which opens the classification edit drawer where the + // name/displayName can be renamed. + const manageButton = screen.getByTestId('manage-button'); - const tagCategoryHeading = screen.getByTestId( - 'current-classification-name' - ); - const cancelAssociatedTag = screen.getByTestId('cancelAssociatedTag'); - const saveAssociatedTag = screen.getByTestId('saveAssociatedTag'); + expect(manageButton).toBeInTheDocument(); + + fireEvent.click(manageButton); + + const editOption = await screen.findByTestId('edit-classification'); - expect(tagCategoryHeading).toBeInTheDocument(); - expect(cancelAssociatedTag).toBeInTheDocument(); - expect(saveAssociatedTag).toBeInTheDocument(); + expect(editOption).toBeInTheDocument(); - await userEvent.clear(tagCategoryHeading); - await userEvent.type(tagCategoryHeading, 'newPII'); + fireEvent.click(editOption); - expect(tagCategoryHeading).toHaveValue('newPII'); + expect( + await screen.findByTestId('classification-form-drawer') + ).toBeInTheDocument(); }); it('User tag should be load', async () => { @@ -750,7 +745,7 @@ describe('Test TagsPage page', () => { }); describe('Render Sad Paths', () => { - it.skip('Show error message on failing of deleteTag API', async () => { + it('Show error message on failing of deleteTag API', async () => { (deleteTag as jest.Mock).mockImplementationOnce(() => Promise.reject(new Error('Error!')) ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.test.tsx index a2abf1cc207f..e6228194be42 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.test.tsx @@ -32,7 +32,20 @@ jest.mock('../../components/MyData/LeftSidebar/LeftSidebar.component', () => ); jest.mock('../../components/Settings/Users/Users.component', () => - jest.fn().mockReturnValue(

User Component

) + jest.fn().mockImplementation(({ updateUserDetails, afterDeleteAction }) => ( +
+

User Component

+ + +
+ )) ); jest.mock('../../components/PageLayoutV1/PageLayoutV1', () => @@ -71,7 +84,7 @@ jest.mock('../../rest/userAPI', () => ({ ), })); -describe.skip('Test the User Page', () => { +describe('Test the User Page', () => { it('Should call getUserByName API on load', async () => { render(, { wrapper: MemoryRouter }); @@ -81,6 +94,8 @@ describe.skip('Test the User Page', () => { 'roles', 'teams', 'personas', + 'lastActivityTime', + 'lastLoginTime', 'defaultPersona', 'domains', ], From cd1e3b8c76e95fee53066c05bfcf546bda930417 Mon Sep 17 00:00:00 2001 From: Karan Hotchandani <33024356+karanh37@users.noreply.github.com> Date: Mon, 31 Aug 2026 07:36:08 +0000 Subject: [PATCH 08/83] fix(security): bump jsoup to 1.23.2 (#32266) CVE-2026-75140 (CVSS 8.7, CWE-770): jsoup's XmlTreeBuilder copies the whole inherited namespace map on every start element, so a deeply nested XML document with uniquely-namespaced elements costs quadratic time and memory. A remote attacker can drive the JVM to OutOfMemoryError and terminate the application. The fix is jsoup PR #2556 (commit 862ba2f, "Optimize XML namespace scope tracking"), which ships in the 1.23.2 release of 2026-08-26. Earlier triage runs classified this unfixable because at the time the fix existed only as an unreleased commit. jsoup is not declared by any module; it reaches openmetadata-service solely through com.vladsch.flexmark:flexmark-html2md-converter 0.64.8, which declares 1.15.4 as a soft requirement. 0.64.8 is flexmark's latest release, so managing jsoup in the root dependencyManagement is the only available fix. Co-authored-by: Claude Opus 5 (1M context) --- pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 5040e2ad45f1..061ccdfabb81 100644 --- a/pom.xml +++ b/pom.xml @@ -855,6 +855,17 @@ commons-compress 1.26.0
+ + + org.jsoup + jsoup + 1.23.2 + org.bouncycastle bcpkix-jdk18on From 4b2927a86a2f0736a5017f687d910434f6a77670 Mon Sep 17 00:00:00 2001 From: Karan Hotchandani <33024356+karanh37@users.noreply.github.com> Date: Mon, 31 Aug 2026 08:45:06 +0000 Subject: [PATCH 09/83] fix(security): bump qs to 6.16.0 (#32265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump qs from 6.15.2 to 6.16.0 in the openmetadata-ui workspace to clear two medium Snyk findings, both fixed in qs 6.16.0: - CVE-2026-82562 (SNYK-JS-QS-19432017) — Allocation of Resources Without Limits or Throttling in parseArrayValue() under comma: true. - CVE-2026-82417 (SNYK-JS-QS-19432019) — Uncaught Exception in isBuffer() reachable from stringify() under plainObjects/allowPrototypes. Neither advisory's precondition is present in this source tree, so this is a dependency-hygiene bump rather than a fix for a reachable exploit. A resolutions pin was also added because the transitive requester url -> qs@^6.12.3 otherwise kept resolving to the old 6.15.2; the pin collapses it to a single 6.16.0 entry so no vulnerable copy remains. OSS-side counterpart to open-metadata/openmetadata-collate#6278. Co-authored-by: Claude Opus 4.8 (1M context) --- .../src/main/resources/ui/package.json | 3 ++- .../src/main/resources/ui/yarn.lock | 24 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/package.json b/openmetadata-ui/src/main/resources/ui/package.json index b8345237c4b1..b33d095bf031 100644 --- a/openmetadata-ui/src/main/resources/ui/package.json +++ b/openmetadata-ui/src/main/resources/ui/package.json @@ -141,7 +141,7 @@ "luxon": "^3.2.1", "oidc-client": "^1.11.5", "process": "^0.11.10", - "qs": "6.15.2", + "qs": "6.16.0", "quill-mention": "^6.0.1", "quilljs-markdown": "^1.2.0", "rapidoc": "^9.3.8", @@ -302,6 +302,7 @@ "clean-css": "4.1.11", "path-to-regexp": "1.9.0", "cookie": "0.7.0", + "qs": "6.16.0", "cross-spawn": "7.0.5", "serialize-javascript": "7.0.5", "@melloware/react-logviewer/immutable": "5.1.9", diff --git a/openmetadata-ui/src/main/resources/ui/yarn.lock b/openmetadata-ui/src/main/resources/ui/yarn.lock index 11040e35a666..0064e78bfca4 100644 --- a/openmetadata-ui/src/main/resources/ui/yarn.lock +++ b/openmetadata-ui/src/main/resources/ui/yarn.lock @@ -10726,12 +10726,13 @@ pvutils@^1.1.5: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.5.tgz#84b0dea4a5d670249aa9800511804ee0b7c2809c" integrity sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA== -qs@6.15.2, qs@^6.12.3: - version "6.15.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.2.tgz#fd55426d710403ddccc45e0f9eab16db7727ece9" - integrity sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw== +qs@6.16.0, qs@^6.12.3: + version "6.16.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.16.0.tgz#c22c723a28a920f3aacdce8289fabd43eccb79fd" + integrity sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA== dependencies: - side-channel "^1.1.0" + es-define-property "^1.0.1" + side-channel "^1.1.1" querystring-es3@^0.2.1: version "0.2.1" @@ -12099,7 +12100,7 @@ showdown@^2.1.0: dependencies: commander "^9.0.0" -side-channel-list@^1.0.0: +side-channel-list@^1.0.0, side-channel-list@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== @@ -12139,6 +12140,17 @@ side-channel@^1.0.4, side-channel@^1.1.0: side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" +side-channel@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.1.tgz#ea02c62e05dc4bea67d4442f0fb71ee192f8e0ab" + integrity sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.4" + side-channel-list "^1.0.1" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" From 93af7c789d2b54b2fb6e42ab3dc81a07a4569058 Mon Sep 17 00:00:00 2001 From: Mohit Tilala <63147650+mohittilala@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:59:46 +0000 Subject: [PATCH 10/83] Fixes 32206: stop linking a table to itself from the Databricks system lineage tables (#32214) * Fixes #32206: stop linking a table to itself from the Databricks system lineage tables system.access.table_lineage records table access rather than derivation, so a streaming or CDC write legitimately names its target table as its own source. The Databricks Pipeline and Unity Catalog connectors both passed those rows straight through, producing an edge from a table to itself that renders as a loop and carries no information. Skip rows where source and target are the same table, matching the guard the SQL DLT parser already applies. * fix(unitycatalog): skip self-referencing rows in the column lineage cache too The table pair they belong to is dropped, so the cached columns can never be read. They only grow column_lineage_map and inflate the cached-lineage counts in the log. --- .../source/database/unitycatalog/lineage.py | 10 ++ .../pipeline/databrickspipeline/metadata.py | 8 ++ ...t_unitycatalog_self_referencing_lineage.py | 111 +++++++++++++++++ ...est_databricks_self_referencing_lineage.py | 115 ++++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 ingestion/tests/unit/topology/database/test_unitycatalog_self_referencing_lineage.py create mode 100644 ingestion/tests/unit/topology/pipeline/test_databricks_self_referencing_lineage.py diff --git a/ingestion/src/metadata/ingestion/source/database/unitycatalog/lineage.py b/ingestion/src/metadata/ingestion/source/database/unitycatalog/lineage.py index a5d9fbca5208..eff863bf0ec5 100644 --- a/ingestion/src/metadata/ingestion/source/database/unitycatalog/lineage.py +++ b/ingestion/src/metadata/ingestion/source/database/unitycatalog/lineage.py @@ -120,6 +120,12 @@ def _cache_lineage(self): with self.engine.connect() as conn: rows = conn.execute(text(UNITY_CATALOG_TABLE_LINEAGE.format(query_log_duration=query_log_duration))) for row in rows: + # A table never derives from itself. The system tables record + # access rather than derivation, so a streaming or CDC write + # legitimately names its target as its own source. Kept as + # lineage it renders as a loop on the node and says nothing. + if row.source_table_full_name == row.target_table_full_name: + continue self.table_lineage_map[row.target_table_full_name].add(row.source_table_full_name) logger.info( f"Cached table lineage: {sum(len(v) for v in self.table_lineage_map.values())} edges " @@ -133,6 +139,10 @@ def _cache_lineage(self): with self.engine.connect() as conn: rows = conn.execute(text(UNITY_CATALOG_COLUMN_LINEAGE.format(query_log_duration=query_log_duration))) for row in rows: + # The table pair this belongs to is dropped above, so caching the + # columns only grows the map with entries nothing can read. + if row.source_table_full_name == row.target_table_full_name: + continue table_key = ( row.source_table_full_name, row.target_table_full_name, diff --git a/ingestion/src/metadata/ingestion/source/pipeline/databrickspipeline/metadata.py b/ingestion/src/metadata/ingestion/source/pipeline/databrickspipeline/metadata.py index 39350d1fafb7..c143dc9597b4 100644 --- a/ingestion/src/metadata/ingestion/source/pipeline/databrickspipeline/metadata.py +++ b/ingestion/src/metadata/ingestion/source/pipeline/databrickspipeline/metadata.py @@ -1098,6 +1098,14 @@ def yield_pipeline_lineage_details( if not (source_table_full_name and target_table_full_name): continue + # A table never derives from itself. The system tables record + # access rather than derivation, so a streaming or CDC write + # legitimately names its target as its own source. Kept as + # lineage it renders as a loop on the node and says nothing. + if source_table_full_name == target_table_full_name: + logger.debug(f"Skipping self-referencing lineage row for {source_table_full_name}") + continue + source = fqn.split_table_name(source_table_full_name) target = fqn.split_table_name(target_table_full_name) for dbservicename in self.get_db_service_names() or ["*"]: diff --git a/ingestion/tests/unit/topology/database/test_unitycatalog_self_referencing_lineage.py b/ingestion/tests/unit/topology/database/test_unitycatalog_self_referencing_lineage.py new file mode 100644 index 000000000000..a33fff3ea7d5 --- /dev/null +++ b/ingestion/tests/unit/topology/database/test_unitycatalog_self_referencing_lineage.py @@ -0,0 +1,111 @@ +# Copyright 2025 Collate +# Licensed under the Collate Community License, Version 1.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# https://github.com/open-metadata/OpenMetadata/blob/main/ingestion/LICENSE +# 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. +""" +A table is never cached as its own upstream. + +`system.access.table_lineage` records table access rather than derivation, so a +streaming or CDC write legitimately names its target table as its own source. +Those rows must not reach the lineage map, or the table ends up in its own +upstream set and is later emitted as an edge pointing at itself. +""" + +from collections import defaultdict +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +from metadata.ingestion.source.database.unitycatalog.lineage import ( + UnitycatalogLineageSource, +) + +CATALOG, SCHEMA = "analytics", "sales" +EVENT_LOG = f"{CATALOG}.{SCHEMA}.orders_event_log" +SNAPSHOT = f"{CATALOG}.{SCHEMA}.orders_snapshot" + + +def _row(source_table: str, target_table: str) -> SimpleNamespace: + return SimpleNamespace(source_table_full_name=source_table, target_table_full_name=target_table) + + +def _column_row(source_table: str, target_table: str, column: str) -> SimpleNamespace: + return SimpleNamespace( + source_table_full_name=source_table, + target_table_full_name=target_table, + source_column_name=column, + target_column_name=column, + ) + + +def _source(rows, column_rows=None): + """The real caching method, with only the SQL connection stubbed.""" + with patch.object(UnitycatalogLineageSource, "__init__", lambda s: None): + source = UnitycatalogLineageSource() + + source.table_lineage_map = defaultdict(set) + source.source_config = MagicMock() + source.source_config.queryLogDuration = 1 + + source.column_lineage_map = defaultdict(list) + + connection = MagicMock() + # _cache_lineage runs the table query first, then the column query + connection.execute.side_effect = [rows, column_rows if column_rows is not None else []] + engine = MagicMock() + engine.connect.return_value.__enter__ = MagicMock(return_value=connection) + engine.connect.return_value.__exit__ = MagicMock(return_value=False) + source.engine = engine + return source + + +class TestSelfReferencingLineageCache: + def test_a_self_referencing_row_is_not_cached(self): + source = _source([_row(EVENT_LOG, EVENT_LOG)]) + source._cache_lineage() + assert EVENT_LOG not in source.table_lineage_map.get(EVENT_LOG, set()) + assert sum(len(v) for v in source.table_lineage_map.values()) == 0 + + def test_a_normal_row_is_still_cached(self): + source = _source([_row(EVENT_LOG, SNAPSHOT)]) + source._cache_lineage() + assert source.table_lineage_map[SNAPSHOT] == {EVENT_LOG} + + def test_only_the_self_reference_is_dropped(self): + """The guard must not suppress real upstreams of the same table.""" + source = _source( + [ + _row(EVENT_LOG, SNAPSHOT), + _row(SNAPSHOT, SNAPSHOT), + _row(EVENT_LOG, EVENT_LOG), + ] + ) + source._cache_lineage() + assert source.table_lineage_map[SNAPSHOT] == {EVENT_LOG} + assert source.table_lineage_map.get(EVENT_LOG, set()) == set() + + +class TestSelfReferencingColumnLineageCache: + """A self-pair's columns are unreadable once its table pair is dropped.""" + + def test_self_referencing_columns_are_not_cached(self): + source = _source( + [_row(EVENT_LOG, EVENT_LOG)], + column_rows=[_column_row(EVENT_LOG, EVENT_LOG, "id")], + ) + source._cache_lineage() + assert (EVENT_LOG, EVENT_LOG) not in source.column_lineage_map + assert sum(len(v) for v in source.column_lineage_map.values()) == 0 + + def test_normal_columns_are_still_cached(self): + source = _source( + [_row(EVENT_LOG, SNAPSHOT)], + column_rows=[_column_row(EVENT_LOG, SNAPSHOT, "id")], + ) + source._cache_lineage() + assert source.column_lineage_map[(EVENT_LOG, SNAPSHOT)] == [("id", "id")] diff --git a/ingestion/tests/unit/topology/pipeline/test_databricks_self_referencing_lineage.py b/ingestion/tests/unit/topology/pipeline/test_databricks_self_referencing_lineage.py new file mode 100644 index 000000000000..31581e14d6ae --- /dev/null +++ b/ingestion/tests/unit/topology/pipeline/test_databricks_self_referencing_lineage.py @@ -0,0 +1,115 @@ +# Copyright 2025 Collate +# Licensed under the Collate Community License, Version 1.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# https://github.com/open-metadata/OpenMetadata/blob/main/ingestion/LICENSE +# 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. +""" +A table is never linked to itself. + +`system.access.table_lineage` records table access rather than derivation, so a +streaming or CDC write legitimately names its target table as its own source. +Carried through as lineage it renders as a loop on the node and tells the reader +nothing, so those rows are dropped before an edge is built. +""" + +import uuid +from unittest.mock import MagicMock, patch + +from metadata.generated.schema.entity.data.table import Table +from metadata.ingestion.source.pipeline.databrickspipeline.metadata import ( + DatabrickspipelineSource, +) +from metadata.ingestion.source.pipeline.databrickspipeline.models import ( + DataBrickPipelineDetails, +) + +CATALOG, SCHEMA = "analytics", "sales" +EVENT_LOG = f"{CATALOG}.{SCHEMA}.orders_event_log" +SNAPSHOT = f"{CATALOG}.{SCHEMA}.orders_snapshot" + + +def _table(fqn: str) -> Table: + table = MagicMock(spec=Table) + table.id = uuid.uuid4() + table.fullyQualifiedName = fqn + table.name = fqn.rsplit(".", 1)[-1] + table.columns = [] + return table + + +def _source(table_lineage_rows): + """The real connector with the Databricks and OpenMetadata sides stubbed.""" + with patch.object(DatabrickspipelineSource, "__init__", lambda s, a, b: None): + source = DatabrickspipelineSource(None, None) + + source.client = MagicMock() + source.client.get_table_lineage.return_value = table_lineage_rows + source.client.get_column_lineage.return_value = [] + source.context = MagicMock() + source.get_db_service_names = MagicMock(return_value=["unity"]) + source._table_lookup_cache = {} + source._yield_kafka_lineage = MagicMock(return_value=iter(())) + + pipeline_entity = MagicMock() + pipeline_entity.id.root = uuid.uuid4() + + def get_by_name(entity=None, fqn=None, **_): + # every table resolves, so a missing edge can only be the self-reference guard + return pipeline_entity if entity is not Table else _table(str(fqn)) + + source.metadata = MagicMock() + source.metadata.get_by_name.side_effect = get_by_name + return source + + +def _edges(source): + details = DataBrickPipelineDetails(pipeline_id="11111111-2222-3333-4444-555555555555", name="orders") + with patch( + "metadata.ingestion.source.pipeline.databrickspipeline.metadata.fqn.build", + side_effect=lambda **kwargs: ( + f"{kwargs.get('service_name')}.{kwargs.get('database_name')}." + f"{kwargs.get('schema_name')}.{kwargs.get('table_name')}" + if kwargs.get("table_name") + else "svc.pipeline" + ), + ): + results = list(source.yield_pipeline_lineage_details(details)) + return [r.right for r in results if getattr(r, "right", None) is not None] + + +class TestSelfReferencingTableLineage: + def test_a_self_referencing_row_yields_no_edge(self): + source = _source([{"source_table_full_name": EVENT_LOG, "target_table_full_name": EVENT_LOG}]) + assert _edges(source) == [] + + def test_a_normal_row_still_yields_an_edge(self): + source = _source([{"source_table_full_name": EVENT_LOG, "target_table_full_name": SNAPSHOT}]) + assert len(_edges(source)) == 1 + + def test_only_the_self_reference_is_dropped(self): + """The guard must not suppress real lineage produced by the same pipeline.""" + source = _source( + [ + {"source_table_full_name": EVENT_LOG, "target_table_full_name": EVENT_LOG}, + {"source_table_full_name": EVENT_LOG, "target_table_full_name": SNAPSHOT}, + {"source_table_full_name": SNAPSHOT, "target_table_full_name": SNAPSHOT}, + ] + ) + edges = _edges(source) + assert len(edges) == 1 + edge = edges[0].edge + assert edge.fromEntity.id != edge.toEntity.id + + def test_rows_with_a_missing_name_are_still_skipped(self): + source = _source( + [ + {"source_table_full_name": None, "target_table_full_name": SNAPSHOT}, + {"source_table_full_name": EVENT_LOG, "target_table_full_name": None}, + ] + ) + assert _edges(source) == [] From 4d37a838b819bc22a4d5a11511738e3bcd52ff59 Mon Sep 17 00:00:00 2001 From: Tomas Montiel Prieto <57763803+tomasmontielp@users.noreply.github.com> Date: Mon, 31 Aug 2026 11:23:32 +0000 Subject: [PATCH 11/83] swap hybrid default values keyword vs semantic (#31968) * swap hybrid default values keyword vs semantic * migration for change * remove unneeded sql comments * greptile comment --- .../migration/mysql/v210/Migration.java | 2 + .../migration/postgres/v210/Migration.java | 2 + .../migration/utils/v210/MigrationUtil.java | 64 +++++++++++++- .../service/search/SearchRepository.java | 4 +- .../v210/HybridSearchWeightSwapTest.java | 88 +++++++++++++++++++ .../search/SearchRepositoryBehaviorTest.java | 2 +- .../elasticSearchConfiguration.json | 4 +- .../schema/configuration/searchSettings.json | 4 +- 8 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v210/HybridSearchWeightSwapTest.java diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v210/Migration.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v210/Migration.java index b20b2fabcb13..7b03340bce44 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v210/Migration.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v210/Migration.java @@ -15,6 +15,7 @@ import static org.openmetadata.service.jdbi3.locator.ConnectionType.MYSQL; import static org.openmetadata.service.migration.utils.v210.MigrationUtil.addCreateConversationRuleToDataConsumerPolicy; +import static org.openmetadata.service.migration.utils.v210.MigrationUtil.alignHybridSearchWeightsWithDefaults; import static org.openmetadata.service.migration.utils.v210.MigrationUtil.exemptQueryFromMultiDomainRules; import static org.openmetadata.service.migration.utils.v210.MigrationUtil.refreshConversationNotificationTemplates; import static org.openmetadata.service.migration.utils.v210.OntologyMigration.migrateRelationshipTypes; @@ -36,6 +37,7 @@ public void runDataMigration() { ConversationReferenceMigration.migrate(handle, MYSQL); refreshConversationNotificationTemplates(); addCreateConversationRuleToDataConsumerPolicy(collectionDAO); + alignHybridSearchWeightsWithDefaults(); new MigrationUtil(handle, MYSQL).archiveLegacyThreadStorage(); migrateRelationshipTypes(handle, MYSQL); // Reconcile the persisted entityRulesSettings so upgraded instances allow queries to carry the diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v210/Migration.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v210/Migration.java index cb040b50a974..a466b0abf3e3 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v210/Migration.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v210/Migration.java @@ -15,6 +15,7 @@ import static org.openmetadata.service.jdbi3.locator.ConnectionType.POSTGRES; import static org.openmetadata.service.migration.utils.v210.MigrationUtil.addCreateConversationRuleToDataConsumerPolicy; +import static org.openmetadata.service.migration.utils.v210.MigrationUtil.alignHybridSearchWeightsWithDefaults; import static org.openmetadata.service.migration.utils.v210.MigrationUtil.exemptQueryFromMultiDomainRules; import static org.openmetadata.service.migration.utils.v210.MigrationUtil.refreshConversationNotificationTemplates; import static org.openmetadata.service.migration.utils.v210.OntologyMigration.migrateRelationshipTypes; @@ -36,6 +37,7 @@ public void runDataMigration() { ConversationReferenceMigration.migrate(handle, POSTGRES); refreshConversationNotificationTemplates(); addCreateConversationRuleToDataConsumerPolicy(collectionDAO); + alignHybridSearchWeightsWithDefaults(); new MigrationUtil(handle, POSTGRES).archiveLegacyThreadStorage(); migrateRelationshipTypes(handle, POSTGRES); // Reconcile the persisted entityRulesSettings so upgraded instances allow queries to carry the diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v210/MigrationUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v210/MigrationUtil.java index 5e519fb95265..6de164399059 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v210/MigrationUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v210/MigrationUtil.java @@ -18,6 +18,8 @@ import java.util.List; import lombok.extern.slf4j.Slf4j; import org.jdbi.v3.core.Handle; +import org.openmetadata.schema.api.search.GlobalSettings; +import org.openmetadata.schema.api.search.SearchSettings; import org.openmetadata.schema.configuration.EntityRulesSettings; import org.openmetadata.schema.entity.policies.Policy; import org.openmetadata.schema.entity.policies.accessControl.Rule; @@ -34,13 +36,22 @@ import org.openmetadata.service.jdbi3.PolicyRepository; import org.openmetadata.service.jdbi3.SystemRepository; import org.openmetadata.service.jdbi3.locator.ConnectionType; +import org.openmetadata.service.migration.utils.SearchSettingsMergeUtil; -/** Migration utilities for the 2.1.0 Conversation V2 cutover and legacy thread archival. */ +/** + * Migration utilities for 2.1.0: the Conversation V2 cutover, legacy thread archival, and alignment + * of stored hybrid search weights with the shipped defaults. + */ @Slf4j public class MigrationUtil { private static final String DATA_CONSUMER_POLICY = "DataConsumerPolicy"; private static final String CREATE_CONVERSATION_RULE_NAME = "DataConsumerPolicy-CreateConversation-Rule"; + private static final double PREVIOUS_KEYWORD_WEIGHT = 0.4; + private static final double PREVIOUS_SEMANTIC_WEIGHT = 0.6; + private static final double KEYWORD_WEIGHT = 0.6; + private static final double SEMANTIC_WEIGHT = 0.4; + private static final double WEIGHT_TOLERANCE = 1e-9; private final Handle handle; private final ConnectionType connectionType; @@ -197,4 +208,55 @@ private boolean tableExists(String tableName) { return false; } } + + /** + * Aligns the hybrid search weights in the stored search settings with the shipped defaults. + * + *

The weights are seeded into the settings row from the schema defaults on first startup, so + * every installation carries an explicit pair that takes precedence over a later default. Only a + * pair equal to the previous default is rewritten; any other pair is an operator choice. + */ + public static void alignHybridSearchWeightsWithDefaults() { + try { + Settings storedSettings = SearchSettingsMergeUtil.getSearchSettingsFromDatabase(); + if (storedSettings == null) { + LOG.warn("Search settings not found in database; skipping hybrid weight alignment"); + } else { + alignStoredHybridWeights(storedSettings); + } + } catch (Exception e) { + LOG.error("Error aligning hybrid search weights in stored search settings", e); + } + } + + private static void alignStoredHybridWeights(Settings storedSettings) { + SearchSettings searchSettings = SearchSettingsMergeUtil.loadSearchSettings(storedSettings); + if (swapPreviousHybridWeights(searchSettings)) { + SearchSettingsMergeUtil.saveSearchSettings(storedSettings, searchSettings); + LOG.info( + "Hybrid search weights aligned to keyword={}, semantic={}", + KEYWORD_WEIGHT, + SEMANTIC_WEIGHT); + } else { + LOG.info("Stored hybrid search weights are not the previous defaults; left unchanged"); + } + } + + /** Returns true when the previous default pair was found and swapped. */ + public static boolean swapPreviousHybridWeights(SearchSettings searchSettings) { + GlobalSettings globalSettings = searchSettings.getGlobalSettings(); + boolean carriesPreviousDefaults = + globalSettings != null + && weightIs(globalSettings.getKeywordWeight(), PREVIOUS_KEYWORD_WEIGHT) + && weightIs(globalSettings.getSemanticWeight(), PREVIOUS_SEMANTIC_WEIGHT); + if (carriesPreviousDefaults) { + globalSettings.setKeywordWeight(KEYWORD_WEIGHT); + globalSettings.setSemanticWeight(SEMANTIC_WEIGHT); + } + return carriesPreviousDefaults; + } + + private static boolean weightIs(Double weight, double expected) { + return weight != null && Math.abs(weight - expected) < WEIGHT_TOLERANCE; + } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java index d3b62d658fe1..81345ad7d26a 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java @@ -943,9 +943,9 @@ public void ensureHybridSearchPipeline() { ElasticSearchConfiguration cfg = getSearchConfiguration(); NaturalLanguageSearchConfiguration nlConfig = cfg.getNaturalLanguageSearch(); - double keywordWeight = nlConfig.getKeywordWeight() != null ? nlConfig.getKeywordWeight() : 0.4; + double keywordWeight = nlConfig.getKeywordWeight() != null ? nlConfig.getKeywordWeight() : 0.6; double semanticWeight = - nlConfig.getSemanticWeight() != null ? nlConfig.getSemanticWeight() : 0.6; + nlConfig.getSemanticWeight() != null ? nlConfig.getSemanticWeight() : 0.4; try { SearchSettings ss = diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v210/HybridSearchWeightSwapTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v210/HybridSearchWeightSwapTest.java new file mode 100644 index 000000000000..1b472e0e72a8 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/migration/utils/v210/HybridSearchWeightSwapTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2024 Collate. + * 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. + */ +package org.openmetadata.service.migration.utils.v210; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.api.search.GlobalSettings; +import org.openmetadata.schema.api.search.SearchSettings; + +class HybridSearchWeightSwapTest { + + private SearchSettings settingsWithWeights(Double keywordWeight, Double semanticWeight) { + GlobalSettings globalSettings = new GlobalSettings(); + globalSettings.setKeywordWeight(keywordWeight); + globalSettings.setSemanticWeight(semanticWeight); + SearchSettings settings = new SearchSettings(); + settings.setGlobalSettings(globalSettings); + return settings; + } + + @Test + void swapsThePreviousDefaultPair() { + SearchSettings settings = settingsWithWeights(0.4, 0.6); + + assertTrue(MigrationUtil.swapPreviousHybridWeights(settings)); + + assertEquals(0.6, settings.getGlobalSettings().getKeywordWeight()); + assertEquals(0.4, settings.getGlobalSettings().getSemanticWeight()); + } + + @Test + void leavesOperatorTunedWeightsUntouched() { + SearchSettings settings = settingsWithWeights(0.7, 0.3); + + assertFalse(MigrationUtil.swapPreviousHybridWeights(settings)); + + assertEquals(0.7, settings.getGlobalSettings().getKeywordWeight()); + assertEquals(0.3, settings.getGlobalSettings().getSemanticWeight()); + } + + @Test + void isIdempotentOnAlreadySwappedWeights() { + SearchSettings settings = settingsWithWeights(0.6, 0.4); + + assertFalse(MigrationUtil.swapPreviousHybridWeights(settings)); + + assertEquals(0.6, settings.getGlobalSettings().getKeywordWeight()); + assertEquals(0.4, settings.getGlobalSettings().getSemanticWeight()); + } + + @Test + void leavesAHalfMatchingPairUntouched() { + SearchSettings settings = settingsWithWeights(0.4, 0.4); + + assertFalse(MigrationUtil.swapPreviousHybridWeights(settings)); + + assertEquals(0.4, settings.getGlobalSettings().getKeywordWeight()); + assertEquals(0.4, settings.getGlobalSettings().getSemanticWeight()); + } + + @Test + void toleratesAbsentWeights() { + SearchSettings settings = settingsWithWeights(null, null); + + assertFalse(MigrationUtil.swapPreviousHybridWeights(settings)); + + assertNull(settings.getGlobalSettings().getKeywordWeight()); + } + + @Test + void toleratesAbsentGlobalSettings() { + assertFalse(MigrationUtil.swapPreviousHybridWeights(new SearchSettings())); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchRepositoryBehaviorTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchRepositoryBehaviorTest.java index e76d73e1ff32..c046dc35ce9e 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchRepositoryBehaviorTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchRepositoryBehaviorTest.java @@ -3017,7 +3017,7 @@ void initializeVectorSearchServiceInitializesOpenSearchVectorSupport() throws Ex assertSame(embeddingClient, spyRepository.getEmbeddingClient()); assertSame(vectorService, spyRepository.getVectorIndexService()); assertNotNull(spyRepository.getVectorEmbeddingHandler()); - verify(vectorService).ensureHybridSearchPipeline(0.4, 0.6); + verify(vectorService).ensureHybridSearchPipeline(0.6, 0.4); } @Test diff --git a/openmetadata-spec/src/main/resources/json/schema/configuration/elasticSearchConfiguration.json b/openmetadata-spec/src/main/resources/json/schema/configuration/elasticSearchConfiguration.json index 3ad6c6d43c03..8b82702be3e2 100644 --- a/openmetadata-spec/src/main/resources/json/schema/configuration/elasticSearchConfiguration.json +++ b/openmetadata-spec/src/main/resources/json/schema/configuration/elasticSearchConfiguration.json @@ -190,12 +190,12 @@ "keywordWeight": { "description": "Weight for BM25 keyword search results in hybrid RRF pipeline (0.0-1.0)", "type": "number", - "default": 0.4 + "default": 0.6 }, "semanticWeight": { "description": "Weight for semantic vector search results in hybrid RRF pipeline (0.0-1.0)", "type": "number", - "default": 0.6 + "default": 0.4 }, "knnNumCandidatesMultiplier": { "description": "Multiplier applied to k when computing num_candidates for Elasticsearch kNN vector search. num_candidates = max(k * multiplier, 100). Higher values improve recall at the cost of latency. Defaults to 2.", diff --git a/openmetadata-spec/src/main/resources/json/schema/configuration/searchSettings.json b/openmetadata-spec/src/main/resources/json/schema/configuration/searchSettings.json index 3b230759da12..ae004fb91979 100644 --- a/openmetadata-spec/src/main/resources/json/schema/configuration/searchSettings.json +++ b/openmetadata-spec/src/main/resources/json/schema/configuration/searchSettings.json @@ -56,12 +56,12 @@ "keywordWeight": { "description": "Weight for BM25 keyword search in hybrid RRF pipeline (0.0-1.0)", "type": "number", - "default": 0.4 + "default": 0.6 }, "semanticWeight": { "description": "Weight for semantic vector search in hybrid RRF pipeline (0.0-1.0)", "type": "number", - "default": 0.6 + "default": 0.4 } }, "additionalProperties": false From 54d7f294a4b9f5b507070c8ebe86f010dec1eef7 Mon Sep 17 00:00:00 2001 From: Shailesh Parmar Date: Mon, 31 Aug 2026 12:02:18 +0000 Subject: [PATCH 12/83] test(playwright): page to the app card; anchor the steward switch (#32295) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test(playwright): page to the app card; anchor the steward switch Settings > Applications paginates at PAGE_SIZE_BASE (15). Adding RdfInferenceApp in #28042 took the bundled app count past that boundary and pushed the Search Indexing card to page 2, so four tests that clicked it without paging started failing as 60s click timeouts. LiveIndexingTab was already flaky on postgres before that — the suite was sitting exactly on the boundary. - add isOnAnyApplicationPage to playwright/utils/applications.ts and build findApplicationCard / expectApplicationInstalled / expectApplicationNotInstalled on it, so presence and absence are both asserted across every page rather than page 1. The installed list and the marketplace share a card testid and paging controls and differ only in the endpoint a page turn hits, so APPLICATION_LIST selects between them and installSearchIndexApplication's hand-rolled marketplace loop is gone - use them in LiveIndexingTab (including the Data Insights guard, which had the same latent bug) and SearchIndexApplication. The post-install toBeVisible() would itself have failed once the reinstall took the count back to 16; the post-uninstall toBeHidden() passed trivially whenever the card sat on a later page - TestDefinitionPermissions: target the definition the spec itself creates instead of getByRole('switch').first(). The Test Library is shared across the run and TestLibrary.spec.ts seeds AaaaExternalTest* to sort first; an external definition's toggle is disabled by design, so the positional locator asserted on a row this spec never owned - delete that definition in afterAll. It leaked before, which was harmless under .first() but not once the row's position is load-bearing: the Test Library is paginated with no search, so accumulated `aaa*` rows would eventually push the target off page 1 - prune the four now-unused positional-locator suppressions Co-Authored-By: Claude Opus 5 * test(playwright): lower the recorded no-positional-locator count The suppressions corpus test asserts exact per-rule totals, so pruning the baseline without lowering EXPECTED fails ui-checkstyle: not ok 25 - the suppressions baseline matches its recorded state exactly Four no-positional-locator suppressions were fixed in this branch — two in TestDefinitionPermissions and two in SearchIndexApplication, which now has no entry at all — so 1328 becomes 1324. Co-Authored-By: Claude Opus 5 --------- Co-authored-by: Claude Opus 5 --- .../resources/ui/eslint-suppressions.json | 7 +- .../TestDefinitionPermissions.spec.ts | 70 +++++++--- .../e2e/Pages/LiveIndexingTab.spec.ts | 38 +++--- .../e2e/Pages/SearchIndexApplication.spec.ts | 74 +++-------- .../eslint-rules/tests/corpus.test.mjs | 2 +- .../ui/playwright/utils/applications.ts | 121 +++++++++++++++++- 6 files changed, 209 insertions(+), 103 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json b/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json index 98ffe06bcd10..2b80843a6637 100644 --- a/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json +++ b/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json @@ -262,7 +262,7 @@ }, "playwright/e2e/Features/DataQuality/TestDefinitionPermissions.spec.ts": { "om-playwright/no-positional-locator": { - "count": 5 + "count": 3 } }, "playwright/e2e/Features/DataQuality/TestLibrary.spec.ts": { @@ -953,11 +953,6 @@ "count": 2 } }, - "playwright/e2e/Pages/SearchIndexApplication.spec.ts": { - "om-playwright/no-positional-locator": { - "count": 2 - } - }, "playwright/e2e/Pages/SearchSettings.spec.ts": { "om-playwright/justified-rule-disable": { "count": 1 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataQuality/TestDefinitionPermissions.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataQuality/TestDefinitionPermissions.spec.ts index e570b49872f1..075c7cb68316 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataQuality/TestDefinitionPermissions.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataQuality/TestDefinitionPermissions.spec.ts @@ -267,16 +267,44 @@ test.describe( 'Test Definition Permissions - Data Steward', { tag: `${DOMAIN_TAGS.OBSERVABILITY}:Rules_Library` }, () => { + // Target the definition this spec creates rather than whichever row sorts + // first. The Test Library is shared across the whole run, and specs seed + // definitions named to sort to the top (TestLibrary.spec.ts creates + // `AaaaExternalTest*`); an external definition's toggle is disabled by + // design, so a positional locator asserts on a row this spec never owned. + const stewardDefinitionName = `aaaColumnTestDefinition-${uuid()}`; + let stewardDefinitionId: string | undefined; + test.beforeAll(async ({ browser }) => { const { apiContext, afterAction } = await performAdminLogin(browser); - await apiContext.post('/api/v1/dataQuality/testDefinitions', { - data: { - name: `aaaColumnTestDefinition-${uuid()}`, - description: `A Column test definition`, - entityType: 'COLUMN', - testPlatforms: ['OpenMetadata'], - }, - }); + const response = await apiContext.post( + '/api/v1/dataQuality/testDefinitions', + { + data: { + name: stewardDefinitionName, + description: `A Column test definition`, + entityType: 'COLUMN', + testPlatforms: ['OpenMetadata'], + }, + } + ); + stewardDefinitionId = (await response.json())?.id; + await afterAction(); + }); + + // Without this the definition outlives the run. The Test Library is + // paginated with no search, and every worker adds another `aaa*` row that + // sorts alongside this one, so leaked definitions eventually push the row + // this spec targets off the first page. + test.afterAll(async ({ browser }) => { + if (!stewardDefinitionId) { + return; + } + + const { apiContext, afterAction } = await performAdminLogin(browser); + await apiContext.delete( + `/api/v1/dataQuality/testDefinitions/${stewardDefinitionId}?hardDelete=true` + ); await afterAction(); }); @@ -306,9 +334,11 @@ test.describe( await expect(addButton).not.toBeVisible(); // Data Steward should be able to toggle enabled/disabled switches (EditAll permission) - const firstSwitch = dataStewardPage.getByRole('switch').first(); + const stewardSwitch = dataStewardPage.getByTestId( + `enable-switch-${stewardDefinitionName}` + ); - await expect(firstSwitch).toBeEnabled(); + await expect(stewardSwitch).toBeEnabled(); // Wait for API call const response = dataStewardPage.waitForResponse( @@ -318,11 +348,11 @@ test.describe( ); // Try to toggle the switch - await firstSwitch.click(); + await stewardSwitch.click(); await response; // Verify switch state changed - await expect(firstSwitch).toHaveAttribute( + await expect(stewardSwitch).toHaveAttribute( 'aria-checked', String('false') ); @@ -333,16 +363,20 @@ test.describe( response.request().method() === 'PATCH' ); // Toggle back to original state - await firstSwitch.click(); + await stewardSwitch.click(); await response2; - await expect(firstSwitch).toHaveAttribute('aria-checked', String('true')); + await expect(stewardSwitch).toHaveAttribute( + 'aria-checked', + String('true') + ); // Data Steward should NOT see delete buttons (no Delete permission) - const deleteButtons = dataStewardPage.getByTestId( - /delete-test-definition-/ - ); - await expect(deleteButtons.first()).toBeDisabled(); + await expect( + dataStewardPage.getByTestId( + `delete-test-definition-${stewardDefinitionName}` + ) + ).toBeDisabled(); }); test('should not be able to edit system test definitions', async ({ diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/LiveIndexingTab.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/LiveIndexingTab.spec.ts index a931fd8447d1..ee61c5f0d120 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/LiveIndexingTab.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/LiveIndexingTab.spec.ts @@ -12,6 +12,10 @@ */ import test, { expect } from '@playwright/test'; import { GlobalSettingOptions } from '../../constant/settings'; +import { + findApplicationCard, + openApplicationDetails, +} from '../../utils/applications'; import { getApiContext, redirectToHomePage } from '../../utils/common'; import { settingClick } from '../../utils/sidebar'; @@ -93,11 +97,7 @@ test.describe( await redirectToHomePage(page); await settingClick(page, GlobalSettingOptions.APPLICATIONS); - await page - .locator( - '[data-testid="search-indexing-application-card"] [data-testid="config-btn"]' - ) - .click(); + await openApplicationDetails(page, 'search-indexing-application-card'); }); await test.step('Click Live Indexing tab', async () => { @@ -144,11 +144,7 @@ test.describe( await redirectToHomePage(page); await settingClick(page, GlobalSettingOptions.APPLICATIONS); - await page - .locator( - '[data-testid="search-indexing-application-card"] [data-testid="config-btn"]' - ) - .click(); + await openApplicationDetails(page, 'search-indexing-application-card'); }); await test.step('Verify empty state message when queue is empty', async () => { @@ -214,11 +210,7 @@ test.describe( await redirectToHomePage(page); await settingClick(page, GlobalSettingOptions.APPLICATIONS); - await page - .locator( - '[data-testid="search-indexing-application-card"] [data-testid="config-btn"]' - ) - .click(); + await openApplicationDetails(page, 'search-indexing-application-card'); }); await test.step('Mock and verify retry queue data', async () => { @@ -278,13 +270,15 @@ test.describe( }); await test.step('Verify Live Indexing tab is absent on non-search apps', async () => { - // Check if DataInsightsReportApplication card exists - const diCard = page.locator( - '[data-testid="data-insights-report-application-card"] [data-testid="config-btn"]' - ); - - if (await diCard.isVisible()) { - await diCard.click(); + // DataInsightsReportApplication is not installed on every deployment, + // so treat "not on any page" as nothing to assert rather than a failure. + const diCard = await findApplicationCard( + page, + 'data-insights-report-application-card' + ).catch(() => null); + + if (diCard) { + await diCard.getByTestId('config-btn').click(); const liveIndexingTab = page.getByRole('tab', { name: 'Live Indexing', diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/SearchIndexApplication.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/SearchIndexApplication.spec.ts index 26b5dff06457..44b1a3ae00a2 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/SearchIndexApplication.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/SearchIndexApplication.spec.ts @@ -13,6 +13,13 @@ import test, { expect, Page, Response } from '@playwright/test'; import { PLAYWRIGHT_BASIC_TEST_TAG_OBJ } from '../../constant/config'; import { GlobalSettingOptions } from '../../constant/settings'; +import { + APPLICATION_LIST, + expectApplicationInstalled, + expectApplicationNotInstalled, + findApplicationCard, + openApplicationDetails, +} from '../../utils/applications'; import { clickOutside, getApiContext, @@ -47,47 +54,13 @@ const installSearchIndexApplication = async (page: Page) => { expect(response.status()).toBe(200); - // Wait for at least one app card to be rendered before polling. - await page - .locator('[data-testid$="-application-card"]') - .first() - .waitFor({ state: 'visible' }); - - // Paginate through marketplace pages until the card is found. - let cardFound = await page - .locator('[data-testid="search-indexing-application-card"]') - .isVisible(); - - while (!cardFound) { - const nextButton = page.locator('[data-testid="next"]'); - - const isNextButtonVisible = await nextButton.isVisible(); - - if (!isNextButtonVisible || (await nextButton.isDisabled())) { - throw new Error( - 'search-indexing-application-card not found in marketplace and next button is disabled' - ); - } - - const nextPageResponse = page.waitForResponse('/api/v1/apps/marketplace*'); - await nextButton.click(); - await nextPageResponse; - - // Wait for the next page's cards to render before re-checking. - await page - .locator('[data-testid$="-application-card"]') - .first() - .waitFor({ state: 'visible' }); - - cardFound = await page - .locator('[data-testid="search-indexing-application-card"]') - .isVisible(); - } + const marketplaceCard = await findApplicationCard( + page, + 'search-indexing-application-card', + APPLICATION_LIST.marketplace + ); - await page - .getByTestId('search-indexing-application-card') - .getByTestId('config-btn') - .click(); + await marketplaceCard.getByTestId('config-btn').click(); await page.getByTestId('install-application').waitFor({ state: 'visible' }); await page.getByTestId('install-application').click(); @@ -117,9 +90,7 @@ const installSearchIndexApplication = async (page: Page) => { await getApplications; - await expect( - page.getByTestId('search-indexing-application-card') - ).toBeVisible(); + await expectApplicationInstalled(page, 'search-indexing-application-card'); }; const verifyLastExecutionStatus = async (page: Page) => { @@ -291,11 +262,7 @@ test.describe('Search Index Application', PLAYWRIGHT_BASIC_TEST_TAG_OBJ, () => { const statusAPI = page.waitForResponse( '/api/v1/apps/name/SearchIndexingApplication/status?offset=0&limit=1' ); - await page - .locator( - '[data-testid="search-indexing-application-card"] [data-testid="config-btn"]' - ) - .click(); + await openApplicationDetails(page, 'search-indexing-application-card'); const statusResponse = await statusAPI; expect(statusResponse.status()).toBe(200); @@ -431,11 +398,10 @@ test.describe('Search Index Application', PLAYWRIGHT_BASIC_TEST_TAG_OBJ, () => { await toastNotification(page, 'Application uninstalled successfully'); - const card1 = page.locator( - '[data-testid="search-indexing-application-card"]' + await expectApplicationNotInstalled( + page, + 'search-indexing-application-card' ); - - await expect(card1).toBeHidden(); }); await test.step('Install application', async () => { @@ -446,9 +412,7 @@ test.describe('Search Index Application', PLAYWRIGHT_BASIC_TEST_TAG_OBJ, () => { await test.step('Run application and rerun with table-only config', async () => { test.slow(true); // Test time shouldn't exceed while re-fetching the history API. - await page.click( - '[data-testid="search-indexing-application-card"] [data-testid="config-btn"]' - ); + await openApplicationDetails(page, 'search-indexing-application-card'); const previousRunStartTime = await getLatestRunStartTime(page); const triggerPipelineResponse = page.waitForResponse( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs b/openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs index add5856a663f..cc06c2ed1831 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs +++ b/openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs @@ -42,7 +42,7 @@ test('the suppressions baseline matches its recorded state exactly', () => { const EXPECTED = { 'om-playwright/justified-rule-disable': 12, 'om-playwright/no-blanket-test-slow': 83, - 'om-playwright/no-positional-locator': 1328, + 'om-playwright/no-positional-locator': 1324, 'om-playwright/require-assertion-per-test': 1, 'playwright/no-force-option': 11, 'playwright/no-skipped-test': 4, diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/applications.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/applications.ts index 648279ccd427..258261411263 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/applications.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/applications.ts @@ -10,7 +10,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { APIRequestContext } from '@playwright/test'; +import { APIRequestContext, expect, Page } from '@playwright/test'; +import { clickAndWaitFor } from './waitHelpers'; export const enableDisableAutoPilotApplication = async ( apiContext: APIRequestContext, @@ -23,3 +24,121 @@ export const enableDisableAutoPilotApplication = async ( }, }); }; + +const APPLICATION_CARD = '[data-testid$="-application-card"]'; + +/** + * The two paginated application lists. They share a card testid and paging + * controls and differ only in the endpoint a page turn hits, so both are + * walked by the same code. + */ +export const APPLICATION_LIST = { + installed: { api: /\/api\/v1\/apps\?/, label: 'applications list' }, + marketplace: { api: /\/api\/v1\/apps\/marketplace/, label: 'marketplace' }, +} as const; + +type ApplicationList = (typeof APPLICATION_LIST)[keyof typeof APPLICATION_LIST]; + +const waitForApplicationCards = async (page: Page) => { + await expect(page.locator(APPLICATION_CARD)).not.toHaveCount(0); +}; + +/** + * Walk an application list from the current page onwards, stopping as soon as + * the card is on screen. Returns whether it was found anywhere. + * + * Both lists paginate at PAGE_SIZE_BASE (15) and the bundled app count grows + * whenever a new application ships, so a card sitting on page 1 today silently + * moves to page 2 the next time one is added. Anything that asserts on a + * card's presence or absence has to page, or it is really only asserting about + * page 1. + */ +const isOnAnyApplicationPage = async ( + page: Page, + cardTestId: string, + list: ApplicationList +) => { + await waitForApplicationCards(page); + + const card = page.getByTestId(cardTestId); + const nextPage = page.getByTestId('next'); + + while (!(await card.isVisible())) { + const canPage = + (await nextPage.isVisible()) && (await nextPage.isEnabled()); + + if (!canPage) { + return false; + } + + await clickAndWaitFor(page, nextPage, list.api); + + // The list swaps its cards for skeletons while loading, so the next card + // to appear can only belong to the page we just moved to. + await waitForApplicationCards(page); + } + + return true; +}; + +/** + * Bring an installed application's card on screen and return its locator, + * paging until it is found. Throws when no page holds it. + */ +export const findApplicationCard = async ( + page: Page, + cardTestId: string, + list: ApplicationList = APPLICATION_LIST.installed +) => { + const isFound = await isOnAnyApplicationPage(page, cardTestId, list); + + if (!isFound) { + throw new Error( + `${cardTestId} was not found on any page of the ${list.label}` + ); + } + + return page.getByTestId(cardTestId); +}; + +/** + * Assert an application is installed, paging until its card is found. Use this + * rather than a bare toBeVisible(), which only ever asserts about page 1. + */ +export const expectApplicationInstalled = async ( + page: Page, + cardTestId: string +) => { + expect( + await isOnAnyApplicationPage(page, cardTestId, APPLICATION_LIST.installed), + `${cardTestId} should be on some page of the applications list` + ).toBe(true); +}; + +/** + * Assert an application is not installed. A bare toBeHidden() cannot tell + * "uninstalled" from "on a later page", so it passes even when the uninstall + * silently failed. + */ +export const expectApplicationNotInstalled = async ( + page: Page, + cardTestId: string +) => { + expect( + await isOnAnyApplicationPage(page, cardTestId, APPLICATION_LIST.installed), + `${cardTestId} should not be on any page of the applications list` + ).toBe(false); +}; + +/** + * Open an installed application's details page from Settings > Applications, + * paging to its card first. Assumes the applications list is already open. + */ +export const openApplicationDetails = async ( + page: Page, + cardTestId: string +) => { + const card = await findApplicationCard(page, cardTestId); + + await card.getByTestId('config-btn').click(); +}; From 7fb74b1aee225e224384ddf3d47f54dee63ab936 Mon Sep 17 00:00:00 2001 From: Sriharsha Chintalapani Date: Mon, 31 Aug 2026 08:23:54 -0700 Subject: [PATCH 13/83] Fixes #30895: Complete Metrics hierarchy and details (#30896) * feat(metrics): complete hierarchy and detail experience * Update generated TypeScript types * Fix metrics CI regressions * Fix Linux metric visual baselines * Fix metric UI CI workflows * fix(metrics): optimize hierarchy pagination * fix(ui): satisfy metrics lint gate * fix(metrics): bound catalog-wide scans * fix: resolve metrics CI failures * fix(metrics): resolve integration and UI regressions * test(ui): refresh metric desktop baselines * fix(metrics): keep group assignments transactional * fix(metrics): keep entity writes on group transaction * fix(playwright): handle glossary rejection comments * fix(tests): prevent short namespace collisions * fix(tests): disperse short namespace identifiers * fix(workflows): isolate async field patches * fix(workflows): restore durable approved versions * fix: resolve metrics CI regressions * fix: address metrics review feedback * fix: retry lineage writes after deadlocks * test: tolerate delayed conversation visibility * fix: stabilize glossary reindexing and metric compatibility --------- Co-authored-by: github-actions[bot] --- .github/playwright/timing-baseline.json | 2 +- .github/scripts/build_playwright_shards.py | 56 +- .../tests/test_playwright_ci_planning.py | 65 +- .../mysql/postDataMigrationSQLScript.sql | 8 + .../native/2.1.0/mysql/schemaChanges.sql | 70 +- .../postgres/postDataMigrationSQLScript.sql | 7 + .../native/2.1.0/postgres/schemaChanges.sql | 23 + docs/generated/api-reference.md | 22 +- docs/generated/entity-index.md | 3 +- .../source/database/snowflake/metadata.py | 19 - .../snowflake/semantic_view_metrics.py | 12 +- .../test_snowflake_semantic_view_metrics.py | 57 +- .../it/tests/ConversationResourceIT.java | 3 + .../it/tests/IncidentGroupsIT.java | 38 +- .../tests/MergedMetricMigrationFixture.java | 129 + .../MergedMetricMigrationTestSupport.java | 475 ++++ .../it/tests/MetricGroupResourceIT.java | 1420 ++++++++++ .../it/tests/MetricMigrationIT.java | 166 ++ .../it/tests/MetricMigrationSqlFixture.java | 76 + .../it/tests/MetricMigrationTestSupport.java | 558 ++++ .../it/tests/MetricResourceIT.java | 2455 ++++++++++++++++- .../openmetadata/it/tests/TaskResourceIT.java | 30 + .../it/tests/TestCaseResourceIT.java | 10 +- .../it/tests/mcp/AIContextMcpIT.java | 56 +- .../it/tests/mcp/MetricAssetsIT.java | 74 +- .../it/tests/mcp/PersonaAIContextIT.java | 72 + .../openmetadata/it/util/TestNamespace.java | 22 +- .../it/util/TestNamespaceTest.java | 50 + .../java/org/openmetadata/service/Entity.java | 1 + .../aicontext/PersonaContextBuilder.java | 43 +- .../impl/RollbackEntityImpl.java | 423 +-- .../elements/nodes/userTask/CreateTask.java | 1 + .../service/jdbi3/CoreRelationshipDAOs.java | 22 +- .../service/jdbi3/EntityDataDAOs.java | 509 ++++ .../service/jdbi3/EntityRepository.java | 41 +- .../service/jdbi3/GlossaryTermRepository.java | 2 +- .../service/jdbi3/LineageRepository.java | 117 +- .../service/jdbi3/MetricGroupRepository.java | 905 ++++++ .../jdbi3/MetricObservabilityBuilder.java | 697 +++++ .../service/jdbi3/MetricRepository.java | 1138 +++++++- .../jdbi3/RepositoryTransactionContext.java | 52 + .../resources/metrics/MetricGroupMapper.java | 38 + .../metrics/MetricGroupResource.java | 651 +++++ .../resources/metrics/MetricMapper.java | 22 +- .../resources/metrics/MetricResource.java | 528 +++- .../service/search/SearchClient.java | 2 +- .../service/search/SearchIndexFactory.java | 3 + .../service/search/SearchUtils.java | 1 + .../search/indexes/MetricGroupIndex.java | 73 + .../service/search/indexes/MetricIndex.java | 42 +- .../service/tasks/TaskWorkflowHandler.java | 95 +- .../service/util/EntityFieldUtils.java | 4 +- .../workflows/MetricApprovalWorkflow.json | 425 +++ .../data/metric/metricCsvDocumentation.json | 18 + .../aicontext/PersonaContextBuilderTest.java | 49 + .../impl/RollbackEntityImplTest.java | 288 ++ .../nodes/userTask/CreateTaskTest.java | 18 + .../EntityRelationshipDaoContractTest.java | 55 + .../jdbi3/EntityRepositoryRestoreTest.java | 77 + .../GlossaryTermRepositoryBulkFieldsTest.java | 135 + .../service/jdbi3/LineageRepositoryTest.java | 56 + .../service/jdbi3/MetricDaoContractTest.java | 176 ++ .../jdbi3/MetricGroupRepositoryTest.java | 480 ++++ .../jdbi3/MetricObservabilityBuilderTest.java | 507 ++++ .../service/jdbi3/MetricRepositoryTest.java | 429 +++ .../RepositoryTransactionContextTest.java | 51 + ...WorkflowDefinitionGraphValidationTest.java | 42 + .../metrics/MetricGroupResourceTest.java | 380 +++ .../resources/metrics/MetricMapperTest.java | 140 + .../resources/metrics/MetricResourceTest.java | 508 ++++ .../IndexMappingVersionTrackerTest.java | 9 + .../search/SearchIndexFactoryTest.java | 4 + .../service/search/SearchUtilsTest.java | 4 + .../search/indexes/MetricGroupIndexTest.java | 45 + .../search/indexes/MetricIndexTest.java | 85 + .../tasks/TaskWorkflowHandlerTest.java | 296 +- .../service/util/EntityFieldUtilsTest.java | 1 + .../org/openmetadata/schema/EntityLink.g4 | 1 + .../en/metric_group_index_mapping.json | 587 ++++ .../en/metric_index_mapping.json | 61 + .../resources/elasticsearch/indexMapping.json | 9 + .../jp/metric_group_index_mapping.json | 574 ++++ .../jp/metric_index_mapping.json | 61 + .../ru/metric_group_index_mapping.json | 553 ++++ .../ru/metric_index_mapping.json | 61 + .../zh/metric_group_index_mapping.json | 559 ++++ .../zh/metric_index_mapping.json | 61 + .../json/schema/api/data/createMetric.json | 20 +- .../schema/api/data/createMetricGroup.json | 67 + .../api/data/metricHierarchyContext.json | 46 + .../schema/api/data/metricHierarchyItem.json | 46 + .../schema/api/data/metricObservability.json | 313 +++ .../json/schema/entity/data/metric.json | 21 + .../json/schema/entity/data/metricGroup.json | 119 + .../application/table/table.test.tsx | 56 + .../components/application/table/table.tsx | 5 +- .../main/resources/ui/src/styles/globals.css | 1647 ++++++++--- .../src/main/resources/ui/eslint.config.mjs | 51 + .../Features/DataAssetRulesDisabled.spec.ts | 179 +- .../Features/DataAssetRulesEnabled.spec.ts | 135 +- .../GlossaryApprovalAfterMove.spec.ts | 30 +- .../e2e/Features/MetricActivityTasks.spec.ts | 424 +++ .../e2e/Features/MetricGovernance.spec.ts | 2384 ++++++++++++++++ .../e2e/Features/MetricHierarchy.spec.ts | 1163 ++++++++ .../e2e/Flow/MetricListSearch.spec.ts | 33 +- .../ui/playwright/e2e/Pages/Entity.spec.ts | 176 +- .../e2e/Pages/EntityHeaderBreadcrumb.spec.ts | 5 +- .../ui/playwright/e2e/Pages/Glossary.spec.ts | 14 +- .../VersionPages/GlossaryVersionPage.spec.ts | 4 - .../metric-activity-desktop.png | Bin 0 -> 96063 bytes .../metric-activity-narrow.png | Bin 0 -> 55978 bytes .../metric-approval-desktop.png | Bin 0 -> 114592 bytes .../metric-approval-narrow.png | Bin 0 -> 61054 bytes .../metric-assets-desktop.png | Bin 0 -> 128771 bytes .../metric-assets-narrow.png | Bin 0 -> 41799 bytes .../metric-list-desktop.png | Bin 0 -> 98957 bytes .../metric-list-narrow.png | Bin 0 -> 60859 bytes .../metric-observability-desktop.png | Bin 0 -> 123998 bytes .../metric-observability-narrow.png | Bin 0 -> 64183 bytes .../metric-overview-dark-desktop.png | Bin 0 -> 149719 bytes .../metric-overview-dark-narrow.png | Bin 0 -> 69438 bytes .../metric-overview-desktop.png | Bin 0 -> 148003 bytes .../metric-overview-narrow.png | Bin 0 -> 68388 bytes .../VisualRegression/metricDetails.spec.ts | 742 +++++ .../playwright/support/entity/MetricClass.ts | 508 +++- .../ui/playwright/utils/customProperty.ts | 64 + .../resources/ui/playwright/utils/entity.ts | 33 + .../playwright/utils/entityPermissionUtils.ts | 34 +- .../resources/ui/playwright/utils/glossary.ts | 6 +- .../playwright/utils/headerBreadcrumbUtils.ts | 7 +- .../ui/playwright/utils/metricMetadata.ts | 176 ++ .../components/AlertBar/AlertBar.interface.ts | 2 +- .../DataAssetsHeader.component.tsx | 122 +- .../DataAssetsHeader.test.tsx | 52 +- .../DataAssetsHeader/StatItem.component.tsx | 29 +- .../DataAssetsHeader/StatItem.test.tsx | 73 + .../TableQueries/TableQueries.interface.ts | 2 +- .../Explore/ExplorePage.interface.ts | 2 +- .../GlossaryTermTab.component.tsx | 95 +- .../GlossaryTermTab/GlossaryTermTab.test.tsx | 50 + .../EntityLineageTab/EntityLineageTab.tsx | 5 +- .../components/Lineage/Lineage.component.tsx | 17 +- .../Lineage/LineageNodeRemoveButton.test.tsx | 37 + .../Lineage/LineageNodeRemoveButton.tsx | 25 +- ...ess => LineageSkeleton.component.test.tsx} | 26 +- .../Lineage/LineageSkeleton.component.tsx | 50 +- .../MetricActivity/MetricActivity.types.ts | 40 + .../MetricActivity.utils.test.ts | 95 + .../MetricActivity/MetricActivity.utils.ts | 282 ++ .../MetricActivityDetail.test.tsx | 192 ++ .../MetricActivity/MetricActivityDetail.tsx | 354 +++ .../MetricActivity/MetricActivityItem.tsx | 90 + .../MetricActivityItems.test.tsx | 163 ++ .../MetricActivityTab.component.test.tsx | 195 ++ .../MetricActivityTab.component.tsx | 362 +++ .../MetricCommentComposer.test.tsx | 101 + .../MetricActivity/MetricCommentComposer.tsx | 206 ++ .../MetricFeedCountUtils.test.ts | 128 + .../MetricActivity/MetricFeedCountUtils.ts | 53 + .../MetricTaskCreateDialog.test.tsx | 369 +++ .../MetricActivity/MetricTaskCreateDialog.tsx | 462 ++++ .../Metric/MetricActivity/MetricTaskItem.tsx | 115 + .../MetricActivity/useMetricActivity.test.tsx | 197 ++ .../MetricActivity/useMetricActivity.ts | 273 ++ ...useMetricTaskResolutionPermission.test.tsx | 132 + .../useMetricTaskResolutionPermission.ts | 74 + .../MetricApprovalHistory.test.tsx | 107 + .../MetricApproval/MetricApprovalHistory.tsx | 174 ++ .../MetricApprovalHistory.utils.test.ts | 52 + .../MetricApprovalHistory.utils.ts | 103 + .../MetricApprovalTab.component.test.tsx | 297 ++ .../MetricApprovalTab.component.tsx | 328 +++ .../MetricStatusAction.component.test.tsx | 53 + .../MetricStatusAction.component.tsx | 80 + .../useMetricApprovalHistory.test.tsx | 108 + .../useMetricApprovalHistory.ts | 211 ++ .../MetricAssetAddDialog.test.tsx | 217 ++ .../MetricAssetsTab/MetricAssetAddDialog.tsx | 445 +++ .../MetricAssetsTab/MetricAssetCard.test.tsx | 198 ++ .../MetricAssetsTab/MetricAssetCard.tsx | 220 ++ .../MetricAssetResizableLayout.test.tsx | 185 ++ .../MetricAssetResizableLayout.tsx | 208 ++ .../MetricAssetSummary.test.tsx | 91 + .../MetricAssetsTab/MetricAssetSummary.tsx | 264 ++ .../MetricAssetsTab.component.test.tsx | 205 ++ .../MetricAssetsTab.component.tsx | 405 +++ .../MetricAssetsTab/MetricAssetsTab.types.ts | 44 + .../MetricAssetsTab.utils.test.ts | 99 + .../MetricAssetsTab/MetricAssetsTab.utils.ts | 182 ++ .../useMetricAssetLineage.test.tsx | 134 + .../MetricAssetsTab/useMetricAssetLineage.ts | 160 ++ .../useMetricAssetsTab.test.tsx | 267 ++ .../MetricAssetsTab/useMetricAssetsTab.ts | 314 +++ .../MetricCustomPropertyValue.component.tsx | 65 + .../MetricCustomPropertyValue.test.tsx | 52 + .../MetricDefinitionCard.test.tsx | 313 +++ .../MetricDefinitionCard.tsx | 466 ++++ .../MetricDeleteDialog.test.tsx | 71 + .../MetricDeleteDialog/MetricDeleteDialog.tsx | 117 + .../MetricDetails/MetricDetails.interface.ts | 13 +- .../MetricDetails/MetricDetails.test.tsx | 869 +++++- .../Metric/MetricDetails/MetricDetails.tsx | 1371 +++++++-- .../MetricExpression.test.tsx | 170 ++ .../MetricExpression/MetricExpression.tsx | 312 ++- .../MetricGroupSelect.integration.test.tsx | 67 + .../MetricGroupSelect.test.tsx | 299 ++ .../MetricGroupSelect/MetricGroupSelect.tsx | 274 ++ .../MetricHeaderInfo.test.tsx | 161 ++ .../MetricHeaderInfo/MetricHeaderInfo.tsx | 263 +- .../UnitOfMeasurementInfoItem.tsx | 218 -- .../MetricHeaderInfo/metric-header-info.less | 34 - .../unit-of-measurement-header.less | 16 - .../MetricHierarchyCard.test.tsx | 293 ++ .../MetricHierarchyCard.tsx | 395 +++ .../useMetricHierarchyCard.test.tsx | 113 + .../useMetricHierarchyCard.ts | 147 + .../MetricListHealth.component.tsx | 101 + .../MetricListHealth.test.tsx | 197 ++ .../MetricMetadataEditor.test.tsx | 573 ++++ .../MetricMetadataEditor.tsx | 506 ++++ .../MetricHealthPill.component.test.tsx | 52 + .../MetricHealthPill.component.tsx | 91 + .../MetricObservability.utils.test.ts | 106 + .../MetricObservability.utils.ts | 103 + .../MetricObservabilityTab.component.test.tsx | 425 +++ .../MetricObservabilityTab.component.tsx | 587 ++++ .../MetricReferencePicker.test.tsx | 351 +++ .../MetricReferencePicker.tsx | 282 ++ .../MetricStatusPill.component.tsx | 103 + .../MetricStatusPill.test.tsx | 58 + .../Metric/MetricUntitledImports.test.ts | 334 +++ .../MetricVersion/MetricVersion.interface.ts | 10 +- .../MetricVersion/MetricVersion.test.tsx | 130 + .../Metric/MetricVersion/MetricVersion.tsx | 439 +-- .../MetricVersion/MetricVersion.utils.test.ts | 68 + .../MetricVersion/MetricVersion.utils.ts | 49 + .../RelatedMetrics/RelatedMetrics.test.tsx | 108 + .../Metric/RelatedMetrics/RelatedMetrics.tsx | 265 +- .../RelatedMetricsForm.test.tsx | 176 ++ .../RelatedMetrics/RelatedMetricsForm.tsx | 215 +- .../RelatedMetrics/related-metrics.less | 26 - .../components/common/Table/TableV2.test.tsx | 221 ++ .../src/components/common/Table/TableV2.tsx | 72 +- .../common/Table/TableV2Utils.test.ts | 110 + .../components/common/Table/TableV2Utils.ts | 40 + .../ui/src/constants/Customize.constants.ts | 1 + .../ui/src/constants/Metric.constants.ts | 18 + .../LimitsProvider/useLimitsStore.test.ts | 111 + .../context/LimitsProvider/useLimitsStore.ts | 36 +- .../ui/src/enums/CustomizeDetailPage.enum.ts | 2 + .../resources/ui/src/enums/entity.enum.ts | 1 + .../ui/src/generated/api/data/createMetric.ts | 15 +- .../generated/api/data/createMetricGroup.ts | 322 +++ .../api/data/metricHierarchyContext.ts | 915 ++++++ .../generated/api/data/metricHierarchyItem.ts | 872 ++++++ .../generated/api/data/metricObservability.ts | 357 +++ .../ui/src/generated/entity/data/metric.ts | 32 +- .../src/generated/entity/data/metricGroup.ts | 505 ++++ .../ui/src/hoc/LimitWrapper.test.tsx | 241 ++ .../resources/ui/src/hoc/LimitWrapper.tsx | 75 +- .../ui/src/hooks/useApplicationStore.ts | 16 +- .../resources/ui/src/hooks/useDomainStore.ts | 4 +- .../src/hooks/useEntityApprovalTask.test.tsx | 142 + .../ui/src/hooks/useEntityApprovalTask.ts | 137 + .../ui/src/hooks/useMetricHierarchy.test.tsx | 459 +++ .../ui/src/hooks/useMetricHierarchy.ts | 486 ++++ .../src/hooks/useMetricObservability.test.tsx | 103 + .../ui/src/hooks/useMetricObservability.ts | 42 + .../ui/src/interface/store.interface.ts | 24 +- .../ui/src/locale/languages/ar-sa.json | 34 + .../ui/src/locale/languages/de-de.json | 34 + .../ui/src/locale/languages/en-us.json | 34 + .../ui/src/locale/languages/es-es.json | 34 + .../ui/src/locale/languages/fr-fr.json | 34 + .../ui/src/locale/languages/gl-es.json | 34 + .../ui/src/locale/languages/he-he.json | 34 + .../ui/src/locale/languages/ja-jp.json | 34 + .../ui/src/locale/languages/ko-kr.json | 34 + .../ui/src/locale/languages/mr-in.json | 34 + .../ui/src/locale/languages/nl-nl.json | 34 + .../ui/src/locale/languages/pr-pr.json | 484 ++-- .../ui/src/locale/languages/pt-br.json | 34 + .../ui/src/locale/languages/pt-pt.json | 34 + .../ui/src/locale/languages/ru-ru.json | 34 + .../ui/src/locale/languages/sv-se.json | 34 + .../ui/src/locale/languages/th-th.json | 34 + .../ui/src/locale/languages/tr-tr.json | 34 + .../ui/src/locale/languages/zh-cn.json | 34 + .../ui/src/locale/languages/zh-tw.json | 34 + .../ExplorePage/ExplorePage.interface.ts | 8 +- .../AddMetricPage/AddMetricPage.test.tsx | 340 +++ .../AddMetricPage/AddMetricPage.tsx | 746 +++-- .../MetricDetailsPage.test.tsx | 392 +++ .../MetricDetailsPage/MetricDetailsPage.tsx | 206 +- .../MetricListPage/MetricListPage.test.tsx | 1326 ++++++--- .../MetricListPage/MetricListPage.tsx | 1899 ++++++++----- .../MetricListPage/metric-list-page.less | 675 ----- .../resources/ui/src/rest/lineageAPI.test.ts | 13 + .../main/resources/ui/src/rest/lineageAPI.ts | 13 + .../ui/src/rest/metricGroupsAPI.test.ts | 126 + .../resources/ui/src/rest/metricGroupsAPI.ts | 118 + .../ui/src/rest/metricTabsAPI.test.ts | 68 + .../resources/ui/src/rest/metricTabsAPI.ts | 141 + .../resources/ui/src/rest/metricsAPI.test.ts | 157 ++ .../main/resources/ui/src/rest/metricsAPI.ts | 118 +- .../ui/src/rest/queries/metricQuery.test.ts | 37 + .../ui/src/rest/queries/metricQuery.ts | 9 +- .../ui/src/rest/workflowAPI.interface.ts | 4 + .../src/styles/components/form-hint-doc.less | 5 +- .../src/utils/EntityLineageNodeUtils.test.ts | 2 +- .../utils/EntitySummaryPanelUtils.test.tsx | 30 + .../ui/src/utils/EntitySummaryPanelUtils.tsx | 2 +- .../ui/src/utils/EntityUtilClassBase.test.ts | 13 + .../ui/src/utils/EntityUtilClassBase.ts | 18 +- .../MetricApprovalUtils.test.ts | 184 ++ .../MetricEntityUtils/MetricApprovalUtils.ts | 85 + .../MetricDetailsClassBase.test.ts | 50 +- .../MetricDetailsClassBase.ts | 71 +- .../MetricDisplayUtils.test.ts | 83 + .../MetricEntityUtils/MetricDisplayUtils.ts | 66 + .../MetricHierarchyUtils.test.ts | 193 ++ .../MetricEntityUtils/MetricHierarchyUtils.ts | 216 ++ .../MetricTranslations.test.ts | 182 ++ .../MetricEntityUtils/MetricUtils.test.tsx | 283 ++ .../utils/MetricEntityUtils/MetricUtils.tsx | 144 +- .../resources/ui/src/utils/ToastUtils.test.ts | 41 + .../main/resources/ui/src/utils/ToastUtils.ts | 24 +- 327 files changed, 57172 insertions(+), 5181 deletions(-) create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationFixture.java create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationTestSupport.java create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricGroupResourceIT.java create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationIT.java create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationSqlFixture.java create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationTestSupport.java create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespaceTest.java create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricGroupRepository.java create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilder.java create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/RepositoryTransactionContext.java create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupMapper.java create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupResource.java create mode 100644 openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricGroupIndex.java create mode 100644 openmetadata-service/src/main/resources/json/data/governance/workflows/MetricApprovalWorkflow.json create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImplTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRelationshipDaoContractTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/GlossaryTermRepositoryBulkFieldsTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricDaoContractTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricGroupRepositoryTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilderTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricRepositoryTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/RepositoryTransactionContextTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricGroupResourceTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricMapperTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricResourceTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricGroupIndexTest.java create mode 100644 openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricIndexTest.java create mode 100644 openmetadata-spec/src/main/resources/elasticsearch/en/metric_group_index_mapping.json create mode 100644 openmetadata-spec/src/main/resources/elasticsearch/jp/metric_group_index_mapping.json create mode 100644 openmetadata-spec/src/main/resources/elasticsearch/ru/metric_group_index_mapping.json create mode 100644 openmetadata-spec/src/main/resources/elasticsearch/zh/metric_group_index_mapping.json create mode 100644 openmetadata-spec/src/main/resources/json/schema/api/data/createMetricGroup.json create mode 100644 openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyContext.json create mode 100644 openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyItem.json create mode 100644 openmetadata-spec/src/main/resources/json/schema/api/data/metricObservability.json create mode 100644 openmetadata-spec/src/main/resources/json/schema/entity/data/metricGroup.json create mode 100644 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricActivityTasks.spec.ts create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricGovernance.spec.ts create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricHierarchy.spec.ts create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-activity-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-activity-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-approval-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-approval-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-assets-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-assets-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-list-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-list-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-observability-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-observability-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-dark-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-dark-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-desktop.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-narrow.png create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/metricDetails.spec.ts create mode 100644 openmetadata-ui/src/main/resources/ui/playwright/utils/metricMetadata.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/StatItem.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Lineage/LineageNodeRemoveButton.test.tsx rename openmetadata-ui/src/main/resources/ui/src/components/Lineage/{LineageSkeleton.less => LineageSkeleton.component.test.tsx} (53%) create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivity.types.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivity.utils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivity.utils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivityDetail.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivityDetail.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivityItem.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivityItems.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivityTab.component.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricActivityTab.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricCommentComposer.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricCommentComposer.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricFeedCountUtils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricFeedCountUtils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricTaskCreateDialog.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricTaskCreateDialog.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/MetricTaskItem.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/useMetricActivity.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/useMetricActivity.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/useMetricTaskResolutionPermission.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricActivity/useMetricTaskResolutionPermission.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricApprovalHistory.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricApprovalHistory.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricApprovalHistory.utils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricApprovalHistory.utils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricApprovalTab.component.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricApprovalTab.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricStatusAction.component.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/MetricStatusAction.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/useMetricApprovalHistory.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricApproval/useMetricApprovalHistory.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetAddDialog.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetAddDialog.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetCard.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetCard.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetResizableLayout.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetResizableLayout.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetSummary.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetSummary.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetsTab.component.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetsTab.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetsTab.types.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetsTab.utils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/MetricAssetsTab.utils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/useMetricAssetLineage.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/useMetricAssetLineage.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/useMetricAssetsTab.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricAssetsTab/useMetricAssetsTab.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricCustomPropertyValue/MetricCustomPropertyValue.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricCustomPropertyValue/MetricCustomPropertyValue.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricDefinitionCard/MetricDefinitionCard.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricDefinitionCard/MetricDefinitionCard.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricDeleteDialog/MetricDeleteDialog.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricDeleteDialog/MetricDeleteDialog.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricExpression/MetricExpression.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricGroupSelect/MetricGroupSelect.integration.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricGroupSelect/MetricGroupSelect.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricGroupSelect/MetricGroupSelect.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHeaderInfo/MetricHeaderInfo.test.tsx delete mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHeaderInfo/UnitOfMeasurementInfoItem.tsx delete mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHeaderInfo/metric-header-info.less delete mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHeaderInfo/unit-of-measurement-header.less create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHierarchyCard/MetricHierarchyCard.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHierarchyCard/MetricHierarchyCard.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHierarchyCard/useMetricHierarchyCard.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricHierarchyCard/useMetricHierarchyCard.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricListHealth/MetricListHealth.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricListHealth/MetricListHealth.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricMetadataEditor/MetricMetadataEditor.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricMetadataEditor/MetricMetadataEditor.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricObservability/MetricHealthPill.component.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricObservability/MetricHealthPill.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricObservability/MetricObservability.utils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricObservability/MetricObservability.utils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricObservability/MetricObservabilityTab.component.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricObservability/MetricObservabilityTab.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricReferencePicker/MetricReferencePicker.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricReferencePicker/MetricReferencePicker.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricStatusPill/MetricStatusPill.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricStatusPill/MetricStatusPill.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricUntitledImports.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricVersion/MetricVersion.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricVersion/MetricVersion.utils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/MetricVersion/MetricVersion.utils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/RelatedMetrics.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/RelatedMetricsForm.test.tsx delete mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Metric/RelatedMetrics/related-metrics.less create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/Table/TableV2Utils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/context/LimitsProvider/useLimitsStore.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/generated/api/data/createMetricGroup.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/generated/api/data/metricHierarchyContext.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/generated/api/data/metricHierarchyItem.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/generated/api/data/metricObservability.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/generated/entity/data/metricGroup.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/hoc/LimitWrapper.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/useEntityApprovalTask.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/useEntityApprovalTask.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/useMetricHierarchy.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/useMetricHierarchy.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/useMetricObservability.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/hooks/useMetricObservability.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/AddMetricPage/AddMetricPage.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricDetailsPage/MetricDetailsPage.test.tsx delete mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/MetricsPage/MetricListPage/metric-list-page.less create mode 100644 openmetadata-ui/src/main/resources/ui/src/rest/metricGroupsAPI.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/rest/metricGroupsAPI.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/rest/metricTabsAPI.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/rest/metricTabsAPI.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/rest/metricsAPI.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/rest/queries/metricQuery.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricApprovalUtils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricApprovalUtils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricDisplayUtils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricDisplayUtils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricHierarchyUtils.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricHierarchyUtils.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricTranslations.test.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/MetricEntityUtils/MetricUtils.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/ToastUtils.test.ts diff --git a/.github/playwright/timing-baseline.json b/.github/playwright/timing-baseline.json index 6aeccc1b6145..54278dfe1346 100644 --- a/.github/playwright/timing-baseline.json +++ b/.github/playwright/timing-baseline.json @@ -1 +1 @@ -{"version":1,"mode":"full","sourceRunId":32744092683,"sourceSha":"36e00d5db788fb96857b34d11dbf2bae8cde24c7","retainedSourceRunId":29980474263,"retainedSourceSha":"9f78d5d741673d44dee0190488ba586cce4fecb1","retainedUnstableTestIds":["10c126ce21ddb47756a4-04d6154814646027d691","10c126ce21ddb47756a4-0741446b51bd1831b1fb","10c126ce21ddb47756a4-211bb353cbf91b58df5a","10c126ce21ddb47756a4-2a8d02fe65e159aa7997","10c126ce21ddb47756a4-326e5741aa3e465e11c0","10c126ce21ddb47756a4-439a804c72c1029b9604","10c126ce21ddb47756a4-485027c527c4c17d746c","10c126ce21ddb47756a4-49aa937a33fa5a8948c9","10c126ce21ddb47756a4-4bca0aa80c53d7c4a24c","10c126ce21ddb47756a4-4f16dd456ed5b31f8f8d","10c126ce21ddb47756a4-5adfe289cb3d8520b0ef","10c126ce21ddb47756a4-7f74b79cdc6913ea9d62","10c126ce21ddb47756a4-89f210443cbeae6bb2c0","10c126ce21ddb47756a4-9585120f51c086d40c8f","10c126ce21ddb47756a4-cda8340b8fcb3bc57b4e","10c126ce21ddb47756a4-d66611608cf890ccc13c","10c126ce21ddb47756a4-e88886cf009eb2d89a24","1c1beaa6e6bb68455687-02db839411b88f88324d","1c1beaa6e6bb68455687-19694be941e5fc5a50d6","1c1beaa6e6bb68455687-4fbd2cc9b2f8b51b955e","1c1beaa6e6bb68455687-620c0ccb2076231e1b46","1c1beaa6e6bb68455687-696baf01722eff41e180","1ce96103ecb38ee49d41-0a4191b4db0efcbae0f8","1ce96103ecb38ee49d41-a83ffa17458ba063ab54","260a9e5977a8ba3ec78b-dace76fe5d6fd2759124","2d5458d5effed0092e57-2c9621778a08fadbc834","2d5458d5effed0092e57-4156e62dca8bfb5afec0","2d5458d5effed0092e57-88e75e085e61e8618e6a","2d5458d5effed0092e57-9b4ef19a6cb0199bf241","2d5458d5effed0092e57-b0ff6e9dd7c295b37f2c","2d5458d5effed0092e57-b68f427de8c7c4e4c036","3f800034a832b756357b-2e3d05e6e1e746b6c156","426c3d5e1c2f1aa09ac8-f8d8b2894982189c8fdb","47563b3c243233393067-36286bd8f41799e49212","4b548bcc60ee243a112c-91f203d529a815190d96","5c28d935b3c657a6e5bc-b0a79157c365565b41e4","5c28d935b3c657a6e5bc-b7e3072f59f508bd7c81","5f37f0e1f4111ad5b126-a044c42b96a086d46495","6491031c3e271b473ed6-a1a41e105bc8e1f05019","6af163fea506aa4566f2-0d9793ea09690a80b966","6f9684bba76ed22e1a8c-76b8bbfc4abe6888a560","6f9684bba76ed22e1a8c-dcee5e388fad4727090e","7c975cd1ceb31d5d60dd-0dbdcff683eb513dc0f5","7c975cd1ceb31d5d60dd-20ec70d5fe0c22fab8a3","7c975cd1ceb31d5d60dd-44413c5a1543a1f5a65d","7c975cd1ceb31d5d60dd-f49b660fff35024b8100","848329c182e7112e80ae-9df4121368d3676326e8","8f00f316c6c46c156a1c-16b3484cc09d5255f8d6","92f4b5f6dbf60767921f-60d6762c4b0ae5b80aa3","9308de5e0d9b01cc3b0e-4cc494c7283e8466765d","9308de5e0d9b01cc3b0e-afbe709e30f6facd3dbd","9308de5e0d9b01cc3b0e-eb3f22266d782e009e06","9cc140ad818dd8f839cb-a80bbe7b29b7f5294127","b63caa6d5c82a89c01d9-930ae77b2adf34892aed","b76310c94a1ee56387bf-eee048f4f8692c102fb6","caebfb61a8a7d76a7401-1dbd614d29e180690a85","caebfb61a8a7d76a7401-7ac27f96d42f8e47da96","caebfb61a8a7d76a7401-dd9f678b3ba6fdaee2cc","d8f8caeb6165f1ef1fcd-2985a21f038abaa38e2b","db1daaef72d72e2312ab-71b65167efedb93432d2","df23f6ad1ee603a6ae65-e2cc6fb3ceccaeb1a09c","e6106fb403b25b398095-eba55dd6b22bb101f65d","e91c95e3d77f8c0bc288-27bf83ebb148b83122c8","e91c95e3d77f8c0bc288-393e6fb3b55e026c5927","e91c95e3d77f8c0bc288-80d244c353a9b5239063","e91c95e3d77f8c0bc288-864b2325f77eb8ef0979","e91c95e3d77f8c0bc288-8b088f9fd4352335f186","e91c95e3d77f8c0bc288-afada82cd2191181328b","fed0153cfc145e829673-749f411c6ea7761e557a"],"tests":[{"id":"004f08191fdf5a664c49-5934f2193bbcf4275249","project":"chromium","file":"Pages/Tasks.spec.ts","title":"List tasks by status","durationMs":73,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-6a8d58070f2721e22772","project":"chromium","file":"Pages/Tasks.spec.ts","title":"All built-in task categories can be created","durationMs":138,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-9a77320621e2e18ce3d6","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Create task with different built-in categories","durationMs":77,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-a034a19fedb3914dc554","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Resolve task with rejection","durationMs":75,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-a37baa03858ead321cb3","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Create task with assignees","durationMs":31,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-a6680360eb1c1db3276a","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Task priority levels","durationMs":113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-cf4a9c8c257c776dc018","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Resolve task with approval","durationMs":134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-dbd17b6aee48089a70bc","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Task ID sequence is unique","durationMs":106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-e915ae4e13ecb3f579d1","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Task CRUD operations","durationMs":60,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0052ab9e28cac302a481-57cf91322cdd33d989d4","project":"chromium","file":"Features/DataProductPersonaCustomization.spec.ts","title":"Data Product - customize tab label should only render if it's customized by user","durationMs":22259,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0052ab9e28cac302a481-f1eee6df796efc54fae7","project":"chromium","file":"Features/DataProductPersonaCustomization.spec.ts","title":"Data Product - customization should work","durationMs":24306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-061045104b0501529f9a","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate between tabs on glossary page","durationMs":9330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-254409f9a53adc8e7c67","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate to nested term via deep link","durationMs":7701,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-3b75351433e5696dd218","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate between tabs on glossary term page","durationMs":10142,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-6092fc9d785185e1febb","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should view activity feed on glossary","durationMs":9296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-9af09dcafe15890a4c22","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should post comment on glossary activity feed","durationMs":9084,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-a8188d2dbe1c913f81cb","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should post comment on glossary term activity feed","durationMs":9355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-dc08d608e28379784c90","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should show empty state when glossary has no terms","durationMs":8250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-ddd5214b0a60bd16b3ab","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate via breadcrumbs","durationMs":9397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-f505640efd2508d042ed","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should view activity feed on glossary term","durationMs":9549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-417dfcf921ef3832d10e","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"TagPage: Certification detail page routes through certification.tagLabel.tagFQN","durationMs":3921,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-5b17e1cf7d08cd3cb595","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"Certification filter narrows both table- and testCase-index queries via the flat field path","durationMs":6970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-b5d9a677fd75a83d66e4","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"Certification filter is rendered between Tier and Tag in the filter row","durationMs":6632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-c2f2bff31097429e61d5","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"Certification tags are not listed in the generic Tag dropdown","durationMs":7084,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-22e2c0617d842764b11b","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"surfaces the index banner and stays usable when search returns an index error","durationMs":12481,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-23d8e6ff84c5ddbabe5a","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"does not white-screen when the search request fails at the network level","durationMs":6094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-9eae8c06bfeb61c22fd9","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"renders gracefully for a malformed quickFilter URL parameter","durationMs":9435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-9f6105f6cdb93d1fd691","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"renders gracefully for a malformed browsePath URL parameter","durationMs":9602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01d9777d939990dabbd7-262dce1d2eeb8d343b4f","project":"chromium","file":"Flow/AppBasic.spec.ts","title":"should call installed app api and it should respond with 200","durationMs":3368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-22792cd610df6f5cade6","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create request description task for column","durationMs":11674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-2491067d6bcb5a54cb1f","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create request tags task for table","durationMs":10047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-25a394db38b512ef6f74","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create suggest tags task with suggested tags","durationMs":9727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-3046f4d31958bfd4dbf4","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should allow manual assignee selection when entity has no owner","durationMs":15347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-3557ecd547d5055ef28a","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create request description task for table","durationMs":14371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-64648a6c346cc46feb53","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should prevent task creation without assignee","durationMs":11668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-c8d9ec46c49bded4357b","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create suggest description task with suggested value","durationMs":8806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-1d172c84ee80912f5e2b","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Delete Button Disabled - Fully inherited contracts cannot be deleted","durationMs":20771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-38ad37abf46eb45d83a2","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Edit Asset Contract - Add SLA when inheriting SLA from Data Product (PATCH should use /add not /replace)","durationMs":29056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-46fe2ceba304a71d5ec7","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Edit Inherited Contract - Creates new asset contract instead of modifying parent","durationMs":26332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-567dac3aaaf0ed82e32c","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Run Validation - Inherited contract validation uses entity-based validation","durationMs":17329,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-a3744a7bd7f9ba4362bf","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Partial Contract Inheritance - Asset contract merges with Data Product contract","durationMs":30916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-b132cbad6c8242839b58","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Remove Asset - Inherited contract no longer shown when asset is removed from Data Product","durationMs":21984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-be0fe0b025326af56b6c","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Delete Asset Contract - Falls back to showing inherited contract from Data Product","durationMs":22506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-f085389ed08a523aed7e","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Full Contract Inheritance - Asset inherits full contract from Data Product","durationMs":26108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-0515ac5501ef2810b804","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12564,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-08ba9d2d9d9dd6d3b4a2","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-0d28e20e436777cb4128","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13544,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-0fafe939201d31585243","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":15310,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-12b31351571057d29cfd","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13092,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-2709b060aa5199ed7c46","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-3ae1dea8ac49be64dca4","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-3b46fb9bae34c93ab1e9","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12757,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-41007f7a6fab6e10596e","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13922,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-4a9e85c6f398e9f67275","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":8666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-4e3beed6243af81a754f","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":11057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-8cdf8f3a9f746fe00862","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-b73259974a470801efb0","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-bc4fcb436e3a2259227d","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":10517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-c2d03257ee6a2a9da060","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":7927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-cb0b667dbd687968d9a4","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":10163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-d0c505fe536cfd142768","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-db5d6a1f95b3e473d580","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":10032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-e5b3fd5755c76424ad67","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-1cee2b35ca54d4c31c16","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should prevent all users from modifying system test definition entity type via API","durationMs":7065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-360040f1744491234d09","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should allow viewing and editing but not creating or deleting test definitions","durationMs":13434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-5d4e43fff79360c3f26b","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should allow viewing test definitions but not create, edit, or delete","durationMs":10549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-6e5f9aa62a0c1a6a0b18","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should allow viewing test definitions but not create, edit, or delete","durationMs":10447,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-7092674b02cee0ed0c42","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should prevent unauthorized users from creating test definitions via API","durationMs":9664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-b2982050987bb5e8b4ee","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should not be able to edit system test definitions","durationMs":13335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-e6aff96f2117419d34a3","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should prevent unauthorized users from deleting test definitions via API","durationMs":13540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-38d034de72fa8cbb70cb","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should not show online status for inactive users","durationMs":6749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-3e05f86121d3c978d4a2","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should show online status badge on user profile for active users","durationMs":6838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-43e97a2523a7811c8bb0","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should show online status below email in user profile card","durationMs":7129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-b7bc8e5ed7bc4471ba0a","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should update online status in real-time when user becomes active","durationMs":13208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-e0bd28c84529a51c89aa","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should show \"Active recently\" for users active within last hour","durationMs":6438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0a56168a40b882fe6894-170e1f3eff5aa971e713","project":"chromium","file":"Flow/FrequentlyJoined.spec.ts","title":"should display frequently joined table","durationMs":9898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0a56168a40b882fe6894-84ac3055d73ecf89a21d","project":"chromium","file":"Flow/FrequentlyJoined.spec.ts","title":"should display frequently joined columns","durationMs":11540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-011fed074239d8794a66","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Admin can remove the default persona for a team","durationMs":9409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-027f80afc1576bc6be86","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Persona rename flow should work properly","durationMs":8472,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-1030722b78088d2ec6ec","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"User without permissions cannot edit team persona","durationMs":8632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-135241804761fb629b85","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Delete persona should work properly","durationMs":7771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-187a985529b191d190fb","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Persona update description flow should work properly","durationMs":6526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-25b967abba28bb47f099","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Description Contains filter – table with matching description appears in widget","durationMs":19069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-2c59da2e1af01cfdfb95","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Remove users in persona should work properly","durationMs":7326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-47c2545428c8641b1aba","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Non-group team types do not have a default persona setting","durationMs":9359,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-828969cb1530df18a4e9","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Set default persona for team should work properly","durationMs":11418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-c91b116cdca0ef43878d","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Set and remove default persona should work properly","durationMs":42419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-e8766d04fa25cb1329b6","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Persona creation should work properly with breadcrumb navigation","durationMs":11581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b721dc6d1e4c283a3d7-254b18deceb1b36bf441","project":"Basic","file":"Pages/Policies.spec.ts","title":"Add new policy with invalid condition","durationMs":14817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b721dc6d1e4c283a3d7-9938e72067584c0c12ab","project":"Basic","file":"Pages/Policies.spec.ts","title":"Delete policy action from manage button options","durationMs":8661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b721dc6d1e4c283a3d7-de3a6ddc322ed853fa63","project":"Basic","file":"Pages/Policies.spec.ts","title":"Policy should have associated rules and teams","durationMs":6026,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-047be35b194c9d866468","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide tokenValidationAlgorithm for OIDC providers","durationMs":5221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-0833169ee6407ec5c50d","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide publicKeyUrls field for confidential OIDC providers","durationMs":4720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-0989b149fa1918db6a13","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Azure AD provider","durationMs":4990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-0bcb263825f9b25094cd","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide clientAuthenticationMethod for Auth0 provider","durationMs":5991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-19081ba3791a2c4eba3f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should enable Configure button when provider is selected","durationMs":5294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-1e149432136c7a6db559","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show SAML SP Entity ID and ACS URL as readonly","durationMs":4970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-22abb186177c16862afa","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should stay on /settings/sso when pressing back if SSO is not configured","durationMs":4328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-2474fda7d7d183e84f6f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide publicKeyUrls for LDAP provider","durationMs":5434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-2a2ad991e5c06901f99e","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Okta provider","durationMs":5228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-2e18cb79c436daab7829","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show advanced fields when advanced config is expanded","durationMs":5643,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-34fba19c758dadd4b5cb","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide jwtPrincipalClaims for SAML provider","durationMs":5125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-38ca5d4d684728fccecb","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Google provider","durationMs":5437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-3a87615ac059ba986272","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should navigate to /settings when pressing back if SSO is already configured","durationMs":9537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-3e41514daf189541ef7a","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide SAML SP callback URL field","durationMs":5510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-47ac2af718829befd92f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show tenant field for Azure provider","durationMs":5237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-4daf0d02c9591a8510d5","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should expand and collapse advanced config when clicked","durationMs":5212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-4df25211bef2dfa32e40","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should render authReassignRoles as a searchable dropdown and support role selection, removal, and search filtering","durationMs":6756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-51d4acdbee95dd109eb6","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide preferredJwsAlgorithm and responseType for OIDC providers","durationMs":5506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-546b90ad1991b04d4494","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide serverUrl field for OIDC providers","durationMs":5148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-55b88df9f30715574758","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should collapse advanced config by default","durationMs":5508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-5a6348a858f0bbba6ae2","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting Google provider","durationMs":5887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-61a7fabbf89bc2f26c7f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields for Okta provider with confidential client","durationMs":5369,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-61d0e3405cdc819cc222","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting Okta provider","durationMs":5809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-67b572e98086ce7eac3b","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show upload drop zone for SAML provider","durationMs":3596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-6a1992cd6f70ad36be17","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should parse valid SAML metadata XML and populate form fields, then clear fields on invalid XML","durationMs":3384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-726836846c61acacf72e","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide jwtPrincipalClaims for LDAP provider","durationMs":5195,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-79775feb638787094aa2","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should display advanced config collapse for OIDC provider","durationMs":4955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-7a25922674aa447ae188","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should support full LDAP role mapping flow: add, fill, open roles dropdown, detect and resolve duplicates, and remove","durationMs":7056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-7a4121fbd7ff73813e83","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show clientAuthenticationMethod for Okta provider","durationMs":5798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-88267c4e251dfab9d1c7","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide publicKeyUrls for SAML provider","durationMs":5280,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-9571bd75cfb56b064f18","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should not display role mapping widget for non-LDAP providers","durationMs":4833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-977c5309463a2194ae58","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields for Auth0 provider with confidential client","durationMs":5405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-98f71413d99725507f60","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields for Google provider with confidential client","durationMs":5964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-9b94064cfad5336dc576","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting SAML provider","durationMs":5405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-a2653b3971e7a3dfe31c","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide tenant field for Auth0 provider","durationMs":5725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-b415cb2dc167ddb53dda","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting Auth0 provider","durationMs":5738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-c3a47af5c898e89c1d82","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should validate the configuration without saving and show a success banner","durationMs":7146,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-d785f2f4f674973f449b","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Auth0 provider","durationMs":5342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-debfc2945a6f9ce23750","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting LDAP provider","durationMs":5437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-ea466a94c0478617e9d8","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show the Test Configuration button and lockout warning for a new configuration","durationMs":7224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-f6cf49ad9159c898f8ff","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should surface validation errors when the test fails","durationMs":7384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-f74d7edc9c9978851109","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should display all available SSO providers","durationMs":4931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-4e375083d590a9a5acea","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Version diff shows synonym changes","durationMs":7758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-73f6fddc80038a5eae47","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"GlossaryTerm","durationMs":21201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-7cf3cccd2fd4e86bbcd0","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Version diff shows reference changes","durationMs":9592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-926156befd108528b026","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Return to current version from history","durationMs":9991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-abb395dc56eb33d395fb","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Navigate between versions","durationMs":12279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-c125342150e1c90238d5","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Glossary","durationMs":29590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-c9fa2cbac6df0316a4ae","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Version diff shows related term changes","durationMs":11321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0fc3c96fe730fa7ec869-cf1d8bf1cc1db0d05bbf","project":"chromium","file":"Features/IngestionListNameSorting.spec.ts","title":"should keep a sorted page addressable across a reload","durationMs":9502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0fc3c96fe730fa7ec869-e123a56fe8bf877f9303","project":"chromium","file":"Features/IngestionListNameSorting.spec.ts","title":"should sort the Name column by the name shown in the cell","durationMs":5593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-04d6154814646027d691","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"dataProduct supports removed property value variants","durationMs":5832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-0741446b51bd1831b1fb","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"dashboardDataModel supports removed property value variants","durationMs":5360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-211bb353cbf91b58df5a","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"apiEndpoint supports removed property value variants","durationMs":5548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-2a8d02fe65e159aa7997","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"mlmodel supports removed property value variants","durationMs":5508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-326e5741aa3e465e11c0","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"searchIndex supports removed property value variants","durationMs":5871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-439a804c72c1029b9604","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"domain supports removed property value variants","durationMs":4448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-485027c527c4c17d746c","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"pipeline supports removed property value variants","durationMs":6377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-49aa937a33fa5a8948c9","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"metric supports removed property value variants","durationMs":5784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-4bca0aa80c53d7c4a24c","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"databaseSchema supports removed property value variants","durationMs":5606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-4f16dd456ed5b31f8f8d","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"container supports removed property value variants","durationMs":6827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-5adfe289cb3d8520b0ef","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"tableColumn supports removed property value variants","durationMs":5871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-7f74b79cdc6913ea9d62","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"glossaryTerm supports removed property value variants","durationMs":6340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-89f210443cbeae6bb2c0","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"database supports removed property value variants","durationMs":5065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-8fec358bf4604e70210f","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"custom property value contract covers the exact removed browser matrix","durationMs":18,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-9585120f51c086d40c8f","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"storedProcedure supports removed property value variants","durationMs":6941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-cda8340b8fcb3bc57b4e","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"apiCollection supports removed property value variants","durationMs":5201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-d66611608cf890ccc13c","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"topic supports removed property value variants","durationMs":5318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-e88886cf009eb2d89a24","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"dashboard supports removed property value variants","durationMs":4402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10d375d35d7071018386-deeb63637a49a6e9339d","project":"chromium","file":"Features/Permission.spec.ts","title":"Permissions","durationMs":62113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-1764dc17d058c43ed0e6","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should keep the run history reachable when the status call fails","durationMs":3870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-373310b628ca43526007","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should list the agents with disabled actions when the status call fails","durationMs":3353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-9438db641e0109169435","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should list the agents while the status call is still in flight","durationMs":3668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-9f029e8b570eb3564250","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should still explain itself when the status call answers with no reason","durationMs":3801,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-15dfb2af7e1db8aec21c","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":14873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-2de09c93fa26511e5882","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":20482,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-3b84db11da31ab9d60f8","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":19906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-412088496e870362a6bb","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":14439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-5185f8d1e5c3bfb6de74","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":20172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-6c3ef71e9c671b248b36","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":15134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-747d62ad76876a268122","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":15014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-7a96261fbe77abc31f4a","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":20356,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-cdd1bc8be764f4d1dc7f","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":16205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-d007ef1cc9caf0532ddc","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":14876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-ffab3b8233da881cb344","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":17556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-0396a683a217404bc705","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"term from another glossary is hydrated in as a node","durationMs":35937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-3396e18d2b057b036c37","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"cross-glossary edge is present in graph data","durationMs":35767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-343af4d62aaba2630406","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"relation filter with no matching edges shows no-relations state","durationMs":35543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-50ed7c1fbcf33c138817","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"clicking a neighbour node opens the entity panel","durationMs":7087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-51484391b4e911f246e9","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"stats include the cross-glossary relation","durationMs":33462,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-6bb1183fced6fb9f8f96","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"only the term and its direct neighbours appear — unrelated term is absent","durationMs":6655,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-7564b4e242fb53c6b77e","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"zoom and fit-view controls are visible","durationMs":6910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-819430d5e839658621ad","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"removing the relation filter restores connected nodes","durationMs":34875,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-9d0332e87b84fec9721d","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"isolated nodes OFF + unmatched relation filter shows no-relations, not empty state","durationMs":34710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-b12144b2967a7a2731c9","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"edge between the term and its neighbour is present","durationMs":6216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-b471627ee638b7bfebca","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"global filter toolbar is hidden in term scope","durationMs":6028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-c3b40279304ec46428af","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"ontology explorer is visible in the Relations Graph tab","durationMs":5762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-d5ce5f84b1effb571047","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"re-enabling isolated nodes while relation filter is active keeps no-relations state","durationMs":34563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"138116cad0db6db3e31c-0db6bba1bba36a56c98e","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":25368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"138116cad0db6db3e31c-8ab63046fdfd9ef943c1","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":24932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"13ef108ee6fd737d094f-086a50c8e31b6ccf6ff3","project":"chromium","file":"Pages/DataProductCertificationFilter.spec.ts","title":"lists only certifications assigned to data products","durationMs":7948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"13ef108ee6fd737d094f-a19672220bf86f8386a8","project":"chromium","file":"Pages/DataProductCertificationFilter.spec.ts","title":"filtering by a certification narrows the listing","durationMs":11396,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"14bd5adb6df9a88c340f-29600d766f20a5eaaea8","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should edit reference URL","durationMs":10594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-296c68d33da16a9dd7d8","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should cancel term creation without saving","durationMs":8815,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-2b2204bb8ab1e8834014","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove related term","durationMs":10542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-3b7344c642f950c9343a","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should show error when glossary name exceeds limit","durationMs":8090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-60710dd072ecbdae486b","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove tags from term","durationMs":10484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-67cb7301397b8e2167cb","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove domain from glossary","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"14bd5adb6df9a88c340f-6aef0428615488839b7e","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create glossary with multiple owners (users + teams)","durationMs":14551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-6c8759c68ef5992a7234","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should handle term with very long description","durationMs":9630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-7c48d938e18034fdb3ab","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should replace reviewer on glossary","durationMs":11794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-7c861f5b15fc8efe5687","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should edit reference name","durationMs":10678,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-7e20f808cda196f4b965","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove owner from term","durationMs":12883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-80d0b311299387783e9c","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should replace owner on glossary","durationMs":11263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-8223e5ca58ae964dbb30","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should clear all synonyms from term","durationMs":10798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-87accf1b092c476fa522","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should change domain on glossary","durationMs":11048,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-a1d727fbf53816e3e867","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create term with custom style color","durationMs":9498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-a5945883ff9686302ca6","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create term with custom style icon URL","durationMs":10134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-ab969a7d4761c13683d1","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create glossary with mutually exclusive toggle OFF","durationMs":8721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-bced7f631eafead67a79","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should update term style to set color","durationMs":9758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-bfd5ef7659767ee9c04c","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove individual reference from term","durationMs":10254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-c0a2104006b98732511e","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should show error when term name exceeds limit","durationMs":9502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-d09abb82cd12494db539","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should update term display name via manage menu","durationMs":10948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-d6b1141fd8a29c352619","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should show bidirectional related term link","durationMs":9528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-d81fab109e3f20196586","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove reviewer from term","durationMs":11625,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-dcac77ccd1673ede0375","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should cancel glossary creation without saving","durationMs":7238,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-e6d2869b45eb07973d63","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should update term style to set icon URL","durationMs":10246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-f15ee3dbeb3557870e2a","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should handle term with very long name","durationMs":9689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-f9256cb87400d1374dfe","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create term with related terms","durationMs":11817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-042c40f6b1a54e6c53ae","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when glossary name is empty","durationMs":5261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-48fa78f24f68871eb1a6","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when creating glossary with duplicate name","durationMs":5234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-7932aa55fdb2a147ece7","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when term description is empty","durationMs":6253,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-7fa3c393df4fd3e48395","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when term name is empty","durationMs":5860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-fb157931edfad50a16d6","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when glossary description is empty","durationMs":4528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-108588a17dc7c1e9e7ab","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"filtering by synonym should show only terms connected by synonym and hide others","durationMs":36584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-455d392a14de1202ee13","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"switching back from Data to Model mode restores stats","durationMs":37741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-45db8d08e9700d762767","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"clearing relation type filter should restore all connected nodes","durationMs":36474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-4d34613e9fd9b0bda54f","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"should reflect relation add and remove in the graph","durationMs":105498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-542208ececb3910f878c","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"should display terms with narrower relation in Hierarchy view","durationMs":40372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-77906f4cbeabbb0481ab","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"Data mode stats do not show Data Assets when no assets are tagged","durationMs":38904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-78cdd2ed39025ffeff45","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"filtering by relatedTo should show only terms connected by that relation and hide others","durationMs":37540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-8b23927bba2fc7066544","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"Cross Glossary view hides terms that only have same-glossary edges","durationMs":38148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-a349c74e7f92a667705f","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"isolated nodes toggle is disabled when Cross Glossary view is active","durationMs":5743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-d1299047f5e68bc2788d","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"Cross Glossary view should show edges between terms from different glossaries","durationMs":39770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-d40d2b4f41f456fda733","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"clicking asset count badge in data mode triggers asset search query","durationMs":38183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"179dbf18e2af7f4cbec2-3e866d93ac6b4b246fc4","project":"chromium","file":"Features/Permissions/DomainPermissions.spec.ts","title":"Domain allow operations","durationMs":28360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"179dbf18e2af7f4cbec2-f81418f6b9c6495bc826","project":"chromium","file":"Features/Permissions/DomainPermissions.spec.ts","title":"Domain deny operations","durationMs":29046,"attempts":1,"retries":0,"outcome":"expected"},{"id":"18494d13c3e927572e0e-8d190554ecc9cdce0e8b","project":"Basic","file":"Pages/CustomThemeConfig.spec.ts","title":"Update and reset custom theme config","durationMs":8422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"18494d13c3e927572e0e-98fda58f97982dc8e671","project":"Basic","file":"Pages/CustomThemeConfig.spec.ts","title":"Should call customMonogramUrlPath only once after save if the monogram is not valid","durationMs":9455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"18494d13c3e927572e0e-c6dc3de533286e6d221d","project":"Basic","file":"Pages/CustomThemeConfig.spec.ts","title":"Update Hover and selected Color ","durationMs":8723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-1087a144c5cc50d535ee","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should open right panel when clicking data product card in domain","durationMs":9079,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-13aa03b757371c9adb72","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should display overview tab for data product","durationMs":8308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-237ee97a03dc27da8efa","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should display overview tab content for data product in domain context","durationMs":7050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-2cdd99c8ce2bb06b59ed","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should not display glossary terms section in domain data products context","durationMs":7555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-a76035f76a4eea346b55","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should display data product name link in panel in domain context","durationMs":8455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-c15c8f4e2f276a832be4","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should edit tags for data product from domain context","durationMs":9357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-cffeac6eeaa76dd6886b","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should edit owners for data product from domain context","durationMs":10426,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-de5961ae0dcc1dc1eb7c","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should edit description for data product from domain context","durationMs":9531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-f4986293245e7e080a70","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should assign tier for data product from domain context","durationMs":9912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-537cb9c232ceabecba8e","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"service lineage has pipeline service connected to both services","durationMs":3637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-612653f6947301a02b49","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"database service has pipeline service as downstream in service lineage","durationMs":3217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-80746b789ad7769474c0","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"entity lineage does not include service nodes","durationMs":3776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-a52558b2d5f6468bb5ea","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"entity lineage edge preserves pipeline annotation","durationMs":4438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-02b5ace1b2248b785a49","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with EditAll can export ODCS contract","durationMs":10633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-2125ddb8382292c5fdda","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with EditAll can import ODCS contract","durationMs":12155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-2ff6b56ee053f07bce20","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Admin should see all import and export options for existing contract","durationMs":7514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-4bc8465740aa8464ebd6","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Admin should successfully import ODCS contract","durationMs":7636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-5cc7d37ab19d320a7f43","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Consumer can export ODCS contract","durationMs":7543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-5fd734b0bc28d6e08535","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Consumer should see export but not import options","durationMs":6677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-75e594ea4b3040db9f2b","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with ViewOnly should see export but not import options","durationMs":10532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-82f6c0dde199e09a485e","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Admin should successfully export ODCS contract","durationMs":6956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-83e7b1c072c2dde4d9ea","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Steward should see export but not import options","durationMs":7889,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-b39b794f3ed9fde9e63c","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"API should allow export for users with view permission","durationMs":4776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-c6dae5c5f1756c1d0e66","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with EditAll should see all import and export options","durationMs":10410,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-d72f4e2dbeb3c195ab46","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Steward can export ODCS contract","durationMs":7258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-ed0768c8b67f4feea53f","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with ViewOnly can export ODCS contract","durationMs":8374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19b2b14ce084d7e3579a-201004f6be67ac9d9065","project":"chromium","file":"Features/CustomMetric.spec.ts","title":"Column custom metric","durationMs":19915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19b2b14ce084d7e3579a-c4d4be4d5d794d22c090","project":"chromium","file":"Features/CustomMetric.spec.ts","title":"Table custom metric","durationMs":10495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-3b16f2702fc12cd8074e","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create term with tags","durationMs":9783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-45bb6a8bde203b85b1cf","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create glossary with tags, owners, and description","durationMs":8108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-51e4f8807e00f57e0192","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create term with synonyms","durationMs":9186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-612c0266b544101fdc87","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create child term via row action button","durationMs":8702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-ad5dd701c1d496e2781d","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should navigate between tabs on term page","durationMs":7470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-b3aae0fef2551ec89460","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove owner from glossary","durationMs":7980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-c2ba3a55bcfac2bf76cb","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create glossary with mutually exclusive enabled","durationMs":8603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-e9fd39fecbc9feeff1f8","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should delete parent term and cascade delete children","durationMs":7819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-ec658667dc5b068c0a42","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove reviewer from glossary","durationMs":7456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-ee3ddfd6112d2b10da41","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove tag from glossary","durationMs":7807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-f3901eb61f81592f1a02","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should display parent term with children for drag operation","durationMs":7428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-f658c35c19332d4004f1","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove synonym from term","durationMs":7666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-f8e45548f1769c59d321","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create term with references","durationMs":9145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a6f1da61460ebe7ad36-7a6c1a3faf2cfc2648d7","project":"chromium","file":"Features/QueryEntity.spec.ts","title":"Query Entity","durationMs":29411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a6f1da61460ebe7ad36-a06d40e1bc9c3f5e1457","project":"chromium","file":"Features/QueryEntity.spec.ts","title":"Verify query duration","durationMs":10433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a6f1da61460ebe7ad36-cf42d000893656b64dbd","project":"chromium","file":"Features/QueryEntity.spec.ts","title":"Verify Query Pagination","durationMs":10827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-0088ed46eab587c90371","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should restore filters from URL on page load","durationMs":11518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-014321099028e71df84c","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should load the page with stats cards and grid data","durationMs":7779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-170dbfd48cfc4dd5c106","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show Service filter chip from URL","durationMs":9657,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-185597b794db3ab6912c","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should update display name and propagate to all occurrences","durationMs":26004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-239c0f77e33ddb02ed00","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should search columns with server-side API call","durationMs":8124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-23c5e0255a245d7bd4a2","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should clear individual filter and update URL","durationMs":22068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-2e96f151f46e62aaae33","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should select and edit nested STRUCT field","durationMs":24638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-32b4d960f036903b8b97","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should open edit drawer when clicking on aggregate row","durationMs":5822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-39e4bd843402570f4339","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show success notification after bulk update","durationMs":27399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-3ef93584d85256069ad4","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show no results when searching for nonexistent column","durationMs":7852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-3ff3cebfc11e44e7369b","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show disabled edit button when no columns are selected","durationMs":5539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-4a4df818cbe72b56fd42","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should not reset stats to zero while search request is loading","durationMs":7845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-59c5f8a31c7199210394","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should not count aggregate parent row in drawer selected count","durationMs":6834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-5dac5fccf031408603db","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should expand STRUCT column to show nested fields","durationMs":25371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-6c8908c3cd1359e50b2b","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show pending progress spinner after submitting bulk update","durationMs":22861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-7267cda84897fc91f6dd","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should update pending changes counter when editing selected columns","durationMs":23547,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-797101ebe2b800c4b2a4","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should select column, open drawer, and verify form fields","durationMs":23850,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-8491c672cd59d38141d9","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show column count for multiple column selection","durationMs":3453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-8b7eb228bf6a6d35884e","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should filter by metadata status and verify API param","durationMs":26462,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-94fbdadd8c9d95ead874","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should filter by entity type (Table)","durationMs":7054,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-c6b5c6fa386a261c9945","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should cancel selection and disable edit button","durationMs":21941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-c9cf4dffe0aa3ea711bb","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should accept text with spaces in the description field","durationMs":21050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-cef1122673da72e852b8","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should navigate through pages","durationMs":9419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-d2e9a4b29a88686387ab","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should keep latest search results when responses arrive out of order","durationMs":48745,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"1a7cffc95ce4e87fc41d-da1a0b3fd0cc0e01ed6d","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should discard changes when closing drawer without saving","durationMs":25322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-7ff955e7b470d12f6b1f","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve mlFeature description task for MlModel","durationMs":653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-968585514b3da1da4c2e","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve requestSchema field description task","durationMs":599,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-9ab19e4c245ad906a5d7","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve responseSchema field description task","durationMs":291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-b59abc2f87ac29cd2972","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve nested field description task for SearchIndex","durationMs":190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-b8d86ff533deaebb79b9","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve field description task for SearchIndex","durationMs":218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-ceff75e902b4028fe53b","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve column description task for DashboardDataModel","durationMs":386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-088888d65c2c12c7041b","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with EditAll on TEST_CASE resource should not be blocked from bulk edit page","durationMs":11904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-10fd0dc506e83a7ecd02","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer should see export but not import & edit options","durationMs":9166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-12f1201233201134e21a","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should redirect to Table Data Quality tab when canceling table-level bulk edit","durationMs":9799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-219eece6de17e298670b","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to import page from Data Quality tab","durationMs":5513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-2f5d1810bf9a82344168","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should export test cases from Logical Test Suite page","durationMs":9290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-3514378a10d1a2777e69","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should upload and validate CSV file","durationMs":14353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-4469b1ebd6879db66e32","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with EditAll & ViewAll on TEST_CASE resource should see import, export & edit options","durationMs":12807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-47d1b7b068edeb4ac63a","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward should be blocked from import page","durationMs":5917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-570ebf80af90e61924f8","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer can successfully export test cases","durationMs":9964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-62a7e656fc98846ddce6","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer should be blocked from bulk edit page","durationMs":3802,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-6647b28c5e6d51f38b7b","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with ViewAll on TEST_CASE resource can successfully export test cases","durationMs":16117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-66538490a691fb2cadbe","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should redirect to Test Suite page when canceling bulk edit","durationMs":10340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-6f744fd1e24888ade4df","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer should be blocked from import page","durationMs":4093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-76c7b490768e9355c0d9","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward should see export but not import & edit options","durationMs":8679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-7ebd62f24bf13648f5fe","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward should be blocked from bulk edit page","durationMs":5038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-8b8f266e0c798fecdbf0","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward can successfully export test cases","durationMs":12886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-9aac88cc9731e6741e41","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should show validation errors for invalid CSV","durationMs":9584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-c3b94742e06f23717451","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should redirect to Data Quality page when canceling global bulk edit","durationMs":10149,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-c555aec9e622f36a508c","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with EditAll on TEST_CASE resource should not be blocked from import page","durationMs":8167,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-d3e2ea3896d13e010edd","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should export all test cases from global data quality page","durationMs":15001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-e074e2a35b2354778e27","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should export test cases from Data Quality tab","durationMs":10960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-e41293a41d782cbfb0c7","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to import page from global data quality page","durationMs":4672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-f20e9de461c4e6cfadc6","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to bulk edit page from Logical Test Suite page","durationMs":15526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-f7761c9107599ffa5435","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to import page from Logical Test Suite page","durationMs":4782,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-081025371a2814b4fb5f","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":11835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-0a4191b4db0efcbae0f8","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":9794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-11ad6728a046d81592e9","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-16216a857e97288f66c5","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-1d2ca67614bbdde8e805","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-1ea9821cb6097c0ec98f","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":10856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-20781c678687a66fa68b","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-20f85fdc0656235f5cf7","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-2abec9f21a8ea3b2cc4f","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":15010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-2e08b3569bf413a4b41d","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-2eee0c93c970f8d07682","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":14807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-38553a39450ce7270e88","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-4f11e50f706352784b6e","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":11945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-5bf28053c2a051ccdfa3","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-693a5a472bbdcd5d7c39","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-6f03ad71cb5cf3694aeb","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":8760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-70f4e24aa49e1afddd61","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":10868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-75aab610bb32463cf2dd","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":8862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-7930c4d3ae24ea30f63c","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-7bbb32de38f97fcb06e3","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":10568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-7d221bdeacd5afefd2ab","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":10882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-88e41b978ee0ef287d92","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":13044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-8db06fd539e01dd3bbaf","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10480,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a1a032a22693be0119e4","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":10708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a5652ed373875bbfa978","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a83ffa17458ba063ab54","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":11870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a89c14c356526919c60e","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":8406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-b9b78692b1500d345e57","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":9704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-c458a06a93bfddc93263","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":8926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-cf44adf2e574fb2cbc19","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-cfdcfe160d3952303e12","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-d1725f195b4f94165c61","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":14338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-d3a1704a85d2cfaf31cd","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":9196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-d636fe1feb6796f668e6","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-f2418d8c375a80d46f69","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":13058,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-fd849b08a1243d3a9494","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":14909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ceb1bff96abee8abc39-80f3f55b370556d0a638","project":"DomainIsolation","file":"Features/DomainIsolation/DomainDropdownIsolation.spec.ts","title":"Admin sees every domain and the All Domains option","durationMs":7436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ceb1bff96abee8abc39-cfe97d75645c1db901ff","project":"DomainIsolation","file":"Features/DomainIsolation/DomainDropdownIsolation.spec.ts","title":"Restricted user sees only their own domains in the navbar dropdown","durationMs":5901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-1965ba5132d65f76b54f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should assign tier from tag assets page context","durationMs":13335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-1f93c23ec60eeb578f8f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit owners from tag assets page context","durationMs":14763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-6551d3f84e4ae3617f7f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit description from tag assets page context","durationMs":9167,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-6d105f08c01f5f945b88","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should open right panel when clicking asset in tag assets page","durationMs":12335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-74d2940c2fb33c358ae0","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should display correct tabs for table entity in tag assets page context","durationMs":7568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-8a7973d64b54fd04b10f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should display overview tab content in tag assets page context","durationMs":8746,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-9193d8183ffaf8094b63","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit tags from tag assets page context","durationMs":12420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-9613819e7989c4a50ea5","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit domain from tag assets page context","durationMs":13190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-c822ef782390b573e856","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit glossary terms from tag assets page context","durationMs":8794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-cf6d8d95a859ea58c1be","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should display entity name link in panel header in tag assets page context","durationMs":7551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-fc44c04a118fcf119b28","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Panel should not be visible before any asset is selected","durationMs":2705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1e7ae5f087867b855c68-48cd403ded8704aa6847","project":"chromium","file":"Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts","title":"navigates to the entity detail page when the link is clicked","durationMs":9045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1e7ae5f087867b855c68-4dc58e52f2b3ef4ddc40","project":"chromium","file":"Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts","title":"renders a clickable entity link for instances with a related entity","durationMs":8888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1e7ae5f087867b855c68-50e09093829a8af6a7a5","project":"chromium","file":"Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts","title":"shows the no-data placeholder for instances without a related entity","durationMs":8517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-0b7d1730a6386f5560c5","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"a non-leaf node count reflects the active Data Assets filter","durationMs":9838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-2cbd0173a43e19a49632","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"selecting a schema keeps the drilled path expanded and highlights it","durationMs":9199,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-4062943a54eac71c08c2","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"browsing the tree stacks removable QUERY chips and filters results","durationMs":9733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-50dc1266c26cb8e4ef67","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"the entity-type leaf respects the Data Assets filter (Table hides Columns)","durationMs":12205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-622bb480069d7b96ff7f","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"Glossary leaf under Governance filters the results","durationMs":8519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-86705f5803eae96f692b","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"drills the database hierarchy down to the Tables and Columns leaves with counts","durationMs":7947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-94b4249e6fb96c12d2b3","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"service type drill-down disables unrelated roots and query-panel Clear resets it","durationMs":10158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-a705079e6c267810beba","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"selecting the Tables leaf highlights the leaf, not its parent schema","durationMs":8900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-a84cc2d736afdc4a7016","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"Tags leaf under Governance filters the results","durationMs":9000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-f1cb8868b95fbc0f7ce2","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"every result-card breadcrumb links to its hierarchy destination","durationMs":8627,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-fac7d8785eac504ff222","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"drills a non-database hierarchy (Dashboards) down to the entity-type leaf","durationMs":8964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1f761de977875b0ac365-5f3ed1d5eca7edaa77b7","project":"Basic","file":"Features/TeamsHierarchy.spec.ts","title":"Add teams in hierarchy","durationMs":18273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1f761de977875b0ac365-9f33170dce0c34953135","project":"Basic","file":"Features/TeamsHierarchy.spec.ts","title":"Check hierarchy in Add User page","durationMs":11672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1f761de977875b0ac365-c663c28071eca27c2f9f","project":"Basic","file":"Features/TeamsHierarchy.spec.ts","title":"Delete Parent Team","durationMs":11434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2001c1c02e517ab398de-49967e402c6c0fbe2572","project":"Basic","file":"Flow/LineageSettings.spec.ts","title":"Verify lineage settings for PipelineViewMode as Edge","durationMs":15531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2001c1c02e517ab398de-79465f7bd5a7cf3d01cc","project":"Basic","file":"Flow/LineageSettings.spec.ts","title":"Verify lineage time filter and tab switch reuse loaded graph","durationMs":10330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2001c1c02e517ab398de-c9abd4818a163664575b","project":"Basic","file":"Flow/LineageSettings.spec.ts","title":"Verify global lineage config","durationMs":27238,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-48420345617d1a8ef174","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Resolving incident & re-run pipeline","durationMs":17751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-6defbf65f0f7b32af71a","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Verify filters in Incident Manager's page","durationMs":10569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-77c6d8b0db807c48f0f5","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Rerunning pipeline for an open incident","durationMs":18516,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-af5d262d6380615148dc","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Validate Incident Tab in Entity details page","durationMs":6100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-d2d654438df91f046bde","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Complete Incident lifecycle with table owner","durationMs":32190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-137a99fe0f15c4a98a02","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Drives Service Spreadsheets Table should have search functionality","durationMs":9635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-25125140ebe405ad916b","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Drives Service Directories Table should have search functionality","durationMs":10403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-4448687b3721cbb49b49","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Stored Procedure Table should have search functionality","durationMs":10648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-5cf93c1909876091f46c","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Database Schema Tables tab should have search functionality","durationMs":10977,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-60cfa1796b7b024699b6","project":"chromium","file":"Features/TableSearch.spec.ts","title":"API Collection page should have search functionality","durationMs":11001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-76b22267beb30e6ce153","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Services page should have search functionality","durationMs":11317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-79db68618d5b1154ffa1","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Data Models Table should find data models by displayName","durationMs":10795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-8f0b48ff70e49c23a10c","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Drives Service Files Table should have search functionality","durationMs":10160,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-cc7c974eeb90a2ace251","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Data Models Table should have search functionality","durationMs":10849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-d705aa5a323d4919dc01","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Data Models Table should find data models by mixed-case name","durationMs":11931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-fede3d39c728e9fc5d3b","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Topics Table should have search functionality","durationMs":10784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-7a5065f335aef4798767","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Multiple rename + update cycles - assets should be preserved","durationMs":27777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-8268f8edccd6575fc094","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Rename then change owner - assets should be preserved","durationMs":19161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-e6575adf21443f9e4abc","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Rename then update description - assets should be preserved","durationMs":19807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-f2d0ea7623838b225b12","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Rename then add tags - assets should be preserved","durationMs":18428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"222fe1e5206cdd75a358-7d5f8774b1fce82284d3","project":"Basic","file":"Features/CronValidations.spec.ts","title":"Validate different cron expressions","durationMs":9469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-3c63e984b9371e4d91c8","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All with Draft filter shows all terms including children of non-matching parents","durationMs":9040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-689fbbe40540b5d50eff","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All with default filter shows all terms","durationMs":7470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-b0971994404c76b9db78","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All shows all children regardless of status filter","durationMs":12145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-b5a7414e2cf53479e246","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All with Approved filter shows all terms","durationMs":8923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2385db9fde781bb59544-ac35955bbae6a48adf8c","project":"chromium","file":"Features/IncidentManagerPagination.spec.ts","title":"Page size dropdown updates list limit and resets to page 1","durationMs":6618,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2385db9fde781bb59544-fd49dbad03ff26fc50b3","project":"chromium","file":"Features/IncidentManagerPagination.spec.ts","title":"Next, Previous and page indicator","durationMs":6251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-064c76de14054d025202","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> apiEndpoint","durationMs":32104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-0d9bbd826523da4a8f43","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> apiEndpoint","durationMs":36882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-0f02f3b748ae134173df","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> table","durationMs":33613,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-13cc491cb5ca92a3ab0c","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - File","durationMs":187485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-14b2454310f82a3c0843","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> searchIndex","durationMs":30009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-16eca21baf156dbcf4a0","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> apiEndpoint","durationMs":28460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-18358f8facc6b4296831","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Spreadsheet","durationMs":174081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-1e0430cd28c2c8054cfa","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"should render temp lineage table nodes on canvas","durationMs":9368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-21ce9dbac82c26a63b8f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify validation for invalid depth","durationMs":7378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-27638ce37ef6999a284b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> dashboard","durationMs":41793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-2b7f46364906eadbe405","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> mlModel","durationMs":31265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-2d3070c5aa20d0e6b1a8","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Mlmodel","durationMs":192299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-2e4b6ec4efa6124ddd72","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Dashboard","durationMs":159490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3002f790005cb7ba6c34","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> dashboard","durationMs":46011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3278ea25b8daecaafd8c","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> dashboardDataModel","durationMs":39279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3352b05fd95f5a0fb235","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> container","durationMs":39215,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-33ae36b1fd82757cf284","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> mlModel","durationMs":32386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-34679292daa52dbac8ea","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> container","durationMs":42886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3608f98e2232fd6df0d8","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> mlModel","durationMs":46612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-376d116700017793d718","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> table","durationMs":40980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3f62ca7c8be0ab85c351","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> container","durationMs":29651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3fe7b58036a4a2125b1d","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Topic","durationMs":182358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-40413374e8b581e88eac","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> dashboard","durationMs":35801,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-48e22825f7eae0f3f29e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> container","durationMs":41307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-49a209210dc5932f5be4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify opening config modal","durationMs":6266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-4bbf4f6c6dd680998645","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> table","durationMs":29037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-4c982c2809b69bbd1a2e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> searchIndex","durationMs":29660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-4fe8582f7af9544ed9ec","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> dashboardDataModel","durationMs":36023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5295edf4c7e15940f709","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> topic","durationMs":30704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5a8d6ed8c112615ed27e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> dashboardDataModel","durationMs":36474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5ae6ed5a7ee2578ac818","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> apiEndpoint","durationMs":29507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5e542cc97152d8d0705f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> dashboardDataModel","durationMs":34947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6241640d58a39cee5537","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> searchIndex","durationMs":38851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6455912558e4fffeac0e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> container","durationMs":34071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-69c142e64207aaa0a94f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> table","durationMs":32332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-69c9ae55c31c1431989e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify column layer is applied on entering edit mode","durationMs":11847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6de016ff06d3e247fd60","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Table","durationMs":194803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6f9687cfb5ff37d4c970","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> topic","durationMs":29748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-71053c4836b2f2c2bab7","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> topic","durationMs":37590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-74f9f044f9d408f8b511","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Data Model","durationMs":160912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-75b8c3ece17cc1e26d1b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> topic","durationMs":29720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-77f07e78b114d7e380a6","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> topic","durationMs":42465,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-7818a3c39c2e3d1ab93e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Worksheet","durationMs":135734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-7d446a8e5d1ae09b69ec","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Container","durationMs":186097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-822e290d4cae6826f11b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> dashboardDataModel","durationMs":37038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-84a4f88be0b0883d0548","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> searchIndex","durationMs":30395,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-86837102759c8b88c7ee","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> mlModel","durationMs":32404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-8a4216c454f70b116882","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> apiEndpoint","durationMs":39368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-8fc92b51471bd08b5ee2","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> apiEndpoint","durationMs":39530,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-902d02b5e1addc6fbcc4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> searchIndex","durationMs":31810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-904f3f185881ee29c575","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Pipeline","durationMs":157466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-924a8f8064c2cb3d0f90","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> container","durationMs":41693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-95a4a55f764426dfa3a9","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> table","durationMs":24579,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-9607caba24e30eadfc51","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> topic","durationMs":41878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-9751a8c99a2653f2aa30","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Search Index","durationMs":188794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-9b4c4e7691752df4be4a","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> dashboard","durationMs":40563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-a026fb430f338403d586","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> table","durationMs":42413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-a81da11d3e68f71662af","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> table","durationMs":43102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-a93a5af92da1405c4d6b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> dashboardDataModel","durationMs":35732,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-b1bf9ca4eb8f2934bcf2","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify there is no traced nodes and columns on exiting edit mode","durationMs":9939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-b236ad548d05490edec9","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> dashboardDataModel","durationMs":41170,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-b8b8c397dd2d10aef2ed","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> dashboard","durationMs":31942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-bf398b163b9ef3139ff4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> container","durationMs":38576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-bf4451a64295a0504826","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Directory","durationMs":133745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c0636255e8b026bb90ee","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> mlModel","durationMs":40852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c3a968d05e03db815c90","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> container","durationMs":38308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c711e248c5afd84bbb51","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> dashboardDataModel","durationMs":38970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c7287b311547d884a060","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> dashboard","durationMs":39421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c7e215f258b4cd2440ff","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> mlModel","durationMs":39678,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c7e39beb095c4acf268f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> apiEndpoint","durationMs":39386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ccd10903aa517591cbeb","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> dashboard","durationMs":38233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-cd31152efe795b3feee3","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> mlModel","durationMs":49476,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-d161a00652e6b794a397","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> apiEndpoint","durationMs":30775,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-d4f051fa41ede4629590","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> topic","durationMs":36736,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-d6dd53d462492cf5c9fd","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> table","durationMs":33620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-dace76fe5d6fd2759124","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> dashboard","durationMs":36947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-e64fffa15e978be71af6","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> mlModel","durationMs":34123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ea05741da3a8f6c58340","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> topic","durationMs":69158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-efddc2fb2b825c20769e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> searchIndex","durationMs":40448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-f170cfec3b7f57bec7f5","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> searchIndex","durationMs":29728,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-f98474a8fa60fbf4ca6a","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Stored Procedure","durationMs":182974,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-f996fdec580d71b0adef","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> searchIndex","durationMs":33017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-fecafeaa4ce3edd1b3c4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify updating depth configuration","durationMs":6608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ff9ebdfc07b8ba7d3850","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Metric","durationMs":181289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ffb10f915aca070503ee","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Api Endpoint","durationMs":128956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"265968562dab11101b36-37daa773ced9fd7bf0ec","project":"Reindex","file":"Features/DataQuality/TestCaseStatusAfterReindex.spec.ts","title":"Test case status survives a full entity reindex","durationMs":2212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"26611e95fed0ca4ab3e1-78c7a95661587119e576","project":"chromium","file":"Features/ExploreQueryBar.spec.ts","title":"query bar is persistent and shows the browse placeholder when empty","durationMs":5895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"26611e95fed0ca4ab3e1-b1aa54afdc73b54d2452","project":"chromium","file":"Features/ExploreQueryBar.spec.ts","title":"selecting an asset type grays out incompatible tree categories","durationMs":9011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"26611e95fed0ca4ab3e1-e2061d62ce11ee960ccb","project":"chromium","file":"Features/ExploreQueryBar.spec.ts","title":"filter survives a tree click and both stack as removable chips","durationMs":17148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"27048049e118f657f450-24951d56e8cd5d4b8308","project":"DomainIsolation","file":"Features/DomainIsolation/DomainSearchIsolation.spec.ts","title":"userA finds tenantA and domainless tables but not tenantB","durationMs":4029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"27048049e118f657f450-ad87b762a7e4e02c372b","project":"DomainIsolation","file":"Features/DomainIsolation/DomainSearchIsolation.spec.ts","title":"admin finds tables from both tenants","durationMs":3909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"27048049e118f657f450-c663e9f8f53d1aa53eba","project":"DomainIsolation","file":"Features/DomainIsolation/DomainSearchIsolation.spec.ts","title":"userB finds tenantB and domainless tables but not tenantA","durationMs":4002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"281c15345384604a0b9f-5e289bddf5fb4d98b73c","project":"chromium","file":"Pages/TaskFormSettings.spec.ts","title":"creates and updates a task form schema from settings","durationMs":18097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"281c15345384604a0b9f-b6e254ef505635b44b37","project":"chromium","file":"Pages/TaskFormSettings.spec.ts","title":"loads built-in tag suggestion schema in the visual designer","durationMs":11488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2824251716383e5d36e7-2060084764dd7ff53518","project":"chromium","file":"Pages/EditClassification.spec.ts","title":"Edit a user classification from the manage button","durationMs":12725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2824251716383e5d36e7-a00456cc1a9c0dc1352f","project":"chromium","file":"Pages/EditClassification.spec.ts","title":"System classification name is disabled in the edit drawer","durationMs":11585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28a5e8d47dd39a15b905-bff1a99ffc922deb45bc","project":"Basic","file":"Pages/DataMarketplacePermissions.spec.ts","title":"Admin sees add buttons and customize button","durationMs":6197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28a5e8d47dd39a15b905-c1e99a61cbaee27a3291","project":"Basic","file":"Pages/DataMarketplacePermissions.spec.ts","title":"Data consumer does NOT see add buttons","durationMs":8534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28dfe7a0de9ed4705a0e-05876c29593dba931db0","project":"chromium","file":"Features/Glossary/GlossaryVoting.spec.ts","title":"should upvote, downvote, and remove vote on glossary","durationMs":10949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28dfe7a0de9ed4705a0e-99e8ed1d5f5e1d0f3445","project":"chromium","file":"Features/Glossary/GlossaryVoting.spec.ts","title":"should persist vote after page reload","durationMs":48935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28dfe7a0de9ed4705a0e-c3e1cb2ae49780d2d5af","project":"chromium","file":"Features/Glossary/GlossaryVoting.spec.ts","title":"should upvote, downvote, and remove vote on glossary term","durationMs":12578,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-01fa65289fdf7772d19a","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Warning shown when removing asset that is also an output port","durationMs":8264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-069bf1431194facaaaf2","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add single output port","durationMs":10077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-09afee46c87e2c0c5306","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage displays input and output ports","durationMs":8202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-11bbd39747f89aaae32c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Remove last port shows empty state","durationMs":11371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-14e8ceea3982385db337","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Tab displays correct port counts","durationMs":8126,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-174d16335a712ce9a332","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage controls work","durationMs":7532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-1c9f8da89ee745c9cdca","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output port drawer quick filter - behaviour matrix","durationMs":12734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-21e7b442b2a6c36c89bd","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Tab renders with empty state when no ports exist","durationMs":6859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-3a74fad72d2d54a8e468","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"No warning when data product has no output ports","durationMs":7800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-3d3e7086548e88c3849a","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port drawer quick filter - behaviour matrix","durationMs":14589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-479038eb5f8430331d00","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output ports list displays entity cards","durationMs":7600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-568c9f18724fb22d5c00","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage with only output ports","durationMs":7388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-5872d10a29e1a2d4b052","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output port drawer shows info banner about data product assets","durationMs":7743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-599f62d906523734a071","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input ports list pagination","durationMs":8752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-623807bc4cef3c742778","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Remove single output port","durationMs":11251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-63e50a82f75c0228edce","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add different entity types as ports","durationMs":16709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-68ed4c25507e6cadedf7","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Cancel adding port","durationMs":8991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-6b0f41ca117d5b0956bb","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add multiple input ports at once","durationMs":12548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-72f0804125828c6f149c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output port drawer only shows data product assets","durationMs":8858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-733ae742a4ce02354d12","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage displays data product center node","durationMs":7632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-79a2f83588f41a76de4c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage loads on expand","durationMs":7404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-819607994bef4b006508","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage section collapse/expand","durationMs":8080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-8aeba85897967d48c777","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Exit fullscreen with button","durationMs":7649,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-94ae8a7689822d8918e3","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage with only input ports","durationMs":8589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-9b8cedfbb43e6bd23630","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input ports section collapse/expand","durationMs":8134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-a73ed6ab8a060722d7d5","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port drawer shows assets from outside data product","durationMs":9309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b1527c09bef737ec3c9e","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Port action dropdown visible with EditAll permission","durationMs":7299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b3dd87c04273c0020ea9","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Multiple sections can be collapsed independently","durationMs":8401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b4817323e9d164afc510","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add single input port","durationMs":10767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b5c149038668b3f7479f","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port drawer does not show info banner","durationMs":6156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-c7afe91593115b6d8e4c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Toggle fullscreen mode","durationMs":8241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-d220e4be7b73acd6cf5c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"No warning when removing asset that is NOT an output port","durationMs":8454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-d54c0a93937f198e079e","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage section is collapsed by default","durationMs":7957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-d9854a7ec2e3f18edc97","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Bulk delete shows warning listing only assets in output ports","durationMs":7500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-ddaf39a4e6d62adc4e31","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Exit fullscreen with Escape key","durationMs":8377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-ddb0e52df0f2bb65f38b","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output ports section collapse/expand","durationMs":34354,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"29d4e0f3d05ee7ab11db-e631fe73e88dac5cda61","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Cancel port removal","durationMs":8417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-e70c9d333f1aebdbede6","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port button visible, output port button hidden when no assets","durationMs":6834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-e8229144fe684928d7de","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add input port from asset not in data product","durationMs":11276,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-ee7e0ca8a849e28a74bf","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input ports list displays entity cards","durationMs":7113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-f04ff612f7841b2c6dcf","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Fullscreen lineage is interactive","durationMs":7644,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-f0887c631c4e55ebf462","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Removing asset from data product also removes it from output ports","durationMs":9258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-f1ce0182791a75fb7ddd","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Remove single input port","durationMs":8707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-3c1aaf6e29997cd9b74d","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create and approve entity-level description task for Container","durationMs":793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-c3d9df18c364056c0ec0","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create and approve dataModel column description task for Container","durationMs":502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-cf8c6964fbe2bb99e5b4","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create DomainUpdate task for Container","durationMs":910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-e777ffbc4ddc1cfbc9ac","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create TierUpdate task for Container","durationMs":294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-ed5bd6cb911fba4657f4","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create OwnershipUpdate task for Container","durationMs":1188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-3536acf272fc1235a483","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"KPI Widget","durationMs":42209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-39b17deca4f99ff79e80","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Data Products Widget","durationMs":53211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-595be3cd2493a7346dea","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Domains Widget","durationMs":54347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-7e3c2324ccd07d25501a","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Total Data Assets Widget","durationMs":34716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-833499f6d2acc671ad5b","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Activity Feed Widget","durationMs":23654,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-8b144a6bf607ae7fadd9","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Following Assets Widget","durationMs":50317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-a3157898561d06d43bc0","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Data Assets Widget","durationMs":27554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-c0a4574b273caeb431b5","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"My Tasks Widget","durationMs":49462,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-e084e4a872d20a615bbf","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"My Data Widget","durationMs":40753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2c508ade7638f8bcccac-e7c9382107a42d661bbc","project":"chromium","file":"Flow/MetricSearch.spec.ts","title":"searching for a metric with a long multi-word name should not cause clause explosion","durationMs":5453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-2c9621778a08fadbc834","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit Revert Changes restores all rows to NO_CHANGE","durationMs":23115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-4156e62dca8bfb5afec0","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit shows NO_CHANGE badge and OperationSummary on unmodified rows","durationMs":22800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-88e75e085e61e8618e6a","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit shows UPDATE badge and increments summary after editing a cell","durationMs":20237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-9b4ef19a6cb0199bf241","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit search filters rows and clear restores them","durationMs":19394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-b0ff6e9dd7c295b37f2c","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Database service bulk edit search filters rows and clear restores them","durationMs":10099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-b68f427de8c7c4e4c036","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Database service bulk edit shows NO_CHANGE badge and OperationSummary for all rows","durationMs":18529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2e6c9afba330c97d50b5-1e20636ea4cdf2691c93","project":"chromium","file":"Features/Permissions/DataProductPermissions.spec.ts","title":"Data Product deny operations","durationMs":15683,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2e6c9afba330c97d50b5-286bfa812828f22999ee","project":"chromium","file":"Features/Permissions/DataProductPermissions.spec.ts","title":"Data Product expert can edit data product details","durationMs":15388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2e6c9afba330c97d50b5-f81d384daa402484ac75","project":"chromium","file":"Features/Permissions/DataProductPermissions.spec.ts","title":"Data Product allow operations","durationMs":15844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2f3ad51ddbdcab4a2a2b-0084dea86addabfd83fa","project":"chromium","file":"Features/StoredProcedureServiceBulkFetch.spec.ts","title":"Stored procedure carries service via the bulk field path even when service is not requested","durationMs":225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30237b3a00cd0fa9b72a-acd0640f861e051504ef","project":"chromium","file":"Features/ColumnBulkOperationsTagsGlossary.spec.ts","title":"should select a glossary term from the tree dropdown inside the drawer","durationMs":24718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30237b3a00cd0fa9b72a-acde5114dfcdd1395bed","project":"chromium","file":"Features/ColumnBulkOperationsTagsGlossary.spec.ts","title":"should select a classification tag from the dropdown inside the drawer","durationMs":26755,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30263b4dc5f93c4f7d25-1d50e07d9894b470896a","project":"chromium","file":"Features/SampleDataDomainDataProduct.spec.ts","title":"Verify TestDataProduct shows correct details and domain association","durationMs":6311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30263b4dc5f93c4f7d25-5c8b64d664628e73b5fb","project":"chromium","file":"Features/SampleDataDomainDataProduct.spec.ts","title":"Verify TestDataProduct exists under TestDomain","durationMs":6832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30263b4dc5f93c4f7d25-d7f88ea8c2c406af471f","project":"chromium","file":"Features/SampleDataDomainDataProduct.spec.ts","title":"Verify TestDomain exists from sample data ingestion","durationMs":8012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30fe03f56c8634b423b8-01bd25935cd715188169","project":"chromium","file":"Features/ServiceAgentsPauseResume.spec.ts","title":"should offer pause for an enabled agent and resume in disabled state","durationMs":4634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"310213acbd422d208ae5-167f8d8a1b921415200c","project":"SystemCertificationTags","file":"Features/SystemCertificationTags.spec.ts","title":"should NOT show disabled system certification tag in dropdown","durationMs":7009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"310213acbd422d208ae5-41471524fd79dda135f9","project":"SystemCertificationTags","file":"Features/SystemCertificationTags.spec.ts","title":"should show certifications after re-enabling classification","durationMs":10201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"310213acbd422d208ae5-4a0f943642b77501695f","project":"SystemCertificationTags","file":"Features/SystemCertificationTags.spec.ts","title":"should NOT show any system certification tags when classification is disabled","durationMs":6221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-22b545a43b2d863af043","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"shows how tier and usage signals moved an exact table match","durationMs":5795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-2e816677f2966a225842","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"returns ranking stage matched queries without explain","durationMs":2674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-4f1c38196e1dd547eb09","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"shows configurable ranking stages in table search settings","durationMs":5071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-5a015d2e8f981f75b56f","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks customer and customers identity matches before high-signal description matches","durationMs":3159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-998bd319d41b5fa9c78a","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks customer profile name and column matches before high-signal description matches","durationMs":2676,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-a8021c129685daf99088","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"finds customer profiles fixtures across searchable asset indexes","durationMs":3291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-b3d869d6c65350419260","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"finds provider address texas fixtures across searchable asset indexes","durationMs":3464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-c4074fe750ef0ac6936d","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks clear provider address intent above weak high-signal description matches with stopwords","durationMs":3016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-e859181cb88056deb9a4","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"toggles ranking details in search settings preview","durationMs":5263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-f250e708b05339783d84","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"shows readable ranking details for exact table matches","durationMs":6792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-f74d3a290f5428946864","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks name and structural table matches before tier and usage description matches","durationMs":3326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3181935147491aeb55f0-6a8fd0caa84eae7db16f","project":"Ingestion","file":"Features/FailedTestCaseSampleData.spec.ts","title":"FailedTestCaseSampleData","durationMs":6626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3181935147491aeb55f0-96858048143c07e8fbee","project":"Ingestion","file":"Features/FailedTestCaseSampleData.spec.ts","title":"gates the sample fetch on failed status","durationMs":4979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"31a87c9b2485f1aec7b5-6e697bb7c08c009f3229","project":"Reindex","file":"Features/SearchSeparation/GlossaryRenamePrefixCascade.spec.ts","title":"glossary-term prefix rename keeps linked asset glossary tag consistent","durationMs":1517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-3cef86380e36f0a03159","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Dimension card click should redirect to test cases with applied filters","durationMs":76055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-3e3ac21dbb78b79b542a","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Tier filter sends tier.tagFQN field in ES query (not tags.tagFQN)","durationMs":7423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-448cbb52313be9ec70b3","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Dashboard batches all report aggregations into one request (no N+1)","durationMs":6483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-4497b8a31a310cc90f24","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Tag filter sends tags.tagFQN field in ES query","durationMs":8122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-52bdc43c7c7c66f92d3e","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Entity Health pie chart segment click redirects to Test Cases with correct status","durationMs":9520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-67e3603da89d1d13dddf","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"DataQualityDashboardTab","durationMs":29168,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-7b1536150d3100c7a16b","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Test Cases list filter — Data Product","durationMs":9833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-8b76300bfab3a0c4b5ab","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Data Assets Coverage pie chart segment click redirects to Test Suites and Explore","durationMs":13561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-9b9e4b3fa500f737bb52","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Tier and Tag filters produce independent ES filter clauses","durationMs":10123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-d086e0bed7cc7831c38b","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Test Case Result pie chart segment click redirects to Test Cases with correct status","durationMs":17744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-d7eb33e1ed4ca47318bd","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Reopen resolved incident in place from the Test Case page","durationMs":10649,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-15ab7c92e6cc4e9e698e","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"Persona AI Context — Rule CRUD: empty state → create → edit → delete","durationMs":12449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-1600d0c7e7e9f50cddc7","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"knowledge entity type forces Fully rendered on and disables it","durationMs":9615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-9c3f02d123ada83d2aeb","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"changing entity type clears an incomplete filter and unblocks save","durationMs":10912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-e0fd56c870d3159d545e","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"incomplete condition (no field selected) blocks save with an error message","durationMs":10876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-e183791f48da280d4ed6","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"max assets input clamps values above 1000 to 1000 on blur","durationMs":10663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-ee9d29fa394f102ef3d7","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"fully-completed Description Contains condition allows save — regression #31564","durationMs":11812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-f48f2b0c4ab37b0281ce","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"duplicate rule name is rejected with a validation error","durationMs":11508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-fc51d001d91cc85c0f14","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"Always in context and Fully rendered toggles are visible and interactable","durationMs":10011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-11614026b8dde22a8254","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Search Data Products","durationMs":6185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-1458cccf2156100ad999","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Create data product with tags using TagSuggestion","durationMs":10106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-6fa7bf28459032ee3dc8","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Pagination","durationMs":8942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-b46995b607c673d5399f","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Empty State - No Data Products","durationMs":6088,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-b61a7bbd7a47b1fd89c2","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Data Product — Data Observability tab","durationMs":9102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-bed8c16cc4258729a678","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Create Data Product and Manage Assets","durationMs":17059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-ca3fcd97cc2fd4b90fce","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Data Product List Page - Initial Load","durationMs":6372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-d475230b6e62375a3ff9","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Data Product - Follow/Unfollow","durationMs":7854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-e497da6ffe895e87458b","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"View Toggle - Table and Card Views","durationMs":6269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"386c5e2a979bf842b774-be875acf813e1ecae98e","project":"chromium","file":"Features/SearchIndexNestedColumns.spec.ts","title":"oversized deeply nested column indexes and an in-limit column name is searchable","durationMs":5463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-1e3f50160ad418e033c4","project":"chromium","file":"Pages/Users.spec.ts","title":"Token generation & revocation for Data Steward","durationMs":10090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-25c1589afdcf05b3f9cc","project":"chromium","file":"Pages/Users.spec.ts","title":"Should switch personas correctly","durationMs":5853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-28a4af5feb386d2eb3bf","project":"chromium","file":"Pages/Users.spec.ts","title":"Update own admin details","durationMs":10484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-40bc5d16474bd567fec7","project":"chromium","file":"Pages/Users.spec.ts","title":"Should add, remove, and navigate to persona pages for Default Persona section","durationMs":20943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-4e844addc2d7deb18855","project":"chromium","file":"Pages/Users.spec.ts","title":"Should display persona dropdown with pagination","durationMs":4760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-55e153f9ef4db1972ec7","project":"chromium","file":"Pages/Users.spec.ts","title":"Permissions for table details page for Data Consumer","durationMs":13599,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-8831dc2085f1fc122b29","project":"chromium","file":"Pages/Users.spec.ts","title":"Should add, remove, and navigate to persona pages for Personas section","durationMs":18631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-90526ec56b570b377292","project":"chromium","file":"Pages/Users.spec.ts","title":"Create and Delete user","durationMs":19237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-9290e51e5e0501556ac1","project":"chromium","file":"Pages/Users.spec.ts","title":"Close the profile dropdown after redirecting to user profile page","durationMs":11344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-92ef91e72262b1cb927e","project":"chromium","file":"Pages/Users.spec.ts","title":"Should navigate to user profile from feed card avatar click","durationMs":11602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-998cbbc9b801f03b3159","project":"chromium","file":"Pages/Users.spec.ts","title":"Reset Password for Data Steward","durationMs":13796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-a075ce3908b993c98ad0","project":"chromium","file":"Pages/Users.spec.ts","title":"Should handle default persona change and removal correctly","durationMs":14049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-a67e6de8eaa1bac9ba4c","project":"chromium","file":"Pages/Users.spec.ts","title":"Check permissions for Data Steward","durationMs":16994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-b006556d31479323998d","project":"chromium","file":"Pages/Users.spec.ts","title":"Should display default persona tag correctly","durationMs":4233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-ba6d0e4506a5b495f489","project":"chromium","file":"Pages/Users.spec.ts","title":"User Performance across different entities pages","durationMs":99779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-bb7e1f324e137b23fc91","project":"chromium","file":"Pages/Users.spec.ts","title":"Should handle persona sorting correctly","durationMs":4704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-c477ab434b58b5c1462a","project":"chromium","file":"Pages/Users.spec.ts","title":"User should have only view permission for glossary and tags for Data Consumer","durationMs":11807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-cb98769927a83a764470","project":"chromium","file":"Pages/Users.spec.ts","title":"Admin soft & hard delete and restore user","durationMs":17176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-d3b9e560fd6791c5dbf1","project":"chromium","file":"Pages/Users.spec.ts","title":"Update user details for Data Consumer","durationMs":12154,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-d753e04c92cfcfde4334","project":"chromium","file":"Pages/Users.spec.ts","title":"Admin is searchable by email","durationMs":12304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-dcb103b18bbe8e8861ab","project":"chromium","file":"Pages/Users.spec.ts","title":"Token generation & revocation for Data Consumer","durationMs":11494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-e004aa852f1f5c14efb7","project":"chromium","file":"Pages/Users.spec.ts","title":"Reset Password for Data Consumer","durationMs":20503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-e28e9e6eefdde1da98c0","project":"chromium","file":"Pages/Users.spec.ts","title":"Update user details for Data Steward","durationMs":8806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-e61829517b764558d9be","project":"chromium","file":"Pages/Users.spec.ts","title":"Update token expiration for Data Steward","durationMs":14784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-edc0496c9c81d3ed5e9b","project":"chromium","file":"Pages/Users.spec.ts","title":"Should revert to default persona after page refresh when non-default is selected","durationMs":8061,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-f34104f9785f64f73e81","project":"chromium","file":"Pages/Users.spec.ts","title":"Operations for settings page for Data Steward","durationMs":14485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-f3a2c3c86e3d09c3dd16","project":"chromium","file":"Pages/Users.spec.ts","title":"Operations for settings page for Data Consumer","durationMs":18394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-f64b8f345910b62363a5","project":"chromium","file":"Pages/Users.spec.ts","title":"Update token expiration for Data Consumer","durationMs":18876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-faece1be3db817778a7a","project":"chromium","file":"Pages/Users.spec.ts","title":"Admin soft & hard delete and restore user from profile page","durationMs":16537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-4739ff2084f3c8e98727","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should not allow dragging term to itself","durationMs":11041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-6737551753852bc1cbf3","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should delete term and remove tag from assets","durationMs":29177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-771c51350f220ab003ef","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should delete glossary and remove tags from assets","durationMs":28119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-e9b4d20d3effa0991571","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should update child FQN when parent is renamed","durationMs":18372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-f046ff3d00fbffbac1c2","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should delete parent term and remove both parent and child tags from assets","durationMs":40829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39f85eca53b00497835e-5795cfec5f514c0dff0a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":26805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39f85eca53b00497835e-b9d0e082fb7768ae4703","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":26757,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-05d0755a10ff7ca86a72","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Search suggestions should be filtered by selected domain","durationMs":18141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-106885a3b01e4c2164f2","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain assets tab should NOT show assets from other domains","durationMs":15389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-107b97cfdd17a1b2e998","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain Data Products tab should NOT show data products from other domains","durationMs":13104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-2df699eabe74a18aae7b","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain filter should use exact match and prefix with dot to prevent false positives","durationMs":23795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-457e576ead0d5e94d5f8","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Subdomain assets should be visible when parent domain is selected","durationMs":21609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-4cecbd70fae32cde1afd","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Quick filters should persist when domain filter is applied and cleared","durationMs":58016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-4f11dba00d75a16f9ce4","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain page assets tab should show only domain assets","durationMs":14099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-57e135a57c2400ac872d","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain filter should persist across page navigation","durationMs":25228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-85fa806fabef9e541f8b","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Assets from selected domain should be visible in explore page","durationMs":19716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-a56e2714819093d7a60f","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain filter should work with different asset types","durationMs":26086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-b501db7d91aa446ad715","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Multi-nested domain hierarchy: filters should scope correctly at every level","durationMs":45488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-cfe1941aeddc2a8aedf3","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"3-level domain hierarchy: SubSubDomain assets visible when SubDomain selected","durationMs":26191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3d714cb874dd7d8d1332-864a1c3f662a3a46b0a2","project":"Ingestion","file":"Pages/HealthCheck.spec.ts","title":"All 5 checks should be successful","durationMs":2519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-1d51ace7c2b9cb0cfb30","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Related Metrics Update","durationMs":19585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-4debf93e2d3cfddfb567","project":"Basic","file":"Flow/Metric.spec.ts","title":"verify metric expression update","durationMs":16817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-50df1fa23ff9349409a6","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Metric Type Update","durationMs":15283,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-7fda60583e5879af3268","project":"Basic","file":"Flow/Metric.spec.ts","title":"Dimensions and measures render and description is editable","durationMs":16676,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-9acc6f2fc61d63d42017","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Granularity Update","durationMs":16162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-ceb78708ef9d141055da","project":"Basic","file":"Flow/Metric.spec.ts","title":"Metric creation flow should work","durationMs":20081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-d1d3605e00316bbde469","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Unit of Measurement Update","durationMs":14708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-0bd2eb1e92ac9425b8dd","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Configure column search field settings","durationMs":11601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-19fb7ea74d0da3fa8c0a","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Preview config reflects reverted n-gram weight after save","durationMs":9235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-1f6c82edb0d025fa4d35","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Restore default search settings","durationMs":7459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-2e3d05e6e1e746b6c156","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Latest preview config wins when a superseded request resolves late","durationMs":10202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-3ed9d0f3e867e19c934c","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Preview config updates when restore defaults returns empty search fields","durationMs":9870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-3f1486bc755826887709","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Update entity search settings","durationMs":11799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-56543540342adb9b3b9e","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Search preview for searchable table","durationMs":8232,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-c8de79795df8ae9d2141","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Update global search settings","durationMs":10394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-cf112303dbb369632c4e","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Reset global search settings to default via confirmation modal","durationMs":7647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-dc51be90f6049672dc25","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Search preview displays column results correctly","durationMs":9906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"40e9622bfe15bcff9ad8-e351a58660693f8ee3e3","project":"chromium","file":"VersionPages/ClassificationVersionPage.spec.ts","title":"Classification version page","durationMs":9945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4101399d238fe61337fd-26aaa7b16fc4e9c43441","project":"chromium","file":"Features/Announcements/AnnouncementEntity.spec.ts","title":"creates an announcement on a domain","durationMs":19934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4101399d238fe61337fd-3ca48bb1ea1b722e1c1b","project":"chromium","file":"Features/Announcements/AnnouncementEntity.spec.ts","title":"edits an existing announcement on a domain","durationMs":11778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4101399d238fe61337fd-e35c5e2370a108a1519a","project":"chromium","file":"Features/Announcements/AnnouncementEntity.spec.ts","title":"deletes an existing announcement on a domain","durationMs":14228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-293d2abba1bbe1172a4d","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Data Model with display name filter","durationMs":24916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-2a3509194f4730d8cba7","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Dashboards with display name filter","durationMs":22486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-2b2c7b49221082fedabe","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Data Products with display name filter","durationMs":26412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-341c54345e6b70793b52","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Stored Procedures with display name filter","durationMs":20781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-35ecd7a4557f829ec686","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Containers with display name filter","durationMs":25406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-369032808baca9262db1","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Search Indexes with display name filter","durationMs":23790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-399c803a6b55bfebb25d","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Placeholder validation - widget not visible without configuration","durationMs":13524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-433345184533998b95ef","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Database Schemas with display name filter","durationMs":27108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-443dbf0db976c77a9310","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Charts with display name filter","durationMs":24789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-445bc96e17011a12c613","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Pipelines with display name filter","durationMs":25988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-49430d25ae8bdad31291","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Topics with display name filter","durationMs":25362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-4a8e2d73b07a9622bd37","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Tables with display name filter","durationMs":21159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-522b865a043f08183f74","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test API Endpoints with display name filter","durationMs":25564,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-56d6106d21f5cbe8f52e","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Complex nested groups","durationMs":28980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-5dd48016c14d23fccc18","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Multiple entity types with OR conditions","durationMs":26575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-70222d8e09ba6b43fbde","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Metrics with display name filter","durationMs":25180,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-8f9c1279b9e0ba86b5ad","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Knowledge Pages with display name filter","durationMs":5345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-9bcab5a6deac24218c64","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test API Collections with display name filter","durationMs":24066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-a06a0a8ac5a0165a48c8","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Multiple entity types with AND conditions","durationMs":26815,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-b1e897419449d04dadc7","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Databases with display name filter","durationMs":23848,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-b61c4dd6c6c72671c332","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test ML Model with display name filter","durationMs":24912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-b6bdaacf16de33bb5986","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Glossary Terms with display name filter","durationMs":25150,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-ed2ab173d7a73750195c","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Entity type \"ALL\" with basic filter","durationMs":15897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-0a6a0c0a89079822be9b","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: chart","durationMs":6145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-1826851f56f2f64a88af","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: table","durationMs":12338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-197e96b23c8dfd4534d8","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: dashboard","durationMs":10970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-1a3701d0ef11c45d2d86","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for pipelineService in platform lineage","durationMs":8720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-1f9fed7ccd1a32e46faa","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for mlmodelService in platform lineage","durationMs":8741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-2d3e40c9d820f5709c19","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: apiEndpoint","durationMs":6397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-2dfc818f81d83de6fdaa","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for messagingService in platform lineage","durationMs":8115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-34bdec5cd3987c0b1474","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for storageService in platform lineage","durationMs":8874,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-5812ef9c06312f638121","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: searchIndex","durationMs":8137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-68545723ed07a1581857","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: topic","durationMs":10809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-76cc687e194d0300f524","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: container","durationMs":8188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-770dfa5de4648db0785f","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: mlmodel","durationMs":8601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-77f956cbb3cdbb432c07","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: metric","durationMs":6242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-da57ff8ea302cc48d77a","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for dashboardService in platform lineage","durationMs":8319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-ea0b3841423e11276a4c","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for databaseService in platform lineage","durationMs":8656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-ecfd33b33b08fec09293","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: pipeline","durationMs":11818,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-f8d8b2894982189c8fdb","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for apiService in platform lineage","durationMs":8245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-039b9d9949c4ae9f9ca1","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Add Table Test Case","durationMs":10692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-727c14a4b085f6d7d08e","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Non-owner user should not able to add test case","durationMs":10742,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-970712d494efa076b03d","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Add multiple test case from table details page and validate pipeline","durationMs":12444,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-9b9fb01ad7fade5e355b","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Add Column Test Case","durationMs":12583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-1d6fa09a9a2596f90ef9","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify No owner and description redirection to explore page","durationMs":6058,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-254524b7d3aaa13e3040","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify metrics in chart API response","durationMs":3189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-3761ae2928ffed19f52d","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Update KPI","durationMs":4093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-56301182f27c3a7cc07c","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verifying Data assets tab","durationMs":4802,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-5d09da8479693162a3cf","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify KPI widget in Landing page","durationMs":4669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-5f88ed46d6737a9bc324","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Create description and owner KPI","durationMs":6741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-82610a9ae35a0e1b158d","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verifying App analytics tab","durationMs":4420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-869f610ab3df9908aa44","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify metrics appear in description chart","durationMs":3256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-944e8c55fd3b896053aa","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verifying KPI tab","durationMs":4442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-9b38808389a222082626","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Delete Kpi","durationMs":4450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-9f5733c4dfa61fe13e8f","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"switches between Graph and Tree view surfaces","durationMs":2047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-ac147fa6311f758e140a","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"searches the Model graph and clears the query","durationMs":2034,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-bfa7a1e932c6531f0d8f","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"opens with the View, Graph, and Model surfaces selected","durationMs":2402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-d3781b6e6f0194b71607","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"scopes the Studio graph and stats to a glossary","durationMs":2240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-dc8b76bc66b6e8259ad7","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"covers Edit Graph authoring and the Model workbench","durationMs":2672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-e2a05d4ab84737443ccb","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"switches between Model and Data layers","durationMs":2631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-f9d00c1ff5fd124e8d68","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"renders every relation type between the same concepts","durationMs":2296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45a520c451ca353b2bea-4f5b3eea701877cc38c8","project":"chromium","file":"Features/DataQuality/IncidentManagerAfterSoftDelete.spec.ts","title":"Incident Manager renders without Jackson error after a test case is soft-deleted","durationMs":10406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45c88a6f0c34dbb0e7c7-1d2e961d2b1aba19000b","project":"chromium","file":"Features/DataQuality/BundleSuiteBulkOperations.spec.ts","title":"Create new Bundle Suite with bulk selected test cases","durationMs":11231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45c88a6f0c34dbb0e7c7-9f20c56231a934527813","project":"chromium","file":"Features/DataQuality/BundleSuiteBulkOperations.spec.ts","title":"Add test case to existing Bundle Suite","durationMs":10520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45c88a6f0c34dbb0e7c7-afb2d8d44d708f76b025","project":"chromium","file":"Features/DataQuality/BundleSuiteBulkOperations.spec.ts","title":"Bulk selection operations","durationMs":9009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45e1ab4b06aa23f33aff-f2407ea680c31e534c87","project":"chromium","file":"Pages/PipelineExecution.spec.ts","title":"Execution tab should display start time, end time, and duration columns","durationMs":6536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-68ed63a7d77a329ff399","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should show enabled certification tag in dropdown","durationMs":11738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-a0fa29193e91484a6ef1","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should show certification after re-enabling disabled tag","durationMs":17328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-b024f565212d80a3e351","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should NOT show disabled certification tag in dropdown","durationMs":12461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-de28387173f13d94b5ab","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should handle multiple disabled tags correctly","durationMs":12290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-0570db7f4661ea4e68b4","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display domain and owner of deleted asset in suggestions when showDeleted is off","durationMs":8561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-325ce92dfd704c84764a","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display deleted assets when showDeleted is checked but deleted is false in queryFilter","durationMs":8353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-36286bd8f41799e49212","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display domain and owner of deleted asset in suggestions when showDeleted is on","durationMs":11208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-6605f6bf34495eb64f57","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display soft deleted assets in search suggestions","durationMs":17892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-66fc48bbab5da83e551a","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display deleted assets when showDeleted is not checked but deleted is false in queryFilter","durationMs":8487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-960a4db0dbad3161c418","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display deleted assets when showDeleted is not checked and deleted is not present in queryFilter","durationMs":8158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-a17f0c9007400530095f","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display deleted assets when showDeleted is not checked but deleted is true in queryFilter","durationMs":8893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-d9a2f9139db34ab1f5c7","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display deleted assets when showDeleted is checked and deleted is not present in queryFilter","durationMs":9374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-f24680ac9fa5499518e4","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display deleted assets when showDeleted is checked and deleted is true in queryFilter","durationMs":9113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-0ae3eee235ec5b54090e","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should display correct tabs for table entity in team assets context","durationMs":7656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-1887262312ad0f4235d2","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should display overview tab content in team assets context","durationMs":7776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-3e9e117558b4023ad650","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should display entity name link in panel header in team assets context","durationMs":7886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-4839ec1ef558a4b2c1e1","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit domain from team assets context","durationMs":7814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-5994beef742f7e20b2e6","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should open right panel when clicking asset in team assets tab","durationMs":8274,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-9f9ccb162be898d5c7ce","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit description from team assets context","durationMs":7891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-b2b79442ca34f8eb583c","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit owners from team assets context","durationMs":10001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-e637e0262a842d70ad43","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit tags from team assets context","durationMs":9437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-eaaf971263597a587c9c","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit glossary terms from team assets context","durationMs":8192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-fe9c6f16ecf7bfb38e71","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should assign tier from team assets context","durationMs":8846,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4962513e4ede9efbc6bc-fe90046fdeee5e13ecdf","project":"Ingestion","file":"Features/TestSuitePipelineRedeploy.spec.ts","title":"Re-deploy all test-suite ingestion pipelines","durationMs":3393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-06daeb511ef00f84fd29","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service deny common operations permissions","durationMs":10716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-0c4645d7bb089c1e321f","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service allow entity-specific permission operations","durationMs":11813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-14321144181f9ce47f79","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Api Service allow common operations permissions","durationMs":10987,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-17cd90767af0966bd36c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Pipeline Service deny common operations permissions","durationMs":10448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-18ede5fe24ff674006aa","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":9597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-2e5ac8793860549aeacb","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":7872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-343573554ec0d8268d70","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":11203,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-3484dd5baeedfabcdc0d","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":11276,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-35a725698998eb2a47f8","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-38f5f03eb5cf5ae7f033","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":7338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-395e69814743ba2cb187","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":8944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-3a1ec3677e129e362fbc","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":4864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-3ae259c0d22b1e1ce4d8","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Messaging Service allow common operations permissions","durationMs":8401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-432352edf3dca06c2ef7","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":7710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-436873586de451fe96d5","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service allow common operations permissions","durationMs":14605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-4c6ea164e911bb693213","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":8740,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-5f11cfb879248cf34e4c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":5429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-622ca29cccba013730a4","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-7b3743d684cf6e117d91","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":8214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-835d301c730efbe11b34","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":7893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-8ddcec058984ec203d3f","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":7961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-8f1bafe670518bc9e83c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":7391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-91a5d646919b4d9597e3","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":9668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-93d0ad051bf724091eae","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":4873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-a475e3ade77b9e387765","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-ae6752ff147b57846fac","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service allow entity-specific permission operations","durationMs":14301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-afc719e0143260d4e040","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Storage Service allow common operations permissions","durationMs":10063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-b77edf9e143ef601fbf9","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-bcc6de800ae0018c8e35","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":9941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-c3aca2c5c8c2d82180af","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":7675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-c552350b1e2fa95be986","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service allow common operations permissions","durationMs":10218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-c7c8619b266099fc4f70","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":9123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-cdae34958cb93081829a","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"SearchIndex Service allow common operations permissions","durationMs":12341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-d59b19f223a8f2cc1bbb","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":7981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-dd662649178d493876e0","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Storage Service deny common operations permissions","durationMs":9870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-ef980385b808a5c01753","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Api Service deny common operations permissions","durationMs":11864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-f03031217bd696b25733","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Mlmodel Service allow common operations permissions","durationMs":13297,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-f14d138df6e533dcf29d","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Mlmodel Service deny common operations permissions","durationMs":13689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-f4ee16bcc2057c7cbe8f","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"SearchIndex Service deny common operations permissions","durationMs":9936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fb8dab4d2fd36f28599c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service deny common operations permissions","durationMs":14707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fc44283d14ba6c42806c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service deny entity-specific permission operations","durationMs":10244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fc52cf1b230c7de377b5","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Pipeline Service allow common operations permissions","durationMs":11841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fee0d4a9f268927eb49b","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service deny entity-specific permission operations","durationMs":13542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-ff25baa5e6705fd87e3c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Messaging Service deny common operations permissions","durationMs":6784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-1bb1a00f45a51a478c52","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should navigate to new page when \"Leave\" is clicked","durationMs":22037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-61dac66ba80ac816590f","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should show navigation blocker modal when trying to navigate away with unsaved changes","durationMs":18431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-91f203d529a815190d96","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should not show navigation blocker after saving changes","durationMs":21220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-9d1b73de8b80246d8cf7","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should confirm navigation when \"Save changes\" is clicked","durationMs":21056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-e22c3867f6fc02b097af","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should stay on current page and keep changes when X button is clicked","durationMs":21653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-02496396ede353f7fb35","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"Add tests CTA navigates to the Profiler tab","durationMs":8017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-0fb42a3e78e29d28e22d","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"replaces the setup CTAs with status badges once tests are configured","durationMs":9888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-983cb693886d03b0dbc8","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"Enable observability CTA navigates to the Profiler tab","durationMs":9926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-990261b030bde9be3d4c","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"renders the widget with all four category rows","durationMs":9680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-d9f11a53361475875ec7","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"shows setup CTAs for unconfigured categories","durationMs":8619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-da9aa25e75339891381d","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"Create contract CTA navigates to the Contract tab","durationMs":10474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-0810169ebfef6450dab7","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"STATIC config sends all three static-only fields when set","durationMs":5350,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-3dd9676e86c529445185","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"STATIC config sends profileSample and no DYNAMIC-only keys","durationMs":4999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-5b5f30c9f86f701498c6","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"switching STATIC → DYNAMIC does not leak static-only fields","durationMs":5835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-c227bb3d66ab294ce3b3","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"DYNAMIC threshold remove drops only the selected row","durationMs":5521,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-ce6cb46c9ee7e6dd2479","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"DYNAMIC with smart sampling ON sends only DYNAMIC keys","durationMs":5514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-cf4cca44f019913b314a","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"switching DYNAMIC → STATIC does not leak smartSampling or thresholds","durationMs":5376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-f02c36f33396d9719410","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"DYNAMIC with smart sampling OFF and thresholds sends thresholds array","durationMs":5459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-0acd98f891080c27eb0d","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Custom SQL Query","durationMs":23001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-19b221f23b1996aea714","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column Count To Be Between","durationMs":14840,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-45298dd3dedeb1025238","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Row Count To Equal","durationMs":16710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-6dffe1d54d6631269ef3","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Row Inserted Count To Be Between","durationMs":20513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-9ab6d3fa51599960986f","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column To Match Set","durationMs":16417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-a38fbe8dce53bede33cf","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column Count To Equal","durationMs":16510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-a586dabea686a2746e3a","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Row Count To Be Between","durationMs":18186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-b6168c587d55ad692c3f","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Difference","durationMs":25342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-efb7d23b30cf3ec7410c","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column Name To Exist","durationMs":16490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-1f7188b7b883e25772b4","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Data Product","durationMs":7384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-27cf91afa49b80c2fff9","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Tag","durationMs":7380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-29cc7b194e31b3fdc811","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Dashboard","durationMs":5651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-2b584b4d9a77cdb55d27","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Data Model","durationMs":5854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-382d14fc9018ce22dc30","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Database Schema","durationMs":7402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-4cc3834b03e310e5e602","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Metric","durationMs":6653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-4dae8060a54ac47cc0a8","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - API Collection","durationMs":5074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-54a64bccafdf003b3b5c","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - All","durationMs":5891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-54ad89a5b97bf479cc59","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - ML Model","durationMs":6612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-6316c64b4f391ed5dd7c","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Database","durationMs":6605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-6559c024bdc4ef8d6595","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Search Index","durationMs":7402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-69a557a324f049438f36","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Directory","durationMs":5933,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-89015f87c94adc34de54","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Table","durationMs":7583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-92dfb0fb33159b9982bf","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Container","durationMs":7122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-960f1bace1eb38b1a42a","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Worksheet","durationMs":8459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-9c37b3959482f071ddae","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - API Endpoint","durationMs":6213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-a8750715d64a09e3c8fc","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Spreadsheet","durationMs":6105,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-cae189412fe5f16c69a7","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - File","durationMs":8243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-cd0c011f0719a41d2d68","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Pipeline","durationMs":6051,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-cf14b19b99f210391fc6","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Stored Procedure","durationMs":6332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-db96c73de1e2ebd5a423","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Topic","durationMs":6264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-dcfea58dc473f62141b7","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Glossary","durationMs":7621,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e89530d9c0b985f2d2e-8764696c70efbfce6d8f","project":"Basic","file":"Pages/Roles.spec.ts","title":"Roles page should work properly","durationMs":19700,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e89530d9c0b985f2d2e-fbf09b1def578f24be64","project":"Basic","file":"Pages/Roles.spec.ts","title":"Delete role action from manage button options","durationMs":8886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-3e47bd48fd77712e1f85","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify columns and edges when a column is hovered","durationMs":9683,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-ad6d8832112259fd0251","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify edges for column level lineage between 2 nodes when filter is toggled","durationMs":8934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-b732968444170866a917","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify column visibility across pagination pages","durationMs":12264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-dfc52176b46c289f580c","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify edges when no column is hovered or selected","durationMs":11031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-fa1589a1509ed48faec5","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify columns and edges when a column is clicked","durationMs":11246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-2fe9c1b4e193b0e8a3c1","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Pipeline via UI","durationMs":10915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-437893114501837400b1","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Dashboard via UI","durationMs":16673,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-69a7106de7c0a6a9eced","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Verify task lifecycle in activity feed","durationMs":13781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-6c54054c4b110926b888","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create tag task for table column via UI","durationMs":10301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-79d67e1c613b05839814","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Table via UI","durationMs":18387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-8605df75810c859fa5df","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create description task for table column via UI","durationMs":10513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-9c3e14eda96c37015d6c","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Pipeline via UI","durationMs":12944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-a6b2c6fca32681720e0d","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Dashboard via UI","durationMs":85578,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"53b3e913ac628cc64131-b14bef78aecc75cf1e4b","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Topic via UI","durationMs":15529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-b3aafe3db491bbb76c3f","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Table via UI","durationMs":12134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-ca8b24a71c63ee90c746","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Topic via UI","durationMs":16135,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-dc5fdbbc55f4323bd01d","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Verify task shows correct metadata","durationMs":12962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53f5e48dc6dd5303275d-f73ee758f1c03b02e338","project":"Basic","file":"Features/MetricCustomUnitFlow.spec.ts","title":"Should create metric and test unit of measurement updates","durationMs":8515,"attempts":1,"retries":0,"outcome":"expected"},{"id":"542738137544ccb7a5b6-ec4052ad168f3715c61c","project":"Basic","file":"Pages/SubDomainPagination.spec.ts","title":"Verify subdomain count and pagination functionality","durationMs":16458,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-20526ba66c2db23ec1b7","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Edit own comment - author can edit","durationMs":208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-3adb3ddf9b6b67100b88","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Admin can delete any comment","durationMs":226,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-494755f4b3475416e2de","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Delete own comment - author can delete","durationMs":246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-5282e3382c460cc2d9f9","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Add comment to a task","durationMs":186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-577db3e820f130af6ca7","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Non-author non-admin cannot delete comment - returns 403","durationMs":7054,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-6f7978153f6acdcda0dc","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"View comments on task in activity feed","durationMs":14342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-80af15ec5a63db7ec1c7","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Add multiple comments to a task","durationMs":240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-861e0f72c5138e44c9dd","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Comment supports markdown formatting","durationMs":130,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-adf9f8b9a52a48f27809","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Comment with @mention syntax","durationMs":194,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-eba5683c6497d7b43096","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Non-author cannot edit comment - returns 403","durationMs":6910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-07bce10ca7c87f76ebc3","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Insights page should trigger collect API","durationMs":5403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-3868472ff94748e79924","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Incident Manager page should trigger collect API","durationMs":5202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-57526628bff2481e11dd","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Explore page should trigger collect API","durationMs":6153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-64c32274d7af4914dbb0","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Tags page should trigger collect API","durationMs":5729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-73b9c5edde2a3debaf93","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Quality page should trigger collect API","durationMs":5114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-a48dd7c323ac0a8ce57a","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Settings page should trigger collect API","durationMs":5817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-ee0a5aeb47d5510b99b5","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Glossary page should trigger collect API","durationMs":5589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-077585f6e4f0a08cffc6","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should create a new learning resource","durationMs":7354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-24ae7d73ea2582e79ad8","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct pageId param when filtering by context","durationMs":4385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-34c89825a071c90c66cd","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct resourceType param when filtering by type","durationMs":3693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-408a941563d59c4b52db","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should validate required fields when creating a resource","durationMs":5404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-4daf0f2ef98790dfdd5d","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should open resource player when clicking on resource card in drawer","durationMs":8366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-6440dc2b2c05f5ff8244","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should clear all filters and reload without filter params","durationMs":4366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-7057ea634ebbed2312bb","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should toggle between table and card views","durationMs":4131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-a5ef027b5906819fe95a","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct status param when filtering by status","durationMs":4265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-b9bfc3ce1ba2ab5785a5","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct category param when filtering by category","durationMs":3691,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-d8c73713be3825c12ab8","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should show correct learning resource in drawer on lineage page","durationMs":7330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-db3917dc961a6c6490d9","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should create resource via UI and verify learning icon appears on target page","durationMs":12299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-f5d75cc00a51851d5306","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should preview a learning resource by clicking on row","durationMs":4977,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-f761108bc52917eb0642","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct search param to API when searching","durationMs":3613,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5609f6479eac3cd9b7a7-683a4b4827384efb9055","project":"chromium","file":"Features/AgentLogStreamHandover.spec.ts","title":"A finished run clears the live state and refetches the log exactly once","durationMs":4710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5609f6479eac3cd9b7a7-8b23b53f970ad335810a","project":"chromium","file":"Features/AgentLogStreamHandover.spec.ts","title":"A run that keeps streaming is never polled, and reconnects from its cursor","durationMs":7428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5609f6479eac3cd9b7a7-d27d4198437bb484a92f","project":"chromium","file":"Features/AgentLogStreamHandover.spec.ts","title":"Scrolling a live log pauses auto-follow and the toolbar toggle resumes it","durationMs":12095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-1d7fa6c7705f360dd57c","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"AI badge should appear on entity description with Suggested source","durationMs":9343,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-4d509e367d791e680fce","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"AI badge should NOT appear for manually-edited descriptions","durationMs":9284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-ad865f0b3a35d329cfae","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"Automated badge should appear on entity description with Automated source","durationMs":6863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-c879ec9ef9cceb2c1db5","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"AI badge should appear on column description with Suggested source","durationMs":12964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-d7e62feac5044c0d61fa","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"Propagated badge should appear on entity description with Propagated source","durationMs":6957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-00d10c1204dcb1503daf","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"uploaded document card shows name, size, updatedBy, updatedAt, and folder","durationMs":8557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-1333813a8cf577276069","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"expanding a folder shows 10 files, view more loads the rest, and show less collapses back","durationMs":8891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-24e040b4f0daf57f8c2b","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"document appears nested in the folder tree after being moved to a folder","durationMs":10201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-269c7beb9556949e695f","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"moving document to folder shows folder on card; re-opening menu shows current folder selected; clicking it again removes document from folder","durationMs":10471,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-2e28f17914a39684acc0","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"retry on a failed file updates the row to complete and keeps the modal open","durationMs":10627,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-2f7b38c26e82cbe867ce","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling the bulk \"Move\" dropdown loads the next page and reveals the page-2 folder","durationMs":13708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-38c6c355899b59d8b7a4","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"documents view container is rendered","durationMs":7618,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-41757222b5c8359eed12","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"copy link button on document list row copies URL with correct document id and opening the link shows the preview panel","durationMs":15271,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-4745dae95484add0ade5","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"create folder appears in sidebar tree and delete folder removes it","durationMs":11041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-485a24ecc4ba1cdad79f","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"delete single document from card menu removes it from the list","durationMs":9900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-4b077df390afe8767316","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"clicking folder in sidebar shows only that folder documents and move menu show the current folder","durationMs":11625,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-62c0897bad0eda516e8d","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"attaching a new file does not close the modal when a pre-existing error file is present","durationMs":10559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-639d91951f33be98d7a6","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling the per-file \"Move to Folder\" submenu loads the next page and reveals the page-2 folder","durationMs":10212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-74c465ee083236782524","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"partial batch failure keeps modal open with failed rows showing try again","durationMs":9940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-77de7e00171675e4d461","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"file upload attaches file and closes modal, then appears in list","durationMs":10280,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8150a4d5518b4bb29ac0","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"clearing document search restores the full list","durationMs":9224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8688b851d9e1c94056d6","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"bulk move moves selected documents to a folder with a single API call and folder name appears on both cards","durationMs":16879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8737cb9413dd7cb2e802","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"searching documents with no match shows empty state","durationMs":8997,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-88817c4218092444a545","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"clicking document row opens preview panel with name, status, size, folder, updatedBy, updatedAt and copy button copies correct link","durationMs":9935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8d88e17dba6bf2ee365f","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"bulk delete 2 documents removes them from the list and both appear in the archive","durationMs":15906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-a00b3e03f359967e5d5d","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"Upload File button opens upload modal with correct title and hint","durationMs":9706,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-a9f5bd79d23a70cae703","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"oversized file appears in list with failed state and Attach button stays disabled","durationMs":12459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-d5758dd9e35122c24e51","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling the sidebar folder tree loads the next page and reveals the page-2 folder","durationMs":9075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-d6fa28cd9dd0a23fe766","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"searching with folder selected scopes results to that folder only","durationMs":9220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-d716db49c6608dbe0e11","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"shows header with Upload File button","durationMs":7043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-e2345c9897597a5db162","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling to the bottom of the list loads the next page of documents","durationMs":11018,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-edb3ac72c05e7f318a35","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"move document to folder via card menu shows folder name on the card","durationMs":9811,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-ef0af5d349390d9be21a","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"searching documents filters the list to matching results","durationMs":8177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-f42e131cca4e98999103","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"duplicate filename in same folder shows retry error; uploading same name to different folder succeeds; delete file and folder from UI","durationMs":16163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-feebbefe7b5c42ddb24e","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"duplicate filename upload fails case-insensitively in the same folder","durationMs":10208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-1a30082a0e8c0134b699","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values Sum To Be Between","durationMs":17747,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-220c8abdae85161f7ef1","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Not Match Regex","durationMs":18181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-2bc0479414d1cfb7e52a","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value StdDev To Be Between","durationMs":16996,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-527690061879323e9f56","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Mean To Be Between","durationMs":16719,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-52a4ac74b376c6248a8b","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values Missing Count To Be Equal","durationMs":16291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-585c361e018618ac3c85","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Min To Be Between","durationMs":17648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-5cf5641d7794e01ed134","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Match Regex","durationMs":17379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-8d0cc261c61869a2e942","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Median To Be Between","durationMs":18468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-941e7252830d062fca15","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be In Set","durationMs":18544,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-a728a614c03861fbe05c","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values Length To Be Between","durationMs":16641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-b8c2ba1a531cf17537f6","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Max To Be Between","durationMs":16358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-b9c4fc654f6df8a64278","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value To Be At Expected Location","durationMs":15728,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-be68a0dcbf4404b7c60d","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Not In Set","durationMs":15852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-d2b4cbf07a2eb74cafaf","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Unique","durationMs":15979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-d44e518bd09b8d8cca9d","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Not Null","durationMs":21275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-f0ad21757191a49ab561","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Between","durationMs":16569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"58209e668526b4118920-9962bcde1da3ae180f23","project":"chromium","file":"Features/TableConstraint.spec.ts","title":"Table Constraint","durationMs":25911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-150f00a8522948ca82c7","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"removing team member should create activity","durationMs":11070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-281ff782d6a9895b5d37","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should be able to resolve team-assigned task","durationMs":11993,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-4218944b90688690d3c8","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should see team-owned entity changes","durationMs":10478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-6a1509d7c1e716eb9550","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should receive notification for team-assigned task","durationMs":11738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-8caa0444f8b3d9f04f71","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"non-team member should NOT see team-assigned task in their tasks","durationMs":12170,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-ae919be6e81338fd2a2a","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team page should show activity feed for team","durationMs":4077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-c97f6ef399e1f3cb9b58","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should see tasks assigned to their team","durationMs":10998,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-d9e43035c5a38c2b7517","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should see team membership changes in activity feed","durationMs":10228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-e2bc93dfdbdc70314acc","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"non-team member should not see team-only activity","durationMs":11419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-ee6cda8cf796aaead244","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"different team member should also see team-assigned task","durationMs":11687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-12d140d9d851ee24f0e1","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Add teams in hierarchy","durationMs":14198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-651d615e2b611721b171","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop on Division team type","durationMs":8505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-821ac29f15154291c014","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should fail when draggable team type is BusinessUnit and droppable team type is Division","durationMs":8160,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-84b55c520eac6337ee73","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop on Department team type","durationMs":9924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-9eebb114627308bfceda","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should fail when drop team type is Group","durationMs":7287,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-c5c76c34a2e5cbd00ce6","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop team on table level","durationMs":8457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-cf4bd8f779f87bb20516","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should fail when droppable team type is Department","durationMs":7707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-e02d0adfda4658ae691c","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop on BusinessUnit team type","durationMs":10015,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-17226c8e4fb8758d4c16","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with only VIEW cannot PATCH incidents","durationMs":10887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-40d5b508af0f1557c186","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TABLE.EDIT_TESTS can see edit icon on incidents (alternative)","durationMs":10506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-5b14a963076563878b00","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"Consumer-like user cannot see edit icon and cannot create/edit incidents","durationMs":11220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-6952ddbbfc1aded68ffe","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view incident CONTENT in UI","durationMs":10915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-86854d0ef42ab99072e7","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TABLE.VIEW_TESTS can view incidents in UI (alternative)","durationMs":10561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-906fb153657cd8c10018","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TEST_CASE.EDIT_ALL can see edit icon on incidents","durationMs":11415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-bdbf4bb4dd50592dc6ab","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with only VIEW cannot see edit icon and cannot POST incidents","durationMs":10373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-e24504ddfad39ded9cfe","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view incidents in UI","durationMs":11393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-8fb80db9e9e824864860","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should show loader then render classification content on initial page load","durationMs":5900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-902997d142078395f0b2","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should render correct content when switching between classifications","durationMs":11606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-bc6bf4188428df4e1363","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should render classification correctly after page reload","durationMs":11856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-d3427f89e0e3492163f4","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should render all classification detail sections after loading","durationMs":10268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a571ecbb30c2877255e-000cc1bf493e11634f32","project":"Ingestion","file":"Pages/LogsViewer.spec.ts","title":"Logs page shows breadcrumb, summary, and log viewer or empty state after opening from bundle suite pipeline tab","durationMs":9062,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-00a1cdb503e15dbb492e","project":"chromium","file":"Pages/Domains.spec.ts","title":"Comprehensive domain rename with ALL relationships preserved","durationMs":37563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-058d4f127752c8b36927","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify duplicate domain creation","durationMs":13638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-08165284efa6f293a92a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Should clear assets from data products after deletion of data product in Domain","durationMs":78533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-13c6520c826c7eca4b68","project":"chromium","file":"Pages/Domains.spec.ts","title":"first-time add (no current domain) commits without showing the warning modal","durationMs":19388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-1810cc2b4c4a408af07f","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify redirect path on data product delete","durationMs":16531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-1edacb9d8c077caa7901","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain","durationMs":26584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-211da11cb816223351be","project":"chromium","file":"Pages/Domains.spec.ts","title":"Domain owner should able to edit description of domain","durationMs":19500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-28fdb3fda9203a613a93","project":"chromium","file":"Pages/Domains.spec.ts","title":"Data Product announcement create, edit & delete","durationMs":34611,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-2bd269f19362ee149752","project":"chromium","file":"Pages/Domains.spec.ts","title":"Should inherit owners and experts from parent domain","durationMs":15321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-2c7f60df9b21b10d852c","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with tags and glossary terms preserves associations","durationMs":17784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-316848d9a8aa099bafae","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain tags and glossary terms","durationMs":38822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-39708973ea128903f12a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain and subdomain asset count accuracy","durationMs":61721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-3a657a5b353f23a52971","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with data products attached at domain and subdomain levels","durationMs":14192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-41ad0369adac81ff6b18","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with assets (tables, topics, dashboards) preserves associations","durationMs":36405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-42fe30db5b099636336b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Subdomain rename does not affect parent domain and updates nested children","durationMs":18697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-468822f47c1bfe7e56ea","project":"chromium","file":"Pages/Domains.spec.ts","title":"Assets tab lists the assigned glossary and its inherited term","durationMs":8468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-4943e305ac2f77dab3e8","project":"chromium","file":"Pages/Domains.spec.ts","title":"AddDomainForm description preserves typed whitespace","durationMs":11435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-4e3971359320b075cbb3","project":"chromium","file":"Pages/Domains.spec.ts","title":"Add-Assets drawer quick filter - behaviour matrix","durationMs":24243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-4ec6b7d25e96a0a0c363","project":"chromium","file":"Pages/Domains.spec.ts","title":"Domain announcement create, edit & delete","durationMs":27637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-54632a239b314fb2b087","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain data products count includes subdomain data products","durationMs":37273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-5ea87aba82de9e69f803","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with deeply nested subdomains (3+ levels) verifies FQN propagation","durationMs":14212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-60ec59c847ceb9594d4a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with subdomains attached verifies subdomain accessibility","durationMs":13851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-78907b1bc71d2fbf4f0a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify data product tags and glossary terms","durationMs":20601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-7aca6831130839a0cec8","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain custom property value persistence","durationMs":20143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-832afab7b2e6da27dcd6","project":"chromium","file":"Pages/Domains.spec.ts","title":"slash, mention, and hashtag popups are usable inside the Add Domain drawer","durationMs":18407,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-867db2298f498ed22771","project":"chromium","file":"Pages/Domains.spec.ts","title":"Follow & Un-follow domain","durationMs":18598,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-877f57fd0b9d6c00c328","project":"chromium","file":"Pages/Domains.spec.ts","title":"User with noDomain() rule cannot access tables without domain","durationMs":15686,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-8a19c401185f31534530","project":"chromium","file":"Pages/Domains.spec.ts","title":"Multiple consecutive domain renames preserve all associations","durationMs":49361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-90441b02005e9e698942","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create domain with tags using TagSuggestion","durationMs":13331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-90d3b0f4f38255032906","project":"chromium","file":"Pages/Domains.spec.ts","title":"cancel on preview modal aborts the move","durationMs":20349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-941ba943b9b6909b181b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create domains and add assets","durationMs":32146,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-a64ddf86b530d1b08c7e","project":"chromium","file":"Pages/Domains.spec.ts","title":"Data consumer can manage domain as owner","durationMs":11038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-a91a7b57d2c8980e04ea","project":"chromium","file":"Pages/Domains.spec.ts","title":"shows preview modal on cross-domain move and commits on Move Anyway","durationMs":21024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-b5b9e238dec299377ac0","project":"chromium","file":"Pages/Domains.spec.ts","title":"Domain Rbac","durationMs":59073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-b9e70b1c81b9ba79fe2b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify Domain entity API calls do not include invalid domains field in glossary term assets","durationMs":15126,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-bde707fc5aac0401750a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create subdomain with tags using TagSuggestion","durationMs":19325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-c38fbe441d42c9627329","project":"chromium","file":"Pages/Domains.spec.ts","title":"preview names affected data products when moving across domains","durationMs":15975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-c9d5f9bbc47b87764df6","project":"chromium","file":"Pages/Domains.spec.ts","title":"Follow/unfollow subdomain and create nested sub domain","durationMs":27330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-d88964156dbad267a3fa","project":"chromium","file":"Pages/Domains.spec.ts","title":"should handle domain after description is deleted","durationMs":8319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-dc27f2d87881ab505c0b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify Domain entity API calls do not include invalid domains field in tag assets","durationMs":14876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-dfc370e7cca8f37456f2","project":"chromium","file":"Pages/Domains.spec.ts","title":"should render the domain tree view with correct details","durationMs":5093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-e39301d5c52576b7bc0c","project":"chromium","file":"Pages/Domains.spec.ts","title":"User with hasDomain() rule can access domain and subdomain assets","durationMs":10373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-e915b74c6eba6a3cb81d","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename to existing domain name shows appropriate error","durationMs":10738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-eba5d9a4be11a73fb40b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with owners and experts preserves assignments","durationMs":13805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-ec0297c4e178bfb838e2","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify clicking All Domains sets active domain to default value","durationMs":21498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-edbb83c1aef23ac5fe9e","project":"chromium","file":"Pages/Domains.spec.ts","title":"should handle data product after description is deleted","durationMs":10339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-f2a49bf85e545308f9cf","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create DataProducts and add remove assets","durationMs":82980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5b560f2a008735eeb753-59998383f71d95e33941","project":"chromium","file":"Features/DataQuality/IncidentManagerAfterOwnerChange.spec.ts","title":"Incident Manager renders after a test case owner change","durationMs":11155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5c28d935b3c657a6e5bc-73a4cae56b3a100775bc","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts","title":"Admin: Complete export-import-validate flow","durationMs":250031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5c28d935b3c657a6e5bc-a936c2f91f4ad9769ad0","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts","title":"EditAll User: Complete export-import-validate flow","durationMs":258400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-10b3bf8dd0d55f85d77d","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Tags","durationMs":10690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-18610c86119ed13f58a1","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Search Index","durationMs":10592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-3aa370ad5eaa21e64275","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"API Collection","durationMs":9560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-4f41b2190e1d1f9d68e2","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Glossary Term","durationMs":9465,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-5675237446380d7955da","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Database","durationMs":10267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-7b5d40e65305dc11c3b4","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Stored Procedure","durationMs":10190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-7da97f8239b2930647ac","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Table","durationMs":11086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-993a003b732f85ca70f1","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Dashboard Data Model","durationMs":11155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-a3aaf964369df56c9bdf","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"API Endpoint","durationMs":11050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-aa4c7687b25f08368410","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Column","durationMs":10968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-aca5963b052c2fbcc208","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"ML Model","durationMs":9402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-adf3ee9562a932f7cfb4","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Topic","durationMs":10684,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-c0d85d22753538870e95","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Database Schema","durationMs":10647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-ca00f14c4cb64a35f244","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Dashboard","durationMs":10155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-cd028f49219fc3decf23","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Pipeline","durationMs":11153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-d9b951c102d713db155e","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Container","durationMs":9881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-dc8ba8fe61a148caacd4","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Metrics","durationMs":9536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-247a852a8f9d96911088","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Sort state should be preserved when searching columns","durationMs":6421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-2d5d89cfca8730ffb2c3","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Clicking Original Order option should sort columns by ordinal position","durationMs":5831,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-3c6d240db259312d28e5","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Clicking Name column header should toggle sort order","durationMs":5592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-70bcb1d6a1cd9df68f81","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Clicking Alphabetical option should sort columns by name","durationMs":6653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-a5dfbdd951385e32b97a","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Sort dropdown should show Alphabetical and Original Order options","durationMs":5298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-c01e49e259252126d74c","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Sort dropdown should be visible on table schema tab","durationMs":4900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-c86bd28c40019f7bf7ee","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Switching sort field should reset sort order to ascending","durationMs":5974,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-0466efa203f90064b580","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary truncates long description and end of text is not visible before expand","durationMs":7000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-197cf17e5b07ddff57de","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Customized Table detail page Description widget shows long description","durationMs":25999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-1d5bdad4fce05f36540c","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Domain long description is scrollable and end of text is visible after scroll","durationMs":9895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-60fae3d5fe2e9ea4edc1","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary long description is visible after expanding","durationMs":7243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-76ee66e52bce790fb914","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Data Product long description is scrollable and end of text is visible after expanding","durationMs":9121,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-9380f0005af196f8f8cc","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Domain description comment-thread button opens the activity feed drawer","durationMs":9132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-bf35b4fa3269cd34eb66","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary Term long description is visible after expanding","durationMs":7449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-c84de7d4c776aa2235ca","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary Term truncates long description and end of text is not visible before expand","durationMs":7159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-c993b188be16c921d381","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Data Product truncates long description and end of text is not visible before expand","durationMs":8488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-2fc13bd486ba204a9b0e","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":68669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-30b6dae7d0a961254f56","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":64619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-4f3a6fb1fb3de6d8217d","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":128413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-92cd730c005813f91465","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":100633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-94c100d67d396805d1b5","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":9679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-9ecb9ce96078b339d264","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":7368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-a044c42b96a086d46495","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":162501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-a3b61ed679be08981a84","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":7010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-acddffdad8f69d48d4ce","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":10268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-b3d6519c76369e63a867","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":7380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-c745b5314f6b89d8d8dc","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":100482,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-f5cf031d5d3d53ec8d50","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":8583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-35843ba93005559bc5b7","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"edit form renders and manifest edits are saved","durationMs":8405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-70976550640ebe56c182","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"manifest editor is full width, clears cleanly and keeps caret stable","durationMs":4413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-8525dc7ae87c5a745a7d","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"confidence field rejects values outside 0-100 and blocks next step","durationMs":4717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-d301fbab1271274948c4","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"sampleDataCount rejects non-positive values and blocks next step","durationMs":4721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-e1ac46b0fa3419663979","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"auto-close keeps the caret between the inserted pair","durationMs":4254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-08f0afc5bbbcfddf5fe8","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should display correct status badge color and icon","durationMs":20481,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-0c5bb45f7891c174950a","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should inherit reviewers from glossary when term is created","durationMs":18623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-26b4e489ecf3c2ec93b8","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should start term as Approved when glossary has no reviewers","durationMs":15643,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-27f2d6ee3aefa050281a","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should view workflow history on term details page","durationMs":11779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-7faac0bc93febd2581b9","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should delete parent term and cascade delete children","durationMs":15132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-bf53bdbb0a31361d92aa","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should change status when non-reviewer edits approved term","durationMs":17111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-c2809e67875b4136fbc3","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should not auto-approve term when glossary has reviewers","durationMs":16794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-c623fe2508894ad9aa77","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"non-reviewer should not see approve/reject buttons","durationMs":28321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-ea2302b8bcba34efbbcb","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"owner should not see approve/reject buttons if not a reviewer","durationMs":26940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-febeba98e63565adc403","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should show workflow history popover on status badge hover","durationMs":12176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-17bb560f186a52556b6e","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently created article appears in the Articles pillar card recent list","durationMs":7494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-35ffe7964f4ff382e358","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"clicking each top summary card redirects to its corresponding list page","durationMs":10373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-591d8e2b0ba501dd7afe","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"Create > Quick Link creates a quick link that appears in the Articles pillar card recent list","durationMs":10484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-7e65fcaf721dd4c7fc90","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently created memory appears in the Memories pillar card recent list","durationMs":7126,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-82c968bc20dd40640260","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"memory with highest usageCount appears at the top of the Most Cited Memories widget","durationMs":7148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-9c9d3267a4439857e600","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"folders widget shows folder with file count and expanding reveals child file","durationMs":7303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-a485be19ead771b720d0","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently viewed article appears in the Recently Viewed widget after visiting it","durationMs":10994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-a7a4ddbacb21212a4925","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently uploaded document appears in the Documents pillar card recent list","durationMs":6873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-b39405d678aebfb3c9d0","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"Upload File button opens the upload modal and uploaded file appears in the recent documents list","durationMs":7842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"629436f87b212b8ba678-b5eccd0197361c9c4f78","project":"Ingestion","file":"Pages/TestSuiteDetailsPage.spec.ts","title":"Add test case modal on Test Suite details page - filters and select","durationMs":14197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6371c6e2d907c92358e4-a6573e241600590ee3d5","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":27447,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6371c6e2d907c92358e4-c116df633ffcf099a993","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":28825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-4067d73d89ad7e8a9d7b","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":36008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-4c0a127433aa7dd6e72b","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":15853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-6cc746feeae7fcde0753","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":16541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-8ed5ae9e4457d894e9a1","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":23568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-c171fd09b78290a7ee3d","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":28352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-c48e9e0adb431a610c55","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":28760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-d459106bf07dc4b72448","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":28718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-ddd05ab1ec93995dc321","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":26526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-f1417577e5c493c9ed9d","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":27492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-fc8cffe6fccb985e0363","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":17942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-fe8f25b8cb74ea0c9c11","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":27569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-01215054e737e2c593fb","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Create team with domain and verify visibility of inherited domain in user profile after team removal","durationMs":13716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-16b7d856c97d302db432","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Non admin user should be able to edit display name and description on own profile","durationMs":8950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-2d41661b7fb29796cb11","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Admin user can edit teams from the user profile","durationMs":9843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-761b0901e1a38838b81d","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"User can search for a domain","durationMs":12002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-82f49cf6ec1e1428430f","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"My Data Tab - AssetsTabs search functionality","durationMs":22032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-8d5d1460501ed67f3bfb","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Admin user can assign and remove domain from a user","durationMs":15418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-a1a41e105bc8e1f05019","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Admin user can get all the roles hierarchy and edit roles","durationMs":14411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-dd0919f68d1d3f97ba68","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Subdomain is visible when expanding parent domain in tree","durationMs":12868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-e327d2178a45b46d6a94","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Non admin user should not be able to edit the persona or roles","durationMs":10305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-270895da7594f80804d0","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"Tier1 OR Tier2 union shows assets with either tier across asset types","durationMs":14439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-2f5e7621dfc5950e7dbe","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"removing one tier chip narrows the union to the remaining tier","durationMs":19402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-77d802807f3b1de7d1e5","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"domain filter spans asset types and ANDs with an asset-type filter","durationMs":22128,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-a5ea7273e17fe2c0b22c","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"certification union shows assets certified with either level","durationMs":34658,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-d88a3c506999e00ab9af","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"glossary term filter spans asset types and ANDs with tier","durationMs":28418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-f4233e4ff83a89dfc78b","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"tier and tag filters AND across fields","durationMs":15946,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-f629a0aa9880099c7b25","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"asset-type union composes with tier union (AND across, OR within)","durationMs":26908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-00c1b828793ac9ccad42","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":15858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-010a74dfd5f225fdd9ac","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16424,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-02cdcc35da1446d26426","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":28879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-0513f79e653d347c7603","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":15440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-05568392368ae2bd8841","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":12615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-076047cd3a3cd9186780","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":18972,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-0b18fe048332aed087f0","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-0e4eed2d6ca3374d26a7","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-106e894b7b0f76f0a360","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":14441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-13d9772ce8471d90d2fb","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16525,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-19e7e34913aaccebcebd","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-1a342db08b7329cc2010","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":16511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-1a8e244a95c0d725bc93","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-1c6d2e1ac16152f480f0","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":15416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-2172832393bae4110f5a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":12614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-21e015047436a930e5a7","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":15798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-241282b34358796f6850","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15395,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-265c0bedcb12d4ef691f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19270,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-27dfe3b37ded28891ed3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-27e953a961e46ba2243b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":17302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-2881886f24b7cb9bedb2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-28a34def86e53882b978","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-28f65a1e4a970d0ce460","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":11408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-2ebf49154da3380d587f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":16094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-31492e12c2051bbec6b3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-319fb1586353f9bf979c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":12584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-324024e123c76341d586","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":18166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3313a1c7730a0f079c48","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3336421788437383e2cc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":15113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-34f290ac8ac48a8f3681","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-39b25a08623f358085e3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3abe5cbe7ce08e9c39ef","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18907,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3b834e2e1e9305adc7dc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":19689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3c15dad0de10fcb3940d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":13730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3c344177da39d32ebbb3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":11820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3d3fc741cd693c321f3c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-42bfa76fce18d5b34428","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-433104e7d8c1442600ca","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-43365053282d79a2ef4d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":16225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-43a7b8e6fc2c81346e3f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":10825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-448846b13aaa4c960092","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-454d7ae3bb0f64862809","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16604,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-46adcce2c19f39334ac2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":15586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-47406fd7c5294829cd17","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17034,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-48370bd09b976d97dbd8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":13115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4935ec04bac029211d03","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4b4716d8c87319aaa92f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4b72173a8ebe71df8285","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4cbdcc28feeba140f2ea","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4ccbd565695fa5768657","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":12651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4d38fabf8de3bc50313c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":15028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4d933fca87fdac097185","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":17889,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-50caa1b488c051292cc8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":17786,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-52a3ac737815ae734775","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-533ef8c505f142eba030","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":18700,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-545e6e53903fed82a826","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5585a4494ff06f0b626c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-590c184434bac31ae289","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-59c5b44e80429341d27c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5a969009255a2a964813","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":16162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5b00196bb214ede31674","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5ba53f6cc22bb1ca824a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":17784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5bd2a819a7b25eb274d2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5c4c3f255252af488b0d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5c65ba00083611ce622d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17236,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5e2a885b3d21932d846a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6236c10675925edb9b90","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":13553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6583488d0da01fc8ef29","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-65d9d74c865640a65a26","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":12576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-65dd33291f9b5de7ba4e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-68260693621f862d67b2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-69fbcd4a7e87daaae068","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":14088,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6c2e72a4195b2981a312","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19424,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6c6060cbfda413351fb4","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":19092,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6f927725b3147cfc1549","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":10229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-70909101625a8fcca6a3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7248df367dfd2960be47","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":14633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7273ab0be89733ad080c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":12070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7618fdc6e84eff5f6dbd","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7d730e6039e107fd3ae8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19604,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7db92659d3391ad65c1a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7e2dc5e8aac0d5fff8d7","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":23154,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-804af1ddf76c49910781","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":15480,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-80d7156a1b91ed22287b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":12864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-8150049125a7505036e2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-81d59491a1bf468b229b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-82683edd2cc5c2be916b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-86bb2767ec2061d053df","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":18727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-890d2284ebd3bdb51816","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":12107,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-894c46dfabd3533da75b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":19454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-8ebf174596f8bd815bea","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-8edcc5e6d6bb0f1a16ba","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":24918,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-905877fe766e2211d3da","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-91dfffdf023fd8d664e4","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-93332f160a13b68f334c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-93399eb07a69f20e4393","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":14511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-935d5d6eaae6efff8844","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":21746,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-96519457d8bbc8c5c44c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-97ed7970c64c03db8ca0","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":17441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-97f87447094342e0138a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":24628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-9a0f3261557420a0a829","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":21049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-9db0dc189483c3aa759e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":12581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-9e8346362c3dd59d8365","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":14308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a0ac272b87419b411d20","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":26420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a42f2967a883983f7eee","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":19636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a4d2e44b270d545690dc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":15891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a562f1607b5d97da27a3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":11060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a5c06614bd30ae670149","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a6d20cb1d84778e47c4c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a9010f9968be28f37ccb","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-add458358c6509860921","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":18779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b081a458527dd4771f99","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b28f4f7e3438b4f89868","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b347863166e253de21ec","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":12883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b3a81cc243659b5b22d2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":19515,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b3eab2a5b7bac6d69f9b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":13722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b78de60c5b14eebde42c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":21179,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b8fa07d6060299c39f8a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":17787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-bb3386e61fb78693df7c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":10919,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-bb40dcab0576d1ea381a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-bbeb537c5b28067ca5d5","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-be8661dc20d902f3ff6b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":13639,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c0c35dd94ce719f0b636","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":18669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c2a115cc084c1b8d1a18","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":11011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c2cdcf6514943a118a32","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c3c5ddb9bebf03c0ec16","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c86bdbbcf24594eef792","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":13759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c871813cde4f307ea67f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c994ce8b23bc3b24cae8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":13695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-ca031813decb3155a1cc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-cad3b8bff0bfe9d71e62","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-caffc1fcf9b06d4b8168","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d1223cb6f1374f90ac92","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16098,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d14f44ac967a37b19113","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d2913f43967f6ace073f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d2a12ff88beae508ac9c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d369aa150f9ce35db93b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":22066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d4a6824ffb45dfb27f03","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19976,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d624bd1de4f48d8c3f26","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":11030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d6759cdd35075bf16730","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d6c7ad5b8c7bf815b262","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dc19daf4b9e9d8bd13ae","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dd7ab1e9b75187ae8c78","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":16208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dd88ae8713aa827fe8ef","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":13882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dff7569cfc2418f45d23","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":20112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e0e5f798bbe87c7693d6","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":18532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e1d9500f79f1f507b9d5","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":17834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e2baa8f96ddd44d625fe","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":17923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e2fe242e40e7ecc5c28e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12348,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e4f5b5761c113321a49f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e7a260ce54c82fa93a5a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":18684,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e9a0ac4eadb2bfe66a3b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-eea4ca892981bf47608e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f4db9223c18459e4eda2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":16081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f5032a00993091c46b58","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f82caafb000c9503dedb","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":24995,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f9921789c29eb324c1c4","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":15048,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-fbd7a84a2f9ab8d3d0cc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":14938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-01848a9bbdce6b9464a1","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Container Column with OR operator","durationMs":23582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-01d3ad34adeb6f3572a9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Task with AND operator","durationMs":26659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-01e396d7fe625ea02be0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database with AND operator","durationMs":23841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-05d5089a21fbd76007e0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database with OR operator","durationMs":25969,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-0ed29065fa2f8ec2272b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Model Type with AND operator","durationMs":30988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-104c3fa8858e1ae3bd07","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Response Schema Field with AND operator","durationMs":26268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-10da06a834ad193ca900","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Field field","durationMs":34425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1265d5ff203e4d02a28a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database Schema with OR operator","durationMs":18927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-17159e54270c09d3b11f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Project with AND operator","durationMs":27269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-19c8b67e10d5e54c16b9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify count shows with Advanced Search filter","durationMs":15376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1d4be164ce6161534198","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Container Column with OR operator","durationMs":33638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1df04ebae89733aa49dc","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Schema Field with AND operator","durationMs":25914,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1e3349a7ef8159c1347c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database Schema with AND operator","durationMs":28102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1e9ffb963dd4a7583b7a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Response Schema Field field","durationMs":38788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1ea2187d290d764a4b89","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Is not null – table with a description is visible","durationMs":14622,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-20796c01b78775d6c025","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Not in [tag1] excludes table1","durationMs":17722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-20c96d382fccf4ab79ff","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Request Schema Field with AND operator","durationMs":25267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-265b4edd463886300e33","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Filtering by status \"==\" shows matching entity and hides others across entity types","durationMs":28398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-28aeb826280919957ec4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags == tag1 returns table1 and hides table2","durationMs":17439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-296bab1d11c2b9ca845b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Name with OR operator","durationMs":27956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2aa7c1b0da131245354c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Name with AND operator","durationMs":35448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2b95e329ec5e4e31e5e9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Schema Field field","durationMs":38895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2c3d820f0145617856b6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Container Column with AND operator","durationMs":32008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2ccc28a7a13694b41740","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Container Column field","durationMs":50959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2e183cba514fb3c2118c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service with AND operator","durationMs":31573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-322ce116d6306a5177f0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Owners with OR operator","durationMs":25076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-35e3f0c99d9eb1a34064","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Service Type field","durationMs":31471,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3728216e42f2d70c0ea6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tags with AND operator","durationMs":30804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-37e7f79fb6618a1e03b3","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Tags field","durationMs":36376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-37fca3a21c7cf0dda6f4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Domains field","durationMs":40494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-38ffce04e25ea99f6ea2","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Column with OR operator","durationMs":30178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3909c10761b7e38e4c65","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"should append page-2 items and make them visible when Load more button is clicked","durationMs":13737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3b2a5bee628fd4b430ec","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Task with OR operator","durationMs":29267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3b4256edbb1eb74b13b5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Chart with OR operator","durationMs":25178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3b768764404abfcf4c61","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Display Name with AND operator","durationMs":37148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3cb9d0ec4de9ab627c1e","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database Schema with AND operator","durationMs":31502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3fa2fce0a766d87533ba","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tags with AND operator","durationMs":28862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4acd7f5fca00875e8136","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tier with AND operator","durationMs":26970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4b5c200835ff15944667","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Product with AND operator","durationMs":25626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4b9cb43c11746fef17d8","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Schema Field with AND operator","durationMs":21733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4f927865854ea480aa3e","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Domains with OR operator","durationMs":33113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-55023d9cf5ab1d215a44","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Name field","durationMs":37145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-5f89518d523b9ba9aaac","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Not Contains – table is NOT visible when filtering by a word that IS in the description","durationMs":14502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-5fdfedbd523e3949feaf","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Model Type with OR operator","durationMs":27234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-605194d0ff1cc933d53b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags == tag2 returns table2 and hides table1","durationMs":14913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-63b0c7ba0ae092e35184","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Chart with OR operator","durationMs":22734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-6551e2d525c123143970","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Response Schema Field with AND operator","durationMs":24215,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-68eb716f87bfb906f7fe","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Data Model Type field","durationMs":48918,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-6d789214c13e0a4b34c5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Column with AND operator","durationMs":32384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-70515d66cc35b8507ad6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tier with OR operator","durationMs":25816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-705b359db456f1bc0884","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify count matches the API total for a quick filter","durationMs":12304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-72e8c3ea3b292870634b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service Type with AND operator","durationMs":29059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7474221eea6bd3f6f851","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Column with AND operator","durationMs":26292,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7593b16cd959b1bccb61","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Field with AND operator","durationMs":25978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-75e104c5eaa1b74c34f1","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tier with OR operator","durationMs":24378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-769657657a74bc339745","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Is null – table with a description is NOT visible","durationMs":15074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7a703a36be973b448822","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Is not null returns table with a column tag","durationMs":14057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7c77a04a9941a95f1d4b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Display Name with OR operator","durationMs":27691,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-81500305ba1d602123c5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Field with OR operator","durationMs":25153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-8234b81e5a5663597613","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Name with AND operator","durationMs":24278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-83aff3aa6b1a24d2d069","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Project with OR operator","durationMs":22539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-88367c4b6043b9c90965","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Description Contains filter returns matching tables","durationMs":12833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-8a8f8dc139a7a230d523","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service Type with AND operator","durationMs":33039,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-8e6b0455f554d30d7e06","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Data Product field","durationMs":34932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-9188bfd7d42b88264dd7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Request Schema Field field","durationMs":33408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-967c29378578d6fdea26","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Contains tag1 name returns table1","durationMs":13014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-9b337cbe854e86fa72f5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Display Name field","durationMs":44892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a012f1d06ec6466aa8b6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Display Name with OR operator","durationMs":31931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a159f21b5939cebf6a76","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Any in [tag1, tag2] returns both tables","durationMs":20168,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a41dafccec5f9c5ed119","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify browse mode has no count","durationMs":5237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a4e7df45b27cb472b042","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Project field","durationMs":48111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a55cbc04952eee33bff7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Request Schema Field with OR operator","durationMs":24808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a61ec30b0327dc631819","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tags with OR operator","durationMs":26546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a7bfc8dce1c294247fed","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify search with non existing value do not result in infinite search","durationMs":11312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a8094f96fbbffc874b81","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Owners with OR operator","durationMs":29711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a9032d44e2e5425ad802","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Service field","durationMs":48297,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a937f2c6c6c939c156b7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Domains with AND operator","durationMs":28352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-aadfd26e649f51ac33cf","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database with OR operator","durationMs":25595,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ad0865cf7553688429be","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Owners field","durationMs":33565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ae1ba0c1a9ffd00603bb","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Name with OR operator","durationMs":29890,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-aff5dd51e0721d50a905","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service Type with OR operator","durationMs":34299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-b0ac72779a45d7811744","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Product with AND operator","durationMs":34859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-b51becf84e64b5a6b239","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"All entity status options are visible in the Status dropdown","durationMs":9833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-b7275e658eba3413629a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Description Status == Complete – table with description is visible","durationMs":17197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-bbbc587a68840bdb685f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Model Type with AND operator","durationMs":27776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-bd7b44947c9de08623b6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"should find page-2 items via search without clicking Load more","durationMs":9526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-bdd71fde1fcd7c7034f9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Is null excludes tables that have column tags","durationMs":14874,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-beac8ac076370c1e2d1a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Field with OR operator","durationMs":34705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c21787818e27a603b94a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Chart field","durationMs":39051,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c2dc8a3cbadd6d431363","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Task with OR operator","durationMs":31875,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c401249e8edfb596e267","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Description Status == Incomplete – table with description is NOT visible","durationMs":14617,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c4178f3f1a09fee9bba7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Filtering by status \"!=\" excludes matched entity but shows all other entity types","durationMs":26139,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c8e29a2085426519eea5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Chart with AND operator","durationMs":35737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c91b448181fb0828b8a4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Domains with OR operator","durationMs":26365,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ce5bc3beeaeb56c7c7d4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Response Schema Field with OR operator","durationMs":22858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d133030d44a21ade5bae","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service Type with OR operator","durationMs":27670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d3ce7297e440b403e050","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Domains with AND operator","durationMs":31466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d79e232222e4787c355a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Database field","durationMs":48163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d929d5fdf2bc919508c2","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Container Column with AND operator","durationMs":28527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d9700ca4b5a3d6e23726","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Schema Field with OR operator","durationMs":29418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-da4ace00236ed1e3eff0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify the toolbar Clear All button is removed","durationMs":10528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-dc1da3be5b340f81fe5c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service with AND operator","durationMs":29056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-dcc05a544a77528fa228","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Field with AND operator","durationMs":21158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-dce1287be55029f6acdb","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Project with OR operator","durationMs":27812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-de073c560d5716e771cc","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Owners with AND operator","durationMs":24485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-de867e203297a3dc87df","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Product with OR operator","durationMs":25803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e07b93065e8a13f5458f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Model Type with OR operator","durationMs":23503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e0fcfe3b1c1255b12537","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Schema Field with OR operator","durationMs":29090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e2173d75f8617ecd7b30","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database Schema with OR operator","durationMs":27926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e31d942443165346ed83","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database with AND operator","durationMs":32727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e386dbc7762dc93f4e60","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Task with AND operator","durationMs":27512,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e3ca2f4c5a82a5530113","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Product with OR operator","durationMs":25060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e731ce0f8d9a3d4de465","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Chart with AND operator","durationMs":23829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e98c930265f88b9c9ea6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Project with AND operator","durationMs":19298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-eaec9a63094a1c230fe3","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tags with OR operator","durationMs":24368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-eb1c6c762c82fab9e5f7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Display Name with AND operator","durationMs":36128,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-eca9d97cb9da576ef82f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Database Schema field","durationMs":44692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ed0b5bb92613ce933c2f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Column field","durationMs":45593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-edde44fec5e8f1dc250a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tier with AND operator","durationMs":38366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ef9b3af75dd47ebf5374","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Not contains tag1 name excludes table1","durationMs":12650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f03202f4045c687551e9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Tier field","durationMs":52193,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f1bda9ce9ec6c293e189","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Column with OR operator","durationMs":27808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f338982eff0e858527a1","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Task field","durationMs":39133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f408b40000135ec0eb83","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service with OR operator","durationMs":34989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f596f76fabf5baba5568","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Owners with AND operator","durationMs":33511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f691e6bde217c36db0dd","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Response Schema Field with OR operator","durationMs":28886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f9d8db08a5cca0ce8bd2","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service with OR operator","durationMs":26839,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-faf56b02741dbae49628","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Request Schema Field with AND operator","durationMs":26992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-fbe116c672f82d125814","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags != tag1 excludes table1 from results","durationMs":16554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-fccef467d24b33c68ff5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Not Contains – table IS visible (word absent from description)","durationMs":17005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-fd63e2d647bc5fe4cd6f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Request Schema Field with OR operator","durationMs":34312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-030f976d52547ffee6af","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"locks system-defined relation types from edit and delete","durationMs":12863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-2ae9d6664eb6771f90a9","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"parallel API writers both succeed when exponential backoff is applied","durationMs":8538,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-420283d7f82a561357d0","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"edits a custom relation type and keeps the name immutable","durationMs":13888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-4deb76eb39aff4718dac","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"paginates relation types when they exceed a page","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-62eb7208161f3640d24f","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"rejects duplicate relation-type names with an inline error","durationMs":13562,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-6819ceb2313f81ae13c7","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"creates a custom relation type via the drawer","durationMs":13979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-97bdef908422bd78cf90","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"findRowAcrossPages locates a row when the table has multiple pages","durationMs":15637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-a47fe4536a712063a893","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"delete removes the row from the DOM before the caller proceeds","durationMs":12797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-eed27231e35e72bb34e0","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"deletes a custom relation type","durationMs":12874,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-0d5b9a6fb6b3f1d36fc5","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission cannot see restore or delete actions on an archived document","durationMs":9115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-10825ea530d9799b47e1","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions but not owner sees read-only banner and no edit/delete on the row","durationMs":10283,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-20e0ce562f9ba525f683","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission can see create action but not delete action, and can create an article","durationMs":24399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-2739db8bc9b9a4df8761","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission can see restore action but not delete action on an archived document, and can restore it","durationMs":14214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-27b7063c112f47ef11b2","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission sees no row delete action on memories they do not own, but can delete their own memory from the modal","durationMs":11998,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-421f44e2cb09509abf6a","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see create or upload actions","durationMs":8574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-540e879d00fd41114f62","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission sees Add Memory button but no row edit/delete actions or modal action buttons, and can create a memory","durationMs":13474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-54d59da4e5d21f32b45b","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions and owner can see Add Memory button and all row/modal actions","durationMs":8824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-5fd1ea349c43b5f7ade6","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"admin user can edit and save a memory owned by another user","durationMs":9878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-679ff08bf7ab1e9638e8","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"Data Consumer can view and edit content but cannot add article, domain, reviewer, data product, or data assets","durationMs":5274,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-67ee0ef55073be2f7ff6","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission sees no Add Memory button, no row actions, and no modal action buttons","durationMs":10199,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-6c7c5e4060896807dfbf","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see upload, folder, or row actions","durationMs":9317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-7048ad1b2cdbba8c7098","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"selecting \"Updated By\" actually reorders rows by updatedBy","durationMs":8419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-75d84722d862535a7d5f","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission cannot see create or upload actions","durationMs":8854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-7bf2358642df91e09c6f","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission can see upload and folder create actions but no row actions, and can create a folder","durationMs":16257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-7fbf4a859228cd5d2077","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"created-by-me filter on the archive page shows only the current user's archived documents","durationMs":11806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8688c4eab1661197c622","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see upload, folder create, and all row actions","durationMs":9869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8b30f4dc8b9a4455def6","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see create or delete actions, but can use share/vote/conversation actions","durationMs":20559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8e9545a0b5baa5e47cbd","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission cannot see create or delete actions, and can move an article under another article","durationMs":18882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8f70f3d35807262b000c","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission can see create and upload actions and perform them","durationMs":14429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-9688a6c96efd0f62f947","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission cannot see create or upload actions","durationMs":10539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-9c43270f91aa02211126","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission sees row delete action but no upload, folder create, or move actions, and can delete a document","durationMs":13239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-a1a04fa4162c7391462d","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"a document archived by a different user can be permanently deleted, via the UI, by a user with Delete permission","durationMs":12359,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-aa88bf1cafba61d0b0c8","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see create and delete actions","durationMs":12409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-b2da0b8d956c9c571e7e","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see restore or delete actions on an archived document","durationMs":9722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-b83ccb07716204f13779","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"Data Steward can edit content, title, owners, tags, and glossary terms but cannot add article, domain, reviewer, data product, or data assets","durationMs":4304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-cbd6a4c438db46a87069","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission sees no row edit action on memories they do not own, but can edit and save their own memory","durationMs":12540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-d406b1d8244bd4837a02","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission sees row move action but no upload, folder create, or delete actions, and can move a document","durationMs":12770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-d5d7c9b8b9a2392b0cc9","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see create and upload actions","durationMs":9458,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-e3b36012c515ccf872c2","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission can see delete action but not restore action on an archived document, and can delete it","durationMs":13652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-e45828987ae3f8cf1c7b","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission can see delete action but not create action, and can delete an article","durationMs":21362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-f14a3d0a85483b085cb1","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"ViewAll-only user cannot create or edit articles","durationMs":10075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-f9b86eac13a88a92bf94","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see restore and delete actions on an archived document","durationMs":8948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-fcde0758e6b601a806ce","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission who owns a memory still cannot edit or delete it","durationMs":9326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-18c6f5eb9f9c19c50dde","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Data Product asset count should update when assets are removed","durationMs":41693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-3a3f742e93d47ca84940","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Verify Widgets are having 0 count initially","durationMs":14012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-81becdadc5311eeb58f8","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Domain asset count should update when assets are removed","durationMs":25055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-9c5b7d3adf677a591fe0","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Data Product asset count should update when assets are added","durationMs":49306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-c6a8e0211da1e6bd097b","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Domain asset count should update when assets are added","durationMs":57047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-e2b7b5f7dbe2189375ac","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Assign Widgets","durationMs":36440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-31c3cba0658c41ef8b20","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity stream API is called when visiting entity page","durationMs":19871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-5e9ae60fe863e3648021","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity feed left panel shows All and Tasks options","durationMs":14060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-78c3f0503d643e660906","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity count badge is displayed in tab header","durationMs":16097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-78ef0b8aae139b3200d9","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity feed tab shows activity events for entity","durationMs":19871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-b8948aa10be3f126124a","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity events are created when entity tags are updated","durationMs":22157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-c01253c3651ccbe9853a","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity events are created when entity description is updated","durationMs":22803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-052a649575c460f16115","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should display entity name link in panel header in glossary term assets context","durationMs":9162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-668b29b178430ef599ee","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit owners from glossary term assets context","durationMs":13070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-7d959402ac411fa1226d","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should display overview tab content in glossary term assets context","durationMs":8989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-7e30f5925bae38e11c8f","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit glossary terms from glossary term assets context","durationMs":11830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-8d7f4224e6da7668b1a0","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should open right panel when clicking asset in glossary term assets tab","durationMs":9161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-9a8a1508351c9a62e774","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should assign tier from glossary term assets context","durationMs":10924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-9fcb2cd0167b25ce5be3","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should display correct tabs for table entity in glossary term assets context","durationMs":8762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-dcabc8f167f7a85fe179","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit description from glossary term assets context","durationMs":11764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-ee18c163cf99218a6116","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit tags from glossary term assets context","durationMs":10962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-f3abb25309536ec109d8","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit domain from glossary term assets context","durationMs":11246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69cacca71964c08834ec-13d8e90a56a4cbcc29e6","project":"chromium","file":"Features/SchemaDefinition.spec.ts","title":"Verify schema definition (views) of table entity","durationMs":7335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-0d63c51a5b8439797ec4","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test search on Table version page columns","durationMs":4934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-1afaf40ca75b9169745f","project":"Basic","file":"Features/Pagination.spec.ts","title":"should display at most pageSize rows on each page and total matches task count","durationMs":3664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-1effafa017fa24dae3a8","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schema Tables normal pagination","durationMs":12576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-270586167806dc7a45d7","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Notification Alerts page","durationMs":11073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-4536ce90c513ea40babb","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Table columns complete flow with search","durationMs":16581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-4849a60b7f9b9c75970b","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Stored Procedures complete flow with search","durationMs":13189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-4a9e844a35462eb4ed53","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test API Collection normal pagination","durationMs":10893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-522675c74c67c05389c8","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Service version page","durationMs":5818,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-569e6236bb343a798340","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Table version page columns","durationMs":8623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5976c978fb8e0412cae3","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Classification Tags page","durationMs":9055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5a0809981ccad3fac96a","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Spreadsheets normal pagination","durationMs":12040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5b1b1a14ee145e3320a2","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Directories complete flow with search","durationMs":13820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5deca5d41faf8cf09f92","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Users page","durationMs":11843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-61c3a2cd143654c345ea","project":"Basic","file":"Features/Pagination.spec.ts","title":"should reset pagination when switching between Files and Spreadsheets tabs and also verify the api is called with correct payload","durationMs":11197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-62a7e49254bc5ed1c0fd","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Files complete flow with search","durationMs":12560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-65a356df11068eb892a9","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Data Models complete flow with search","durationMs":11563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-6ccab878d5d132496901","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Table columns","durationMs":17243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-70eff9216ce9baf67def","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schemas complete flow with search","durationMs":13595,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-7230a3d6ac8be6c0b43b","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Bots page","durationMs":10740,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-755acad3b9ae48868e50","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Service Databases page","durationMs":12246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-7f9d55e3f06664f27de6","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Spreadsheets complete flow with search","durationMs":12133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-81562d6199750c91eedf","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Stored Procedures normal pagination","durationMs":12617,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-95f815f4af52e846761f","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Data Models normal pagination","durationMs":12429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-ac4a045699a81c56318d","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Service Database Tables complete flow with search","durationMs":13155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-b9120310e2cedd8c5bf0","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schemas normal pagination","durationMs":11860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-be507602cb869bf3d3a4","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Roles page","durationMs":10768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-c0e169775cd894d676f8","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Metrics page","durationMs":9811,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-c5300a813856c71be56c","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Pipeline Tasks normal pagination","durationMs":11341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-cf38d16dc446f8c57869","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Policies page","durationMs":11075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d09956c0604ead156107","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Users complete flow with search","durationMs":11963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d28067dfec2215fc2a1f","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test API Collection complete flow with search","durationMs":10389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d4ee9d0888330156246e","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schema Tables complete flow with search","durationMs":13600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d6cd483f8e72dec2aab6","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Observability Alerts page","durationMs":10771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-dbd8d16a665a04625901","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Directories normal pagination","durationMs":9514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-fa33d3888c5145159d4c","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Files normal pagination","durationMs":10504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ab1a126f5f0454c42dc-aa12aecd843105a4100f","project":"chromium","file":"Pages/PipelineValidation.spec.ts","title":"should reject pipeline creation when task name contains reserved FQN characters","durationMs":8,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ab1a126f5f0454c42dc-efa1da2a9c4231a884ee","project":"chromium","file":"Pages/PipelineValidation.spec.ts","title":"should reject pipeline creation when task name is empty","durationMs":21,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-00d78358a54604aa5230","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Follow & Un-follow entity for Database Entity","durationMs":14746,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-05ceb395a88e2b017909","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-07fa338ea4eb691ca04e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":14426,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-095366bb3f9782e4b4ac","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":14674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-0d9793ea09690a80b966","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-0ebb53f319f2a67ff9f4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":5794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-0fe6b99ec9f67bfa9faa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":13264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-12ec4b8c5deb13223785","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":11781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-13e54e4ad192cd9efb73","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":21648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-141e1d403d78ee81d20d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":6428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-17428dd1dbd106320b78","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-17c18c4a39bde14e5a5b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Database Service","durationMs":24703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-19d75f5f67db078abe6c","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":17609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1b6aef52cf71f2f96cd8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":14151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1cef3376d98ef0bc6845","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1d6aa7210486e47f00e3","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":14781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1f7257faa3ff6ee3d90a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":11219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2044951d3a73d0b2d996","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":19805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-22f08f8e66fb0a6b142f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2339e2d24363f2751c72","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-23f289761eea5d8ad0d9","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":18575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2415dc37c3890f585aaa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":16100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-28f4e85540f8278e7e5e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":7112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2b3f4a2ef8db1d71465e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":24716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2bb0ad11cb7c8c9e83ac","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":13127,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2e1bdc838f7d0fd8bcd7","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":11774,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-315d4c39979d5b429be4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":11901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-330814fd205fc63c7a89","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":7135,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-36a6a7eff3583482208b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":14769,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-3d6d96bcfc6c2b28446a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-3f0f017751c0f9e5d24e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":11033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-3fd1a3fbb71265224dd8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":12562,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-439162d3691b598fbc91","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":8483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-44a0649dc047654eaf5d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":11532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-44d28a5b57954577834f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":8403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-456a6d64f84a51837dd9","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":7964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-46581f14ac1a04c5ae14","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Messaging Service","durationMs":27019,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-48696a6d0816b53ee59d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":6260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4ab33598b1cfd871bfe7","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":14717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4bf44086b6fb8019ca24","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":13068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4c97fecb78d90497f70f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":12905,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4ceda484206529830fc1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Api Service","durationMs":28727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4d7762a289fe4ba86f4c","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":18603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4db8a131edf74e52d43e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":26816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4e3b0413aee3a8de3c8e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14713,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4eccaafaf317fd3925eb","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":10345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-502d8da9de83d9520848","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-5405ded470cb5150a6d0","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":15556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-586f692293f073d1021f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":8764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-58bdff9e058f898c1af8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Search Index Service","durationMs":26405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-5956015465cac568e5fa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":6227,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-59781b41dd8cc26391e1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-61ca56e64d18f8db0689","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-64ec4bc4779c2028b4f6","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-66c12a591dde84d462a5","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":14362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-681341682d7d6ff41b5a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":15949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-68fd12d73abb2789cdb5","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":13916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6b438bbddf9c67179b23","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6b52238501c9dd87c323","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6e97f2492432e11bd72f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":26948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6e9f9c02b1878da34748","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":17177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-71ad41b0d7192f9308b0","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-72b2976f74708121344b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Pipeline Service","durationMs":27372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-738ae92e7a456d8559cd","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":9210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-74a1e27f45394080d2a2","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-79f742b06207108de1fa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":22055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-7c0ca4d50ff297de79ec","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":21151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-7ced936483e254bdc26f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-851289553bf3f933e4d1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":19464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-864ac85bd99a9a4cd647","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":11758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8a886064018e6d7ce40d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":16668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8c3e68a1db2f22a89a00","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":15995,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8dc41e621dab83ad094c","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":15951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8e67349c98bdd3b3b16b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":16741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-901d2391b8c515986986","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":34446,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-90c9ce604f7a5005c6b5","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-90f41a42948dfce135db","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":10604,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9354d7b199cc56d1285b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Database","durationMs":29259,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-97d8de928397f494de98","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":25066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-98560e031b247e205bee","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":8380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9eb835bbaf3d632ff610","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":14508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9ed1e087674fbc9e90ca","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":14761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9fe5cbbaefa01f3b8088","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":18724,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a1aa9e9e55e2aaf5c830","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a385aaaa6615db8d41b4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a5df7e6bc93587c9c39f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":14573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a8858778387f593ba0f8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":11738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a915ceb90728aafa8624","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a95000b4d2a834bca12a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":17994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a95af30fabe36816ae5b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Certification Add Remove","durationMs":18696,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a9ace2bb98e05805214d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ad6771e7ca6599ec9d2f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":12664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-af5887e77e84824f926f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":7758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b1f3c51ac39336818657","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Follow & Un-follow entity for Database Entity","durationMs":25374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b2f8330ad165aa371918","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":7734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b5448a6d970596d21ff3","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":13016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b66b7fb8d4958d16af63","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":23026,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b87b5ff8369052806821","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Storage Service","durationMs":24703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b8a15061fd3f12b20ddd","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Dashboard Service","durationMs":22284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-bd4d81cb27aebc7522c6","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":9729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-beb2a792c179b0e18582","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":16246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-bfbb1f2951aa7247cfcb","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":11159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c059425f0ee306d51262","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":9095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c0e25a61c0c94d058b14","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":18050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c1ee83ea9c55a5143b78","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":19559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c5f0c42ad03d6cd1533d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":28027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cd1f1f467e0f30044cdc","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":11102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cd4638ad50da7c16713f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cd6cc1c77ceb3a4f813f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cdb652309a855e8e8b6e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":14262,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d401b8d4fdec50f4d527","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d41e33cf18f0a0f03d4a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":14520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d5c7e41187ffccee6c2f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":13958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d7acb023b21d042a3854","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":7153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ddd593594947a3f2f7e8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":8773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-dfa31604b8badf1fca29","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":14429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e2f4e4bd31755dce4ba1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":17203,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e56d1b8c2d393ba2eac6","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Mlmodel Service","durationMs":27952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e5745670b7663e6284ba","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Certification Add Remove","durationMs":18602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e5b8f6da7ae9c9c091d8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":26392,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ea74abe48bd512e6d744","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":29247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ea80f5ffeba8e3e514e3","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":13440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ed093e7198e33633d2f4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":13307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f19a60e986c74388fcf1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":14147,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f739417ab5977cadad8a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Drive Service","durationMs":28117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f74fb883c671c6c2adff","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":9490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f88eadfd770af9615a31","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f8908380572ade6ba2bc","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":23827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fc556a3cfc34a3a4842b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Database Schema","durationMs":21326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fc6a816a8d68fa625004","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":17223,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fd38fa8ea0050bc11f12","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":8960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fd72e28576cf322baa24","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":9244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fd845648f618a8c8686a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Follow & Un-follow entity for Database Entity","durationMs":27063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ff8a67b3c643a6de256d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":31601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ff8e8ecfffbb7bc11dbc","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":15738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-60c875ad97424dee4e25","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create and approve entity-level description task for Dashboard","durationMs":736,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-786e6f8c70160627e0e9","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create and approve TagUpdate task for Dashboard","durationMs":483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-90cedc12661a4643946e","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"rejected task should NOT apply changes","durationMs":298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-b4317d710c370bd24be7","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create OwnershipUpdate task for Dashboard","durationMs":1661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-f378c009570f9449ef08","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should show task in activity feed after creation","durationMs":17862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-f4e63cb88ba395b56c54","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create TierUpdate task for Dashboard","durationMs":504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-f505580b6048b9e7f4f7","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create DomainUpdate task for Dashboard","durationMs":354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-0f6f29e2f1c4b474fdd2","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"zoom and fit-view controls are visible in glossary scope","durationMs":8437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-155194eb24d2e2caccd9","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"clicking a node in the Relations Graph opens the entity summary panel","durationMs":9574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-1b32d1add1034bd536eb","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"an edge exists between a nested child and its cross-glossary related term","durationMs":8667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-2b0b559c4357595c86c7","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"search returns empty state when no term matches the query","durationMs":9435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-2d4e6ef72c33fc44d05b","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"deeply nested grandchild term appears as a node in the glossary Relations Graph","durationMs":8944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-4ac81f68eadb0eddd0f1","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"isolated term within the same glossary IS shown in the Relations Graph by default","durationMs":8616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-4d3660629680261514e8","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"a parentOf edge exists between a parent term and its child in the Relations Graph","durationMs":8989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-5ea646b31bc57f6ceb8d","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"cross-glossary related term has an edge to the term in the viewed glossary","durationMs":8393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-752887931640b36a1b6b","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"Relations Graph tab renders the ontology explorer for a glossary with related terms","durationMs":9651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-8a81ed58944bf0102167","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"search in the Relations Graph filters to the matching node and its neighbours","durationMs":9235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-8d45c5f6a1ebda6dab15","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"term from an unrelated glossary is NOT shown in the Relations Graph","durationMs":9951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-9f75d86f777103f3730b","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"global filter toolbar is NOT shown in glossary scope","durationMs":8689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-a02781b14c6c4a0560a7","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"nested child term appears as a node in the glossary Relations Graph","durationMs":9598,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-a6f0673f9f3ec464a1a6","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"related terms from the glossary appear as nodes in the Relations Graph","durationMs":9186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-b7bbd38343ffe4ec95b3","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"an edge with the correct relationType exists between the related terms","durationMs":9074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-c46a41f4509f43b3c19a","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"cross-glossary related term appears as a node in the glossary Relations Graph","durationMs":8665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-d0894452615bac35da92","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"cross-glossary term related to a nested child appears as a node in the glossary Relations Graph","durationMs":8571,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-02a9f1f5bc2bb9cb4d3f","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"My Data filter should show only owned entity activity","durationMs":8822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-130907f22f9a222f9f78","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"entity tab badge totals conversations, activity and tasks","durationMs":6710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-218075417344154ad45d","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"creating task should immediately appear in entity feed","durationMs":12041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-25c0ae0e67cbf704171c","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should show task in activity feed widget","durationMs":11787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-2648a94a2a8068a286c0","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"Activity Feed widget filters should switch between All Activity, My Data, and Following","durationMs":11541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-495fa33b459cbee9a0c6","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should show description updates in activity feed","durationMs":8896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-4f7c55b775868a3cf15c","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should have clickable task links that navigate correctly","durationMs":9278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-637ba584c4c13c1ec867","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"assignee should see assigned tasks in Tasks filter","durationMs":9155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-64e4c0054be5e225e0a5","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should display activity feed tab on entity page","durationMs":7398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-92037e70c926a2ee43db","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"updating entity should create activity in feed","durationMs":8340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-9a99af13dea9f806d0d2","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"clicking activity feed tab should show feed and tasks","durationMs":7660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-bb14751acfa82ef92787","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"entity task filters should request open, closed, and mentions views","durationMs":10017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-c0fb4e74dc25f2e9f4e2","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"All and Tasks panels each show their own seeded items","durationMs":7522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-c8ec51c30cc18befab0d","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should display activity feed widget on home page","durationMs":11580,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-e0b6d76a34064a97d805","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"Tasks filter should show only tasks","durationMs":8568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-fb6c38e52d91ff7a7ad1","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"following an entity should show its activity in Following filter","durationMs":8937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-fef19851f322651f1034","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"All filter should show all activity","durationMs":10055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-69ef15cf8752da40f2d0","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify table search with special characters as handled","durationMs":20697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-b2d9d31b73fb2eb60e67","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify domain platform view","durationMs":6368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-b6a72c0554063dbc917e","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify platform view switching","durationMs":4856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-f85c9a5692010b56850f","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify service platform view","durationMs":7404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d0fae529d1edab6e47b-b7e0c7af5d202caa41de","project":"DomainIsolation","file":"Features/DomainIsolation/DomainIncidentIsolation.spec.ts","title":"admin sees incidents from every domain","durationMs":7128,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d0fae529d1edab6e47b-fa37465f7517bf023bcf","project":"DomainIsolation","file":"Features/DomainIsolation/DomainIncidentIsolation.spec.ts","title":"user without a domain cannot see incidents belonging to a domain","durationMs":7767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-55e0b895422ddbcfcabe","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"should render the service listing page","durationMs":6251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-9661a49fa27744bd3143","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"should send wildcard query_filter on name and displayName when searching","durationMs":4627,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-b799453e514626e37076","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"service listing pages should use the correct search index for search","durationMs":18797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-d7a58326fcfc4813852f","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"should find service when searching by displayName","durationMs":4278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-0e8840821fdd9591c08c","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create glossary term via row action (+) button","durationMs":9168,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-0f76b5d2ce502173a58b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Add and Remove Assets","durationMs":20690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-1bbd2c7b10a1630cab95","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify Glossary Term Deny Permission","durationMs":14311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-1f0f00122ded66da4ee5","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - multiple deletes all succeed","durationMs":11910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-24070596b72f9abe027d","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Column dropdown drag-and-drop functionality for Glossary Terms table","durationMs":8157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-250c033f5b7545226c98","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify Glossary Deny Permission","durationMs":10001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-2e2d5dcd6abb731f559b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Add Glossary Term inside another Term","durationMs":11323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-2fc1b4844bf346a49db7","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - WebSocket failure triggers recovery","durationMs":9939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-324008c43bb03cdc58ba","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify asset selection modal filters are shown upfront","durationMs":24960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-33111021a8e04784f97b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary & terms creation for reviewer as team","durationMs":40952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-33c9092459c128f840b0","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create glossary, change language to Dutch, and delete glossary","durationMs":18502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-39d846e87c6473185980","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary Term Update in Glossary Page should persist tree","durationMs":8305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-3ea56dcec13cfd0cb14b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary & terms creation for reviewer as user","durationMs":39582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-3eb3ff25dcb18cef8261","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Check for duplicate Glossary Term with Glossary having dot in name","durationMs":9387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-4bb9baa9d5c21cfdbf9f","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify Expand All For Nested Glossary Terms","durationMs":8923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-5a610d0a9eb613d67238","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Request tags for Glossary","durationMs":31784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-5a931a565618611e9157","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary creation with domain selection","durationMs":11501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-671802bb890487e49835","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - multiple deletes with mixed results","durationMs":15499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-72c1dc9f8709dfe8230e","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Cancel glossary delete operation","durationMs":9181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-7fe26832ef78f2917c1f","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Update Glossary and Glossary Term","durationMs":32430,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-81dc43d85a215ab8b165","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Delete Glossary and Glossary Term using Delete Modal","durationMs":16784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-857ca83e7559df6d36e0","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary Terms Table Status filtering","durationMs":7096,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-8cb20faba23be878c6dc","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Request description task for Glossary Term","durationMs":13073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-8d87915326d11af4cefc","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create term with references during creation","durationMs":9304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-8e7d0dee5127a7499a42","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Rename Glossary Term and verify assets","durationMs":49110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a15003491770da48495f","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Cancel glossary term delete operation","durationMs":12354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a19e65f930c31ed62640","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - single delete success","durationMs":14060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a32aed4937ee6208029e","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Change glossary term hierarchy using menu options across glossary","durationMs":21061,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a6cb7e10eba2ff9cdce7","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Column selection and visibility for Glossary Terms table","durationMs":21094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a710897c7d486fbb4486","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Drag and Drop Glossary Term","durationMs":17553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-b9921bc7a75085d79508","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Change glossary term hierarchy using menu options","durationMs":10064,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-c748c4ce0e07a48a2b83","project":"chromium","file":"Pages/Glossary.spec.ts","title":"should handle glossary after description is deleted","durationMs":10265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-c7d137db2fa513ee316c","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Approve and reject glossary term from Glossary Listing","durationMs":27215,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-cf340c60c05ff8f90b01","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Drag and Drop Glossary Term Approved Terms having reviewer","durationMs":14086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d0d74d1eebd0e9ec349b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Update glossary display name via rename modal","durationMs":9220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d35fc5f3b1a45324e336","project":"chromium","file":"Pages/Glossary.spec.ts","title":"should handle glossary term after description is deleted","durationMs":10455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d889c49c19047a815116","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create glossary with all optional fields (tags, owners, reviewers, domain)","durationMs":18159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d9372e9478961f7918e0","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Request description task for Glossary","durationMs":12484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-dae7065ebeb1f43dad4e","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Add, Update and Verify Data Glossary Term","durationMs":13783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-e37cc1dc3d2ab84a987a","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Update glossary term display name via edit modal","durationMs":8411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-e4264aa2f6b7d75c5586","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create term with synonyms during creation","durationMs":9250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-f62b0df349afb243d895","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create term with related terms, tags and owners during creation","durationMs":12671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-fc77f94d1b063e3741af","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Check for duplicate Glossary Term","durationMs":10499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-fd3cdcb2fa734b3b5501","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Term should stay approved when changes made by reviewer","durationMs":30009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-fe267b81be07d2c8b0d4","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Assign Glossary Term to entity and check assets","durationMs":17554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-15e7a6655993cf472f71","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"FAILED import job shows error styling and dismiss button","durationMs":5333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-2c8ea2ed5e902ca58987","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"can cancel a running job from the tray","durationMs":5475,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-50a6a22f1167181c90a0","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows Download button for a completed export job","durationMs":6053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-5dc1fd8ecf1e78491cab","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"multiple jobs co-exist in the tray","durationMs":5658,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-74fc8dff0080e7079d56","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"auto-opens the tray for download when the poll completes it, minimised and multi-pod","durationMs":8572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-abf606d9a6ab5b15ca5a","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"Clear completed removes all terminal jobs and hides the tray","durationMs":5819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-d3918016bff34a387cf5","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"reaches Completed by polling, without a websocket event","durationMs":9498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-d498b16902150f020cf6","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows a lineage export job in the tray","durationMs":5327,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-e8bb44e083b6c9008b89","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows a running export job and its progress text","durationMs":7378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-f4e002a0ef30f8649c0c","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows an import job in the tray","durationMs":5844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-fd7fc1a370ea9ae52400","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"dismiss button removes a completed import job and hides the tray","durationMs":5290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f0590c0231406c6c5a0-022fa2831b7edf55d8f0","project":"chromium","file":"Features/TierDropdown.spec.ts","title":"should show tier again after re-enabling disabled tag","durationMs":13876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f0590c0231406c6c5a0-26e804d4f6811de98994","project":"chromium","file":"Features/TierDropdown.spec.ts","title":"should show enabled tier tag in dropdown","durationMs":9081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f0590c0231406c6c5a0-468f85de81c9afec7bfc","project":"chromium","file":"Features/TierDropdown.spec.ts","title":"should NOT show disabled tier tag in dropdown","durationMs":9274,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-00204bf3d420e3c1362f","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Any_In","durationMs":27812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-0a941e8cff652ad32a0b","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is Not","durationMs":23433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-0ddc285347b228f85206","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is Not","durationMs":25569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-150515a15c5e4f366b88","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Less than <","durationMs":22345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-171540945652ea1c4669","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is_Not","durationMs":30402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-236779457b0d1656b12c","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Less than equal <=","durationMs":21290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-23f7096c73ed3b03ea31","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Greater than >","durationMs":21542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-24f53ec25d5a2ae1b8f0","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Not_In","durationMs":22477,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-293d5150c418db58f951","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is_Set","durationMs":20831,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-371b66dc6824959e3445","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Any_In","durationMs":26469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-401cf2233b89cc98bc05","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is_Not_Set","durationMs":21414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-45ea20bc75c5c6030bd0","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is","durationMs":22209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-4f736eab9ff01cba8174","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Not_In","durationMs":32022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-5837ce00a1f636832c29","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Is Not","durationMs":22793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-69de011bc32436fd94f7","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Is","durationMs":25453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-6b295db5f949a01405ee","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Contains","durationMs":23422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-6b58e52550f8b1fa9dd5","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is_Set","durationMs":24817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-71cc9056833b064bdb3d","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate semantics fields","durationMs":12360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-728dc344e20efb9729b9","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is","durationMs":25987,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-761e52994497d5d1e897","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Any_In","durationMs":22554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-76b8bbfc4abe6888a560","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is_Set","durationMs":23478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-77dab837438ee562ad3f","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is","durationMs":22869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-82a0d03adf940fb889c8","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Greater than","durationMs":17782,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-8ff70b2979cf0715ab91","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is_Not_Set","durationMs":22697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-9cfe99b98caf05fddac1","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Is_Not_Set","durationMs":23863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-a04ece8b45d647faeb43","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Not_Between","durationMs":19247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b00a58585fdb947f1ae7","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Less than Equal","durationMs":16018,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b2713e50d8d09a875c66","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Not_In","durationMs":20816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b2f8faabd3ce8bd6fe9c","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is_Set","durationMs":23453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b376a2ffda8ffaaf70fe","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Not Contains","durationMs":22714,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b5b5798172033fc42f0c","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Between","durationMs":18079,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-c71827d0e1bc939645d1","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is","durationMs":24760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-c982caaa50eb72dbae85","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is_Not_Set","durationMs":23896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-dcee5e388fad4727090e","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Is_Set","durationMs":24793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-eb537c1fbd594f3b40b2","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Greater Than Equal","durationMs":17671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-eca97bb8f81b98afc82d","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Not_In","durationMs":29481,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-f218a044c71b677a3ff1","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Less than","durationMs":18408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-f6bec3efb1ea171da67b","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is_Not_Set","durationMs":18981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-fa4ea30a932d11c1087f","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Any_In","durationMs":20630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-fd19177a0b37dd31d6a6","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is Not","durationMs":22404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-ff5f445d50fd4aca74f2","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Greater than equal >=","durationMs":21194,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-0dee03971527229cf2b4","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"Copy column link should have valid URL format","durationMs":13984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-19f3266acdd6cf2bbe8a","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"schema table test","durationMs":65030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-55dc5f002f5389dd54c6","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"Copy column link button should copy the column URL to clipboard","durationMs":23682,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-d9fd88aeb278a136b4b9","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"Copy nested column link should include full hierarchical path","durationMs":29938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-10870a5ff304ba82d6e7","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Single Filter Alert","durationMs":40520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-40be061349021020fcd0","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Multiple Filters Alert","durationMs":37027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-5f357d0a8f543a66ce84","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Task source alert","durationMs":20640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-624bf59d0b99f47aba5f","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"destination should work properly","durationMs":11484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-a5110db8fbca70dbfb81","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Conversation source alert","durationMs":22577,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-df4c09990358fadaa853","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Alert operations for a user with and without permissions","durationMs":61361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-089ac879c8a1bf48e14e","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":6046,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-2123239773951a420d08","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":8424,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-607ce3ae26140d8d5214","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":9040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-a9296610d946263c61d6","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":5808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-aec4f097f30f2f6f3d5b","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":6621,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-c8f9791788c2c6562291","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":8560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-ebee8e531238cd9a1ce1","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":8911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-1791da577014ae152bcb","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Export maintains hierarchy structure in CSV","durationMs":9950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-3d16c444f1c9c329db61","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Glossary CSV import rejects unknown relation type","durationMs":19122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-493528214858d92fd7a5","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Glossary CSV import preserves typed relations","durationMs":40584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-679f70fff3c550677e9d","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Import partial success - some terms pass, some fail","durationMs":10018,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-8ea351f3c7814ef9e3d9","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Export large glossary with many terms","durationMs":14230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-9ffaf4d7a82a18e1f940","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Import validation - missing required fields","durationMs":9866,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-a2b1b1d4e5d988307f70","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Glossary Bulk Import Export","durationMs":135241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-cee2d57c047fe3642660","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Check for Circular Reference in Glossary Import","durationMs":50519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-fdb534fec42101d87676","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Import validation - invalid parent reference","durationMs":10256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-00dc2bfe21cad2f9df2a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":17981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-05419e782211d9d1de2a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":12164,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0734f3c96e7f54ce6c6a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-07b4ea279b562bfe5f3e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":12542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-098aa2e4c7da1b046465","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":18005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-099a8b05c67e2846d078","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-09ad004942c23feecedd","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":12099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0af5b5347fe1881e8bd8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":17343,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0be37046a03f74efd994","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0f1f2d5e8d4043861466","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":16036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-104abf45b88605c51ba2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":23804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1233936a260349b16c83","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":16190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-13079334487a6cadd03d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":15498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-13add27af4975daea758","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":15900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-13e4d9f5ee7a05fd7ba3","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1505cf28cd885f4777a4","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":11214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-159605a397828a93f493","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":10010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-15b85784d9980e662aac","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-171caaaaadb1abdde4e8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":18781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-179a76d9663cf8294023","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1dc7f85d16a2b90bb9b5","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"DisplayName edit for child entities should not be allowed","durationMs":15376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1fce82f531f7060e9a80","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":13670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-207d899430f83bd70026","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":16952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-25d1ff90961691a28f62","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2615b128abf51a2b722e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":20420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2846038d5787a94b6221","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":12773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-28b4f6bcc80a1469e2a6","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":18531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2b2b7ce855f4c94504cf","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2fd5d612894f1dc087d2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15199,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-313f7934124ca3a6ec1e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":13401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-31cac5cc40a390e2ada4","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":19214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-32c128143c6af1999483","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":9305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-35d5a3a5220f9b82914e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-3674479f1e1d92294596","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":14797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-368e75ff19cf7240c335","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-397071d12f931d852590","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":19375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-3cf9455e51dd60f34c9c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":18275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-3d5a8b6ded213476ccb9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":22900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-40e20c32f73b2f1e33db","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-42ed38552b351ed6c93d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":17156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4349f30cfdd7afe581f0","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":12574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-451b7a6d09e89e02b130","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4a795e20925174b2ebbf","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":12958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4e2068c8100414367241","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":13192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4f77ec64b3961ae26287","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":13999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-55df040662d878f36358","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":13293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-57c6d7653390fa73f1af","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":10332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-58090467bafe4832be37","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":16816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5bbca01e71559b6833a9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":18567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5bbd17233fbb970090c0","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":18716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5e7dd90d5176a4da519b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":17964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5e913694e9bf25d7a0da","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":10512,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5fe9f87da680252d5de7","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":12157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-62a7ab20daeb7fd9d75a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":11556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-63ebcb256954060a40e2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":19153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-64c9dec746918237cfc9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":15207,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-665195c1bcf8ae7d6dc5","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":13113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-66b9bd452e0e1785a5d7","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":20421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6a354d7e70e5fc359cec","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6ce1ce593dc1604c0d8c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":14076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6e073fa1c99cfcd9614e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":21581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6e3155a8180681dce32f","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-741ba010d8001a9fd629","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":16432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-764889744082814f83b9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":27973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-764f83da00cc0a2bc041","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-77d5fb9465e2342072eb","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":10843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7954ae16633a0595e250","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7c7fe35a843c7aa4c1e7","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":18807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7d8680096167e16dee4e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7ee85a0df418f4685ece","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7fe4517367fdf10aeb2e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":21873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-80ea803681cb43d239a8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":16022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-811ff9238e656b089a1e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"DisplayName edit for child entities should not be allowed","durationMs":15451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-84d793627d1430a44c63","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":13080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-871014d136a919f8ddac","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-89be5e692516eb5ace57","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":11335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-8d75a1daebe16b4ad248","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":14652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-8da24219a87618238385","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":22923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-8f18317ce2a8dedc296b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":15507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-918beeac313c2d5b006f","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":12600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-92203d502969bf810290","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":12221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-92af334a81058c115c6d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":21398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-97043d7c0e95c7a9b538","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":16579,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9b061925110794967937","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9b0a261339c941b15ef9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9b4e7d5a9d9be16b81a2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":15056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9f8fe0076ba3960c5ed6","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":10241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a110445f4bb0e5a9249b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a239abd986ca12d3b089","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":10893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a4b590de5fc7b09886b5","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":9999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a5cb67bbd403c122b448","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a944d4b83c40d64ad528","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a9fcd65f05b20919cc7b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12096,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ac9d289deb13e7de0d5b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":13333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ac9dd7137941fa967739","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":21947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-afc588b98fc64a39d3cf","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b1e7b2c2ce671c777b00","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":11561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b47625127ce7c655c09a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":11373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b524c69bb71c565d2b58","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":17634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b65beaa3001a816f6cae","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b6826b78d1ecfa486857","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":13838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b76587fc8ad7db226e8b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-bb1ec5293b3152b029eb","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":10932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-bb31d3b1cdc3a33b4aee","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":18596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-bc218ae35c432f47e3b2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c2ace8fd6a3946f909d1","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c428f095b19e7cf46395","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":20523,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c7722802523210206b72","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c9e3527162de0406d5c1","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":13535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-cbc65211b511edc84eef","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":16031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ccb5da6fbf33b4fc343e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":17352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-cd8b6feff9b29b140db3","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":16899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-cef54b49eb30d934016a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":13180,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d41355c268d0640de0b2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d45d573707423b4333c8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":25108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d6a7c54426412861c898","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":15208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d6dc2c7f4c00079cdea2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-da2efd47495633f62256","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":12565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-db55f0ef1567c8eb8dc9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-dc91d3dc044f44f23f34","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-dd6d3dcd3b2bec3dec99","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-de0da7c7009cd8139681","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-dee80a2bdb8cdeaae997","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-df0cc209a2c7e2be249d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e0e7f3e88e2fe516e148","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":14369,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e1150544251e50df2ef4","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":18228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e1f548ad3eb98feedc9c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":18608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e2b289727fffe1359476","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":11578,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e3bf544a74276372dc76","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":25265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e4aa4620bb993ec7c6b0","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":15730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e4cb394bd3ed4d377f45","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e5368f1856ed3179634b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":20105,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e54846b3978101495d15","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":18816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e627170fb572721ecd2c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":14376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e6683721b86aac6fa89c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":16022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ed316521ba0802cb2f9f","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ed48b466904dfd246b36","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-f37f7f8af59b042bd1fc","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":16551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-f8ce0fccb9088a10ed3b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":15284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-f8d220191366b9f7beef","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-fbcfe7b1efb2c8a34834","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":13348,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-fd8fee043148b3cd8527","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":16012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ffc56bac94bcaaa595e6","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"71f3811ba836bd5d2426-0cef81448f669267012e","project":"chromium","file":"Pages/TestSuite.spec.ts","title":"Test suite tab switching keeps active bundle suite data after stale table suite response","durationMs":8413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"71f3811ba836bd5d2426-89887dbf3e98dfa2e74b","project":"Ingestion","file":"Pages/TestSuite.spec.ts","title":"Logical TestSuite","durationMs":22478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-01d1dce9230b25ea2505","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Metric in recently viewed","durationMs":12607,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-13b7a204ff200c336897","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check SearchIndex in recently viewed","durationMs":12536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-24032ed075b8c41897c3","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Dashboard in recently viewed","durationMs":12968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-2586c2bf4dfb82bef75c","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Store Procedure in recently viewed","durationMs":13371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-2f3fd80ebc9a9ce7ed65","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Container in recently viewed","durationMs":13550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-47c55d1985c5945153c6","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Table in recently viewed","durationMs":14122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-5618482fdd645a26b706","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check ApiEndpoint in recently viewed","durationMs":12458,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-5f1972c128aabaab7ad8","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Pipeline in recently viewed","durationMs":13242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-9421df08f5c6615cda5d","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check MlModel in recently viewed","durationMs":13594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-9929792040eb7c5e6031","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Topic in recently viewed","durationMs":12356,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-f40caac58f9f81e19025","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check DashboardDataModel in recently viewed","durationMs":13208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-083dec8015a3843e7cd2","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify cycle lineage should be handled properly","durationMs":9009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-32f8b0ccd2482bf59ee5","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify multiple non-platform layers can be active simultaneously","durationMs":9641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-420eb75a7ad41f3f161d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"grays out non-traced node-to-node edges when a node is selected","durationMs":10964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-590c0cccca1fd8b28312","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify edit mode with edge operations","durationMs":9427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-6c7e50b5a927cef3105e","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Column-level edge deletion persists across a page refresh","durationMs":10291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-7887942fb4b1a81cf4f2","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify function data in edge drawer","durationMs":27730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-893bf3a839f3d965551a","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"highlights traced node-to-node edges when a node is selected","durationMs":13391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-8cbc1d5f3df767e1a30c","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Node-to-node edge deletion persists across a page refresh","durationMs":13913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-993dfeaec0379736db1d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Node edge tracing state responds to column selection and pane click","durationMs":15493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-a18e7ad071eeb5841602","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"highlights traced column-to-column edges when a column is selected","durationMs":13597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-aaffec18ebc6fd24d065","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"hides non-traced column-to-column edges when a column is selected","durationMs":12244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-af9a6883f6bfe2044127","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify node panel opens on click","durationMs":36593,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"72d52555450cf448e344-bcda310ae42da5f9981d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"grays out node-to-node edges when a column is selected","durationMs":9963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-c817ed50e2845dccca7b","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify node full path is present as breadcrumb in lineage node","durationMs":12425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-d3c613365a48705e9f08","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify edge click opens edge drawer","durationMs":8190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-f060811fb20415a34c46","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify edge delete button in drawer","durationMs":11033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-fd9777143ac55c7ff05d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"hides column-to-column edges when a node is selected","durationMs":12334,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-22575bd0187b55901bec","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should add and accept a requested api endpoint request schema field description","durationMs":22734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-65c54cf0e0efe55e1890","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should edit and accept a suggested table column description","durationMs":23585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-80f4fe7e66749741bb2f","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should decline a suggested container column description","durationMs":22694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-93993cb9c92e1cd67d6b","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should add and accept a requested topic schema field description","durationMs":23159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-be064f2bb0d81c98522c","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should add and accept a requested table description","durationMs":24267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-df608fd0fde9ffb3dcd8","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should edit and accept a suggested api endpoint response schema field description","durationMs":22498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-fa64ee029c7d508dae0f","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should decline a requested api endpoint request schema field description","durationMs":23992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-04adac79fce387536d5a","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should replace focused documentation when a new field is focused","durationMs":8868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-136d19e6f39cd1065416","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render code blocks inside pre > code, not as raw text","durationMs":8222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-67847c8372f8e027537e","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render image in Mssql doc panel","durationMs":7635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-7df729b7f0f4b0f06d1a","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render links that open in a new tab","durationMs":7611,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-8384bb8c4d3d5c6fceed","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should auto-focus service name input and show name docs when entering step 2","durationMs":7879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-858dc1ba7e867d341974","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show service name docs without requirements when service name is focused","durationMs":8835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-a353893f87d30e844b91","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should update panel when a oneOf select field is focused","durationMs":7908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-a8c66091c37ee0517c7b","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show section docs without a field fallback for fields with no markdown docs","durationMs":7956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-aa3c42f2b54ccca226aa","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should copy code block content to clipboard and show copied tooltip","durationMs":7744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-b605c6fbbd9a2fc001d4","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render headings not raw markdown","durationMs":7991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-cb0cb27b27b2eef3e924","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render admonition blocks with correct class","durationMs":8699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-cc58195c92559dedbdad","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show general docs when no field is focused","durationMs":7833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-dfb092691560c4c5f613","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should load the correct doc file for the selected service type","durationMs":7956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-fa45cd6f9878dc6c4cbb","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show field documentation when the corresponding form field is focused","durationMs":8072,"attempts":1,"retries":0,"outcome":"expected"},{"id":"75e196e842ebd82840f4-f9512e6353ddfe34a4a3","project":"search-nightly","file":"Search/SearchNightly.spec.ts","title":"should load global search suggestions for sample data query","durationMs":3899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-0769921c525897eff595","project":"chromium","file":"Features/Container.spec.ts","title":"parent Deleted toggle reveals the deleted grandchild — its actual direct parent","durationMs":3971,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-3913d4f58462a7a3df4e","project":"chromium","file":"Features/Container.spec.ts","title":"Copy column link should have valid URL format","durationMs":13359,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-42b547ec6ff262456209","project":"chromium","file":"Features/Container.spec.ts","title":"should correctly load, display breadcrumbs, and navigate deeply nested containers","durationMs":8165,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-45da7c2e7258e334c204","project":"chromium","file":"Features/Container.spec.ts","title":"Container page children pagination","durationMs":9532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-4f996668155242b716c3","project":"chromium","file":"Features/Container.spec.ts","title":"Container page should show Schema and Children count","durationMs":9966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-6d000f93734bfa3641f4","project":"chromium","file":"Features/Container.spec.ts","title":"Deleted toggle reveals and hides soft-deleted children","durationMs":3884,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-74d2687b81ec34d1df25","project":"chromium","file":"Features/Container.spec.ts","title":"Copy column link button should copy the column URL to clipboard","durationMs":8773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-814af37fb8584f11c87e","project":"chromium","file":"Features/Container.spec.ts","title":"grandparent Deleted toggle returns empty — deleted grandchild does not bubble up","durationMs":5893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-99a5693eb43b1b956e3f","project":"chromium","file":"Features/Container.spec.ts","title":"search + Deleted toggle compose to find soft-deleted children by name","durationMs":5104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-b25813e92d687c1ac664","project":"chromium","file":"Features/Container.spec.ts","title":"auto-collapses the breadcrumb into an overflow menu on a narrow viewport","durationMs":7355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-db68482bfca9911d3811","project":"chromium","file":"Features/Container.spec.ts","title":"expand / collapse should not appear after updating nested fields for container","durationMs":15006,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-dd86738ce9af0c2bd293","project":"chromium","file":"Features/Container.spec.ts","title":"search filters direct children only — sibling subtree never leaks","durationMs":6705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-46773b2126fe5bb8eb31","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create OwnershipUpdate task for Pipeline","durationMs":1009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-4a8117316e1eb5a1d1fa","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create TierUpdate task for Pipeline","durationMs":307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-7fd5240fe33065f768e3","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create and approve pipeline task description update","durationMs":483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-bd22bafa09fe5baaf2c2","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create DomainUpdate task for Pipeline","durationMs":470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-c8dccd6e61c2e9dea7de","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create and approve entity-level description task for Pipeline","durationMs":438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78095862efae8cf216ee-6119e7b35fd37214afd1","project":"Ingestion","file":"Pages/IngestionLogStreamLive.spec.ts","title":"Live logs arrive over SSE while the agent runs, with no polling","durationMs":33157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-07402fbc3d954dac78b8","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"searching for a term shows it and its neighbours","durationMs":2100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-092270212c19cdaa4908","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"unconstrained built-in relations omit endpoint labels","durationMs":1950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-0fd42fa09b4645db923a","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"searching for a non-existent term shows the empty state","durationMs":2437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-11fd427817bd9d655f42","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"cardinality map survives a Data-to-Model round trip","durationMs":2133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-2db29163257de252b256","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"Data mode shows an empty state when the glossary has no assets","durationMs":2085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-37cd6e390ea42415c6e5","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"switching back from Tree to Graph restores the graph and stats","durationMs":2024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-3a301091329822c5d151","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"custom ONE_TO_MANY relation shows \"1\" at source and \"M\" at target","durationMs":1772,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-407235e749dda8ee080a","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"returning to Model mode restores graph controls","durationMs":2176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-4eccf3be34c45254b555","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"all three term nodes have canvas positions","durationMs":2074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-6d49d78bfe49b343cf22","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"Tree surface renders the glossary hierarchy","durationMs":1856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-b03f0a71701825a04fd3","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"stats show 3 terms and 4 relations","durationMs":2189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-bb1c308761249a94185c","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"concept inspector exposes the full-details action","durationMs":2016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-ddb75b6bd2bd20a31525","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"graph edges contain all four expected relation types","durationMs":1982,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-dfd025e99a6dc28bd7b3","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"graph renders without empty or error state","durationMs":2161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-f1f2b8e2b3a7545b4790","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"clicking a node opens the concept inspector","durationMs":1937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-022759ec864b56b71bcc","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Copy domain FQN to clipboard","durationMs":7232,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-0ebd54efbc2b2b155beb","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Add expert to domain via UI","durationMs":10497,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-1f1c563e90bcce9f6d8b","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete data product via UI","durationMs":6582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-2449dd2855d6489495e5","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete domain with assets removes domain from assets","durationMs":5504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-28a3b2486df912d34410","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Clear domain selection returns to All Domains","durationMs":5948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-2a56fa3766116e1c5585","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Add owner to domain via UI","durationMs":11003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-3b3349f8197353baba62","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Add owner to data product via UI","durationMs":9095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-3c0793e4d0a02a034dd6","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Domain description required validation","durationMs":4859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-572e07b57107a81c8a5a","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Domain name validation - special characters","durationMs":4598,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-8257af9327d0aecb1a57","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Navigate from data product to parent domain","durationMs":8122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-94706ce6c0a223ba7d9c","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Select domain from global dropdown filters explore","durationMs":5555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-95eb86ffe8e67da8357f","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Search assets within domain","durationMs":8231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-986797853ac5b5f33e0e","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Navigate from subdomain to parent domain via breadcrumb","durationMs":6677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-a3eec08a270058e9c4a8","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Edit domain style - change icon URL","durationMs":9353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-ac6bba54da09716d0bb1","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete domain with subdomains shows warning","durationMs":8115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-ae62dad6a8513b600bd8","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Remove owner from domain via UI","durationMs":7822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-c792ca79ac2754e7a040","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Rename data product via UI","durationMs":7374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-e665fdbd2e91e08e4f8b","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Rename subdomain via UI","durationMs":8806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-e67dcb1bdd80adb3ef5f","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete subdomain via UI","durationMs":9567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-fe4f73c64fe8c8e5de31","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Domain name validation - max length","durationMs":5076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c313e060173ac894b2b-403f9052a3a13d25ac40","project":"chromium","file":"Flow/AddRoleAndAssignToUser.spec.ts","title":"Verify assigned role to new user","durationMs":6474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c313e060173ac894b2b-cad45ddec1ffc014868e","project":"chromium","file":"Flow/AddRoleAndAssignToUser.spec.ts","title":"Create role","durationMs":6524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c313e060173ac894b2b-ee14ce47b05f65e1ffd4","project":"chromium","file":"Flow/AddRoleAndAssignToUser.spec.ts","title":"Create new user and assign new role to him","durationMs":7830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-5d577d037f46e4e6ac12","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should render connector forms that previously stalled at loading","durationMs":13651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-bff0435e79efac0348cc","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should scroll the form when the wheel is over the blank margin beside it","durationMs":7903,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-d2f910cd545265e60c99","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should clear inactive Snowflake auth fields before test connection and unlock ingestion filters","durationMs":13034,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-d9a6d1d97ea16fafc5c8","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should align nested sample data storage config fields without overlap","durationMs":10784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-00c5931044e86cac81ab","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should accept a valid name with allowed special characters","durationMs":4817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0198f50c773eac76637b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for mlmodel in right panel","durationMs":12134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-046fb43e97de2c99aded","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on mlmodel","durationMs":19379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0586bf3c032e2e35530a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for table in right panel","durationMs":7936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-06fcc5757ec84237d9d4","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on pipeline","durationMs":15185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-073ad5c7df0d928319e5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Markdown","durationMs":17339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-090b772ba3caf2d12879","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-099f20268d1f7b48745e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on dashboard","durationMs":23574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0b461a5e0578cd2efd31","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on container","durationMs":14267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0cb4d8f7a9199c942503","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for dashboardDataModel in right panel","durationMs":12597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0cc0177e680651493e9b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on database","durationMs":17626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0d1c5ed8b0999aa6e657","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time Interval","durationMs":18044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0d1e7593a663f34a4167","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Duration","durationMs":16911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0dbdcff683eb513dc0f5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should accept valid http and https URLs","durationMs":7103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0ede02e520a7dc955605","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Number","durationMs":17816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-11f7e608c623dfca5f06","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for topic in right panel","durationMs":12606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-13131035a68d36358766","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a tilde","durationMs":5461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-13c94bba599eb95dce34","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Timestamp","durationMs":17863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-13e7ba4bc2cad9b1de63","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for storedProcedure in right panel","durationMs":10388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-144b42f1d0bcd87467bb","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for chart in right panel","durationMs":9141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-150a7f419a6502d5f7af","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on glossaryTerm","durationMs":19093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1542edf5a447db147b2c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Create custom property and configure search for Pipeline","durationMs":20639,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1661fababed9adc53f9d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for container in right panel","durationMs":9060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-16aa58907a6fdfcaf258","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a colon","durationMs":5137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1928de880af6bb1217b1","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":16864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1b3f3bdd4a95d12e5782","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Email CP with all operators","durationMs":30254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-20ec70d5fe0c22fab8a3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should display URL when no display text is provided","durationMs":6687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-215123aafd70cf8361ec","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for searchIndex in right panel","durationMs":11074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-22c1d84db9283bdded31","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for topic in right panel","durationMs":12163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-234372fa7573d8422663","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for glossaryTerm in right panel","durationMs":10466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-24855e52e738b6d8cc55","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Duration: advanced search equalTo and Contains operators","durationMs":13306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2666fae5eaf8b524f8b2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for apiEndpoint in right panel","durationMs":12862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-26a002b822c0a4f22189","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a backslash","durationMs":5375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-284272a57881394530a8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for chart in right panel","durationMs":9679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b3f1ca73d2b19cd7829","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Integer CP with all operators","durationMs":32391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b44204ae297960da4ca","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for apiEndpoint in right panel","durationMs":14385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b958f7c7ead420a53cf","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set string custom property on column and verify in UI","durationMs":15721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b9e2f2bf4b05988942e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Integer","durationMs":17143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2dc55bac67402b99ea1c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-33ead8586aacbd1e7514","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String CP with all operators","durationMs":33357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-36c2e3f98f9691386383","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Number CP between operator sends gte/lte bounds (Issue #27482)","durationMs":29044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-38c5b4f50e470a21dec5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"DateTime CP with all operators","durationMs":36493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-39ca4bac99e8c38f4893","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name exceeds 256 characters","durationMs":5038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3af16c42b7e43de3610a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for databaseSchema in right panel","durationMs":9305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3cd6204cfd0c101ede1b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a caret","durationMs":5055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3e66b795beaabcfc4e18","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should accept a valid name starting with a letter","durationMs":5376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3fc0be82527ff18dbf4d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for container in right panel","durationMs":9081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3fe3da753570171b89f8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference CP with all operators","durationMs":35260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3febd7d88ddcf14f9d74","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for chart in right panel","durationMs":9175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4337412e95b645514b11","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for storedProcedure in right panel","durationMs":10543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-443430595829177dc49b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":20171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4440d5c29ebf7b879e13","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a less-than sign","durationMs":5574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-44413c5a1543a1f5a65d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show No Data placeholder when hyperlink has no value","durationMs":5169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4448b5bfa30f03224bd5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for apiCollection in right panel","durationMs":9716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-47b51888cdfc4692d610","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15929,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4827e24fda5a1d45d22f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Hyperlink CP with operators","durationMs":56863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-48a4ae191a789b00d2b2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on apiCollection","durationMs":14923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4b507b63d20449a81643","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a double quote","durationMs":4910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4c6f5910036e8a8ecd06","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table CP - Role column with all operators","durationMs":32441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4c7f9c476c2ed0007bee","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for dashboard in right panel","durationMs":6636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-5134cc15da4d82e27660","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for searchIndex in right panel","durationMs":9909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-52d82632ab1dbfb46acb","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Create custom property and configure search for Dashboard","durationMs":27685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-53e6f09a5c52bf7df3ef","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for metric in right panel","durationMs":9901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-55e07b0e789c9713f0e1","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for container in right panel","durationMs":9717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-578a14db66c772d9f19a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time Interval CP with operators","durationMs":56527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-5b8fbffd20b99a05b306","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for dataProduct in right panel","durationMs":14280,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-5ec7d3ce5e4c562daa12","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for dashboard in right panel","durationMs":6992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-631d2b822a425a37f1ad","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"sqlQuery shows scrollable CodeMirror container and no expand toggle","durationMs":14777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-65307a93e05183f89aea","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for metric in right panel","durationMs":10258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-656cc7d8ddbc7c49d430","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time CP with all operators","durationMs":24103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6655b40bd42bf7dd92cf","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for dashboardDataModel in right panel","durationMs":12555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-68023ece76e3b9d66801","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"no duplicate card after update","durationMs":23695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6822a41e8f427108e34d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for apiCollection in right panel","durationMs":10429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6d9247cb6f905ac30d36","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for dataProduct in right panel","durationMs":13876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6e0b510a4357a92405ad","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":24298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6e2dcbfa65968e44a7c7","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on dataProduct","durationMs":18973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6f453e86d7a1c3ac71e3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference","durationMs":21176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-706fba167c2158a9f19c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for table in right panel","durationMs":8949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-74f1413fcd08c3e9eea9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for searchIndex in right panel","durationMs":10050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-758a3345517b4a31f72f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for pipeline in right panel","durationMs":10511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-75b13a66cc9bb065087a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for database in right panel","durationMs":12140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-78380c7e57ee93066467","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains an asterisk","durationMs":5530,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7841102043c30e3f1f34","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Enum","durationMs":18816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7b91914a9fad1814c71e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Enum: Set Value, Verify, Remove Value","durationMs":8306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7cc62919e3b9e1b62694","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for pipeline in right panel","durationMs":9734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7d2ecf1e1524a2e1892d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on storedProcedure","durationMs":17277,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7d3bdab21816548f036f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Date CP with all operators","durationMs":34596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7d916dac346243f25b87","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for topic in right panel","durationMs":12776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8008a10e168b1c34bc42","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Number CP with all operators","durationMs":27768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8206d4dac7f2ead1c59c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for searchIndex in right panel","durationMs":10641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8465025d34d1ba303095","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for storedProcedure in right panel","durationMs":10387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-85d2000be90731f68ff3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"User visible in right panel when added as entityReferenceList custom property","durationMs":7581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-86a58b48381d1d8e95d3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":20787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-87e8c056c3709eb4e491","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for glossaryTerm in right panel","durationMs":10176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-880378d44be14f2a0d8b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on dashboardDataModel","durationMs":19979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-88b29e301c7885391aba","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8afc594c33cf95e66ff6","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for dataProduct in right panel","durationMs":13545,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8ef70bdc69877ccd56cc","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for table in right panel","durationMs":8201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-918132860676bf7ef176","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for metric in right panel","durationMs":10677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9188e4d6124f320a46a9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for databaseSchema in right panel","durationMs":7992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-925b2a5ddef6f183d467","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"table-cp shows row count, scrollable container, no expand toggle","durationMs":9978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-92e66352c532d1282ab5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for dashboardDataModel in right panel","durationMs":14158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9543959e2b5605de9ea8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Date","durationMs":12949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-95da432fd800c29682ce","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9642fc35ba00455535b1","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for apiEndpoint in right panel","durationMs":12984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-97e0f312e86c2b042db8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-98578f04c3c4935811d2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on topic","durationMs":19838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-98c8415db3b1f4ca0569","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for database in right panel","durationMs":12129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9a7507dc2536c9b96f53","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a greater-than sign","durationMs":5533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9c0b89b0755adc0f5919","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":14175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a2d9c2586f84fe5251aa","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a dollar sign","durationMs":5124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a4e24951e57deeb9ee69","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference List","durationMs":20329,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a55f86c4ec59405c15b9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"entityReferenceList shows item count, scrollable list, no expand toggle","durationMs":14661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a733d29eb95f348d8d7f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for apiEndpoint in right panel","durationMs":14273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a77692b01e6eca70c785","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set all CP types and update representative properties on table","durationMs":35155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-aba34920bf0b82ae95bb","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for dashboardDataModel in right panel","durationMs":13101,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b1308b8a516b8cb9ebf8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Verify Pipeline custom property persists in search settings","durationMs":5776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b1b39433ec030281258b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":16734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b29df081605055efcf39","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b3388fdecc2ad8d1a917","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name starts with a non-alphanumeric character","durationMs":5560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b3574c7e673e7661e1d0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table","durationMs":20319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b42635480458c69c0058","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for databaseSchema in right panel","durationMs":9103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b49c14b444b41ef871c0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":16915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b4fe5b76badf6f07556f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for dataProduct in right panel","durationMs":13796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b55d69150fb57f8ebf3d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for table in right panel","durationMs":10049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b5a3c351a5994c7468ba","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for pipeline in right panel","durationMs":9961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b89bfd43a8bfc7e51b34","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table CP - Name column with all operators","durationMs":33385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b8bf915ba142ddcac4c0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-bd447013e59274885103","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for mlmodel in right panel","durationMs":13787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c00429d0241747787024","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on chart","durationMs":13630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c2a6e896d6c984cc6a55","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Enum CP with all operators","durationMs":33812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c5145b1f6116551c054a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for dashboard in right panel","durationMs":7284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c8cd0c7b62f24c8bf605","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for pipeline in right panel","durationMs":10103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c8f4fdafd8c406812655","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on searchIndex","durationMs":17355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ccbbec56928c924a0364","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a forward slash","durationMs":5677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-cd5c20bf0878e3ddfb88","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains an ampersand","durationMs":5638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-cfb9e8e45a2cf6f8edba","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for databaseSchema in right panel","durationMs":8931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d1f1d6682c54f0eee731","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for dashboard in right panel","durationMs":6582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d367410a3d276e768f1e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Sql Query","durationMs":16349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d3690b8817694bcb83b7","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Email","durationMs":17619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d404277b926d9d8d2069","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for chart in right panel","durationMs":9357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d47e27129966726f7534","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for glossaryTerm in right panel","durationMs":10833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d65630934d80acbe62cd","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Duration CP with all operators","durationMs":26247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d7e8ad039d71e8a7c572","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for topic in right panel","durationMs":12338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d93a7140bf1bd5bdd8d8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for database in right panel","durationMs":11609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-dae6e741e568b0557027","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for mlmodel in right panel","durationMs":13004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-dbc2b32a754a0f964545","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on apiEndpoint","durationMs":17523,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-df87952db325e9d6d907","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String CP with numeric-like string value","durationMs":30536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e4ba59ec229c66902e0d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":18342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e694ff42b3b887567bfd","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for apiCollection in right panel","durationMs":9829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e769b190aa8fb84b45e4","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Date Time","durationMs":17172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e84c3c0137f1039e28c2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for glossaryTerm in right panel","durationMs":10035,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e8ad632e57cd4726f62e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference List CP with all operators","durationMs":37156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e8bc3c66a99f793df1d8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for database in right panel","durationMs":12061,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e8fdc4505ec39607a36d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Markdown CP with all operators","durationMs":25043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ea562b6d00e8518d2137","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Timestamp CP with all operators","durationMs":22773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ea89b0ef843ab4311f58","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":21027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-eb0bd2320ea66fd86706","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on metric","durationMs":16288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ef476d3b4603c8a4381c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for metric in right panel","durationMs":9266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f079a72c9858cbf038d7","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on databaseSchema","durationMs":16830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f206353a5c99d247c672","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for storedProcedure in right panel","durationMs":10654,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f24f565618b6ef1ce3bd","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Verify Dashboard custom property persists in search settings","durationMs":3289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f3634eddf4aeb8ede7a5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"SQL Query CP with all operators","durationMs":20114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f3d24db98506074025a9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table CP - Sr No column with all operators","durationMs":31309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f4100ee1ffe0946ec7f0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for mlmodel in right panel","durationMs":12107,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f49b660fff35024b8100","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should reject javascript: protocol URLs for XSS protection","durationMs":6753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f5a397a6f934257987e4","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":20313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f5a8dbb1a3170bea745a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time","durationMs":19367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f6475c472a261574fcb0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for apiCollection in right panel","durationMs":10470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f9f2a10de961b60567fa","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Hyperlink","durationMs":19777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-fad45bcbe2162604d3b9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for container in right panel","durationMs":9089,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-fb579170cd1d7c4a289a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-174101936d3896ce9f47","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should add multiple different target terms in a single save","durationMs":8737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-21c26aaf5eca59e26cc8","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should delete a specific relation while keeping others","durationMs":9285,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-347289cdde81b2e86c77","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should add three relations to a single term and persist all after reload","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-471da3990b61252d964c","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should edit the relation type of an existing related term","durationMs":8938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-99084aaab07cdc368d6b","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should reveal the related terms hidden behind the overflow toggle","durationMs":11803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-ac6e5f3ff65f304cd641","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should add Related To, Narrower, and Has Part to the same target term and persist all after reload","durationMs":12821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-0b22ed09f9439ea8c7ff","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"search for child term name + apply non-matching status filter shows no results","durationMs":7919,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-234737f04928d20473b5","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"expand all button loads all terms","durationMs":8060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-27e6f44e8b15f854d098","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"apply filter, expand parent, verify children shown","durationMs":6580,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-466fc3ab5bfc5a841ed3","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"all children have same status different from parent","durationMs":7881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-4f00a63e0200f02e1523","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"search for child term name + matching status shows child","durationMs":6788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-57f0b473b90da6940065","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"expanding grandparent shows parent with any status","durationMs":8308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-79bfb46ac41aa25bf7bf","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"clearing status filter maintains search results","durationMs":8325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-8db8c485b9ff1b220d60","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"search for parent term name with child status filter shows no results","durationMs":6483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-a3ffe4e7ef370a9818c2","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter shows parent when status matches and all children on expand","durationMs":8761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-ac556f0de995587cfa8f","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"clearing search maintains status filter","durationMs":6942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-ae74ac03d84aac90be70","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by parent status shows parent and allows expansion to see children","durationMs":7700,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-b99d3ceddec644ada565","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"multiple status filter shows terms matching any selected status","durationMs":7023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-c2facc4c319dc59d5305","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by grandparent status shows only approved terms","durationMs":6883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-de1c9c9f19f09f7f3f74","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"only leaf nodes match filter - parent chain does not","durationMs":6404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-ed1a87cd827864150908","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"change filter while expanded updates visible root terms","durationMs":7331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7f83f47ccb329ee308eb-2d5871a8c22b587d7bc9","project":"chromium","file":"Flow/ApiDocs.spec.ts","title":"API docs should work properly","durationMs":10004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7fe377069ec905157f69-c57732e5a453d5d11e48","project":"chromium","file":"Features/EntityRightCollapsablePanel.spec.ts","title":"Show and Hide Right Collapsable Panel","durationMs":7535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8353b5bd378f555885cd-ced9991ca1236b535306","project":"chromium","file":"Flow/ApiCollection.spec.ts","title":"Verify Owner Propagation: owner should be propagated to the API Collection's API Endpoint","durationMs":39737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"83b398fa84d933d87686-04e325d8cc12eba5e53e","project":"Basic","file":"Pages/LoginConfiguration.spec.ts","title":"reset login configuration should work","durationMs":3745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"83b398fa84d933d87686-1a9e5feffef3d3445b26","project":"Basic","file":"Pages/LoginConfiguration.spec.ts","title":"update login configuration should work","durationMs":6197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"84796481a57bc647802f-242f17fe293eed0e4f58","project":"chromium","file":"Features/Glossary/GlossaryInheritedReviewerApproval.spec.ts","title":"term inherits reviewer added to the glossary after an earlier term ran the workflow","durationMs":13230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"84796481a57bc647802f-37f3e60b3e7ddf0777cb","project":"chromium","file":"Features/Glossary/GlossaryInheritedReviewerApproval.spec.ts","title":"inherited reviewer is shown on the term page and it is not left in Draft","durationMs":6717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"848329c182e7112e80ae-9df4121368d3676326e8","project":"chromium","file":"Flow/PersonaDeletionUserProfile.spec.ts","title":"User profile loads correctly before and after persona deletion","durationMs":10859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-21870b80ea06c6c61080","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should be able to select multiple terms for bulk operations","durationMs":12342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-69563df3d8d1bd29ecc4","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should prevent dragging parent to its own child","durationMs":12459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-791826c9cc34ae77ae2a","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should be able to toggle mutually exclusive setting","durationMs":12188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-a3e7717d96e1c52463d5","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should navigate to bulk edit page when clicking bulk edit button","durationMs":13449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-1845d01e7ccdda0095af","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"renders the stale cache-state badge","durationMs":3032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-533404d5aa35173d9319","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"caps max assets at the backend maximum of 1000","durationMs":4528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-700160c385a041b6b4c9","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"renders the failed cache-state badge","durationMs":3090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-98777200bcc547a3549c","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"rule card shows the condition count for a multi-condition filter","durationMs":3513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-a3f208ae7d0498a397c3","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"surfaces the persisted generation error on the settings card","durationMs":4636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-aa7a9fec272b5dd4104b","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"rule card shows the all-entities state when no filter is set","durationMs":3429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-39e2d4210de3a6aee51c","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should show term count in glossary listing","durationMs":8222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-51c90aa3d3cbd50f7c3d","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should expand and collapse all terms","durationMs":23499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-5ce50f557be26da6421c","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle large number of glossary terms with pagination","durationMs":13026,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-66452f74ee29979cc6d3","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle large number of glossary child term with pagination","durationMs":25945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-c321395812e83839cd55","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should maintain scroll position when loading more terms","durationMs":9601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-c75ef376e0e3aeac99e7","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle drag and drop for term reordering","durationMs":20518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-dfd827b0183ea271ab84","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should search and filter glossary terms","durationMs":12307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-f609aa3b78d2f65881fd","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should expand individual terms","durationMs":9758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-fd6356c420635592f5ea","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle status filtering","durationMs":9234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-140cb435ed84863f3897","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Alert operations for a user with and without permissions","durationMs":64459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-517df8c4e105fea3132d","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Data Contract Name filter lists matching data contracts","durationMs":7074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-8c8069db90344336e8b3","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Test Suite alert","durationMs":25083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-918aa5763e716d122442","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Test case alert","durationMs":32355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-b916a573700fed09d859","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Table alert","durationMs":21605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-c2cb524aacc68f08f74d","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"delivers table schema changes to an external webhook","durationMs":34252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-e080c3944816b4fb8c10","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Pipeline Alert","durationMs":37873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-f843143498ffba623720","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Ingestion Pipeline alert","durationMs":26064,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-05d6b12140e7b158a71e","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should reset pagination when filters change","durationMs":8988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-0a10b0e44065fb8502c3","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should filter test definitions with single-select filters","durationMs":9743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-2f0ed50d9a397315fe21","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should handle filter UI interactions correctly","durationMs":8279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-4537e6e3d565f4a5c602","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should handle multiple filter operations","durationMs":10608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-6220e7b1bc4fccbd3504","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should restore and persist filters from URL","durationMs":15236,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-6cfa09b12a7300edb68f","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should not revert to previous value when changing filter selection","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-8e7b0ff4ff1be00a6fd0","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should make correct API calls and show filtered results","durationMs":7888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-024f722ac50dd9817b74","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"DataProduct - Certification assign, update, and remove","durationMs":11753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-049fb397dbc7f673f76b","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Edit buttons not visible on Domain","durationMs":7758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-8e0b212ecad90a923a5f","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Domain - UpVote and DownVote","durationMs":8393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-c6fcf77553a572dac672","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"DataProduct - UpVote and DownVote","durationMs":6996,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-c82d83f43577ab6478e0","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Domain - Certification assign, update, and remove","durationMs":11729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-d89f229dce3bfd3c5897","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"DataProduct - Tier assign, update, and remove","durationMs":10230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-fd03e39a19b2a7270353","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Edit buttons not visible on DataProduct","durationMs":6549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-fec525a76b0cc14929bb","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Domain - Tier assign, update, and remove","durationMs":10425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"881e65180b3903b61009-329957068f1e26fcddaa","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":23301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"881e65180b3903b61009-b5eebb5ec29f3085052a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":23152,"attempts":1,"retries":0,"outcome":"expected"},{"id":"886b17c78623def558cb-655d3f46261756c6406e","project":"chromium","file":"Features/Tasks/TaskCustomFormWorkflow.spec.ts","title":"renders and resolves a workflow-driven custom task end to end","durationMs":15181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"88aed568d27816e1e7bc-df00a43a3c43019be57b","project":"Ingestion","file":"Flow/ApiServiceRest.spec.ts","title":"add update and delete api service type REST","durationMs":10879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-0dc418f1c23a4844a197","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should add asset via Add Assets dropdown button","durationMs":18038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-28906e2384c9a1bab9f6","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should search within assets tab","durationMs":12574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-4a7e377e96c978147e0a","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should add pipeline asset to glossary term","durationMs":17198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-61b40f6d4808b291d05e","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should add topic asset to glossary term","durationMs":16823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-96fa4ed1ffebaddf928d","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should remove glossary term tag from entity page","durationMs":10305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-9f29d348a57a79cc841b","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should bulk select and remove multiple assets","durationMs":14441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-b0bdefe972c5bed0bcca","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should paginate through assets","durationMs":15465,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-b1f3d6ed1b08d1a4bb24","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should filter assets by entity type","durationMs":12943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-cc69574004082d93a6c5","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should remove asset from glossary term","durationMs":15573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-d3d22f75cff0fb556b4b","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should open summary panel when clicking asset card","durationMs":11929,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-01b2b9560e74a71c4e80","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for topic","durationMs":11806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-01b32310e41f5a980287","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for databaseSchema","durationMs":8122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-01fb2e8333263723922b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for pipeline","durationMs":14958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-021b43b75a663324a24f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for searchIndex","durationMs":7592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-04c9500a66e07a0f4d19","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for mlmodel","durationMs":6320,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-075ca5b3b707726c1fed","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for container","durationMs":10042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-08f3053810bc0d9eabc9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Data Quality tab should show permission placeholder for ViewBasic-only user in column detail panel","durationMs":9311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-098503b11056d698e6d5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for topic","durationMs":7074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-09e1f1bd7ce4581c08be","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for searchIndex","durationMs":21435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0b0f6011525649c413ca","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for topic","durationMs":8819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0b717bcb08d7229c39ed","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for dashboard","durationMs":8563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0cb8b557b5588a3a58fb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for container","durationMs":7024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0d014fe4158d6b11b3cc","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for topic","durationMs":7757,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-108197f2ea7989151511","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show lineage connections created via API in the lineage tab","durationMs":10262,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-10b1487c0530097575fe","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for table","durationMs":10449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-11009753c55f5981d8ac","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should add multiple tags simultaneously","durationMs":12090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1239865fabbb2f7594c2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for database","durationMs":6140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-12b33b3886ab0aba320a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for database","durationMs":9833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-133d2e4520c8ec06a4f8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for mlmodel","durationMs":7087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-13567b059282c60d0137","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for table","durationMs":11112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-13de2cfc701692d2a9ea","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for dashboard","durationMs":11252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-13e86c10ca16df0499a1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for dashboardDataModel","durationMs":11461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-14d4eb746eba76f718ca","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for topic","durationMs":7923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1538d123f2c2a8811c53","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless searchIndex","durationMs":8831,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1563e5297bd085a588eb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no tier assigned","durationMs":7647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1585959eee57db3c7549","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for topic","durationMs":9629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-186ced8275acfdbf9e0d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for dashboard","durationMs":7416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-18ba5f44c0099f79d0a3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless databaseSchema","durationMs":7898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-19a477c372c716a9b39e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for container","durationMs":7418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b2b323f53e816de1c91","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for searchIndex","durationMs":9159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b34f2684127b3d55c88","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for pipeline","durationMs":6473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b365f5b11a18b0c3a39","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for table","durationMs":8820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b60622e03798838715f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for topic","durationMs":7959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1cca72e08823914fe23d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for dashboardDataModel","durationMs":72291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1e2b0ffad049bc59c8d0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show lineage not found when no lineage exists","durationMs":8955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-210dadbfa945990935c3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for database","durationMs":11241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-244b13ccd0f7b900fb28","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for container","durationMs":7068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-24c9ce8ce0dabd0d509c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for searchIndex","durationMs":7407,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-25d41d54b9b04a45678b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for database","durationMs":39097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-265891ba968cefecc439","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for table","durationMs":12780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2678b9d0b7d021634922","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no domain assigned","durationMs":6492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2a1b4bcab0fcc6c2ce4a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for container","durationMs":6574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2a4c2dca654df7df1006","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for container","durationMs":20042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2d3f1768f2cb5afafa65","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for dashboardDataModel","durationMs":31124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2e6e45b67faa36697299","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for dashboard","durationMs":8204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2fc3809a0d019d09cae9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for database","durationMs":7459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-30ea32e8028fb027e06a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show incidents tab content and verify incident details when a failed test case exists","durationMs":8510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3165aa7bde7820a3795c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no glossary terms assigned","durationMs":6358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-32005e753a77f02e59b8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should update panel content when switching between entities","durationMs":17403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-336bac00f4185cc63b6f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for databaseSchema","durationMs":10446,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-33c5fbe2f0d2d2b46928","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for table","durationMs":8497,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3462732720adea629df6","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for mlmodel","durationMs":11999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3563f62190ac2b1c45b1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for databaseSchema","durationMs":6780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3686e6b7490be9179d9d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for container","durationMs":10679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-36938a136687ea4b0aca","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no tags assigned","durationMs":6002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-379ca13bb8e867f09013","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for table","durationMs":14347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-38405a0dff0a4e15c280","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for dashboardDataModel","durationMs":12955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3a90fe95b59eae1daa7a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for database","durationMs":8321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3afc31365a9afae9a2b2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for container","durationMs":9252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3bd8882671b45f246ae3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for pipeline","durationMs":7233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3bec1cf9f34fbf374128","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for database","durationMs":8570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3d138dec7cdb5adc679a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for dashboardDataModel","durationMs":11737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3e934042c6730b3de1ce","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for database","durationMs":9224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3ec0933dab0a3b371888","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for table","durationMs":18042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3f76b3e13a73d4472bf3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for container","durationMs":9461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4043f9e1c36ea0ea6a60","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for container","durationMs":9756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-429f7a20fda2da1e9bbb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for searchIndex","durationMs":7717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-42f94f41e925d9ccfe5b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for searchIndex","durationMs":9387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-43e1553306030ed869f5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for table","durationMs":60946,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-473216426419bf5f9a0f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for topic","durationMs":7536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4880722314bd7f82cdfb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for databaseSchema","durationMs":9614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-48fc388a6c2a2863b1f1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for container","durationMs":10277,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-499f0373baa46d13eaa4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for topic","durationMs":8268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-49e28f6489c7e97ea574","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for dashboardDataModel","durationMs":9509,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4a62b223c60b06477ffb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for table","durationMs":8840,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4b303bd077ac40ef58a2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for pipeline","durationMs":11328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4d7466661908a3d14775","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for dashboardDataModel","durationMs":8208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4db7926c584af28e377e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display incidents tab for table","durationMs":9893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4ee18c4acfd795b9804a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for dashboard","durationMs":9272,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5233209655e60c3a8994","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for topic","durationMs":13860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5292139b2be76c19f5f9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for pipeline","durationMs":6855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-530577a1b9881140aa0b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for databaseSchema","durationMs":10670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-54c8de9b6bc6f04c9f93","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for pipeline","durationMs":6945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-564cf22c841556fb5bfb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for mlmodel","durationMs":10293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-56c2bf919a99f01eaed5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for databaseSchema","durationMs":6490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-57573d1765bdeaa7dd3f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for dashboardDataModel","durationMs":10550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-58a5555b60b70ce5d6b7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for container","durationMs":10266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-59aec5b13e4c7fd0035f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for table","durationMs":10099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5a4c679cefbe0fd7a08f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for searchIndex","durationMs":11248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5bf2dc1bad8025064534","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for dashboard","durationMs":20912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5d117c59ba118aee6ec5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for topic","durationMs":8803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5d3b2212dda5295f2c25","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for searchIndex","durationMs":8810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5fefb66da2175223e06a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for dashboardDataModel","durationMs":10257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5ff2addc90e11b5b1429","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for database","durationMs":5804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-62eb3a55c6a5df575ff2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for pipeline","durationMs":8694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6473eb373e9b0fb070e0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for topic","durationMs":7510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-656d7787e6bd7e9df922","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for searchIndex","durationMs":11355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-663bba2a53845b8ea55b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for topic","durationMs":51962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-685ed0fc7776cf71b618","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for pipeline","durationMs":8182,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-692888610a61ccdff209","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for dashboardDataModel","durationMs":9861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6970a240acfb0e1d8b51","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify empty state when no test cases for table","durationMs":6391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6d0142300f3217f0e21c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for pipeline","durationMs":9916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6d9d673d723e25f12f7e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for container","durationMs":9137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6ecc15f9f9ba3f23f44a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for mlmodel","durationMs":10261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6f44900a3c4281198d6f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for database","durationMs":9536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7219436bbdd76d7279fe","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for database","durationMs":13466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-727e88a336b4ec778ffc","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for databaseSchema","durationMs":7008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-737a0f1778b15fc44600","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for table","durationMs":10823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-73cb8c486fbda270c14f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for topic","durationMs":8594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-742072c30dbb99bd0484","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for topic","durationMs":14922,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-768ccc8bc120323d821b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for mlmodel","durationMs":7075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-798159f734b0c332a42b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for mlmodel","durationMs":9628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-79e4216446a38640e9a1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless dashboardDataModel","durationMs":8353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7d9f4e48e9dcfe591dce","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for searchIndex","durationMs":9366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7dd33f8b24d0f71db45d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for table","durationMs":11853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7dd365bcb6c0d8f3c1dd","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for mlmodel","durationMs":9211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7e0095dfd25254c7f75f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should search and filter test cases in Data Quality tab","durationMs":10901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7ea3408a9784bedb27b5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for container","durationMs":8245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7eda860aa3972132c9dd","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for databaseSchema","durationMs":13262,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-83db68eb1c852d7ff609","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for mlmodel","durationMs":9848,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-846a0cefdd1305f9ed1f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for searchIndex","durationMs":7185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-84e1e82f8a7d650659ef","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for database","durationMs":13302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-867ab86eaca612a373f5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for database","durationMs":11452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-870a0dd2d3a32a952a61","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to data quality and verify tab structure for table","durationMs":10778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-88258c610239b8cb1322","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless mlmodel","durationMs":8377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-88c53fddc30f751fa124","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for dashboard","durationMs":11594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-894ae9960c4b6b84a946","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for databaseSchema","durationMs":7077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8956232c87a9e10cb734","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for topic","durationMs":8814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8ad72141d07f120d17f3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for searchIndex","durationMs":7858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8c027a0666e7c0718c7b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show no test cases message when data quality tab is empty","durationMs":7289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8c0f36ededad10ee0c0c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for databaseSchema","durationMs":13239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8d8ab167de121658e7e7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for topic","durationMs":7153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8e0c627d31aa7c2e7e7c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for topic","durationMs":9327,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-930c4957721075839350","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for database","durationMs":9549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-93f9949605954467bc13","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless container","durationMs":6553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-94b895bd39cbeecbf478","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for pipeline","durationMs":5524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9754cdab78f1f70cba04","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for mlmodel","durationMs":8009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-97f0ce9aaeb905d35f7e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for dashboard","durationMs":7196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-98de6578045812df76c9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for mlmodel","durationMs":6400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-99839712f24fb735f384","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for dashboardDataModel","durationMs":9056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9994533a4719723b9d4b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for searchIndex","durationMs":45322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-99bb36c88847f6d6f3b1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT allow Data Consumer to edit owners when entity has owner","durationMs":19172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9a4b9416d84f1f23c897","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for database","durationMs":8221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9b25a468e966bd069a74","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for table","durationMs":7770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9fa9aacf3b07fb05ba7d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for dashboardDataModel","durationMs":9341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a0841d6bc1c9f097bda0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for searchIndex","durationMs":7436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a201f5c4eb58c110901e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for mlmodel","durationMs":12993,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a229c05471eda8fa1d5f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for table","durationMs":9231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a31a06cd87f69b9df866","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for mlmodel","durationMs":7749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a58f95651ebdd39a4baf","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should not make forbidden API calls when ViewBasic-only user opens column detail panel","durationMs":11501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a5f2ecf8b4476450c4db","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for dashboard","durationMs":11006,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a671dc22f0967afe3bb3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for table","durationMs":12089,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a744c11227116d506e78","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for databaseSchema","durationMs":10178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a7514af88554d985d47e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for pipeline","durationMs":180524,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"8b186e385bbdb2574005-a7c023e88c4f118f6f02","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for databaseSchema","durationMs":37131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a8514f3a07691b47119f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for databaseSchema","durationMs":13482,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a96ef28811ef2178b45a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for dashboardDataModel","durationMs":10183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a99d3370ba468f21cab1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for container","durationMs":7531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-aa1561bf1073bcc3c435","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for database","durationMs":11752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-aad46b378dfde5d87619","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for searchIndex","durationMs":8354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-acd8015ef4305973bce6","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for searchIndex","durationMs":11321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ae0d88c8e231ab65349f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for table","durationMs":16171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ae56396e3657654ed95a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for pipeline","durationMs":9314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-afc78822b98d1c640ea5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for searchIndex","durationMs":10242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b0181c53477b65c05d35","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for mlmodel","durationMs":6398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b0cd45603d85986f08c7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for container","durationMs":8507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b15a31f4e5af43faba7c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for container","durationMs":7255,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b43a981d6c7c7d843812","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for mlmodel","durationMs":50474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b5a9ed0234ef1e52bc52","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for mlmodel","durationMs":7789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b8d5ea42f6a6b6f8535b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for topic","durationMs":10313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b98a58764e43cdd18b86","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless topic","durationMs":6836,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ba47593ab31c61081912","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for dashboard","durationMs":9634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-bd02f0788f67382d3e11","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for pipeline","durationMs":9255,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-bd0ba1f1db8e8ebaba73","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless table","durationMs":9647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-bff139f834dd62f12ca0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for mlmodel","durationMs":15701,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c0ae5ab7d970d296c1c8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for pipeline","durationMs":10401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c263c93a44e29c3e55e4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no owners assigned","durationMs":8376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c36f059d2c6d8059e39f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for searchIndex","durationMs":10246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c38d013f1592751af7e8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for table","durationMs":11132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c441e734d3b80c96fbd8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for database","durationMs":12850,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c45af9ddb6911f2c8c08","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for dashboardDataModel","durationMs":8602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c666d823b842348f9a68","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for container","durationMs":8635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c6b66ba86aa55c55c210","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for searchIndex","durationMs":8636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c6b8adb0e10a3fb5bded","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for dashboardDataModel","durationMs":9287,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c6d8cc4def9c9829081e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for dashboard","durationMs":9688,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c70c7ab1e9b13167250c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for searchIndex","durationMs":7342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c8767c2bb584879cd982","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless pipeline","durationMs":8390,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c9724a2b13445c4d6a92","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for dashboard","durationMs":7814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ca5bb991ac4fd8652e2d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for dashboardDataModel","durationMs":10156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cc4f5e3a70eaab5107d0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for pipeline","durationMs":14667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cdc74314b0b746849d53","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for searchIndex","durationMs":7988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ce9287a9a94ad35fa4f7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for pipeline","durationMs":8582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cf77fd2cc064e138e21d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for container","durationMs":8800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cf880f1b73444ae5e7dc","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for dashboard","durationMs":52634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d24b82b38fba9393a77f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for pipeline","durationMs":7069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d3313262932f8e5c26e7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for table","durationMs":13267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d423c43dd26c1009523d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display stat cards and filterable test case cards when runs exist","durationMs":7764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d42c7dfcafd0c3d20840","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for dashboard","durationMs":12224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d63bb39fad8fff480982","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for pipeline","durationMs":8033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d775f5c5071bc10a90b1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for dashboard","durationMs":8430,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d936ca38aed47123aaf3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for mlmodel","durationMs":9313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d94149b5a027a424200d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for table","durationMs":12603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-dc17507cea6f5e2a941b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for dashboardDataModel","durationMs":8431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-dd46065e3973aee948da","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for dashboard","durationMs":14352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e04473dc158500311e77","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for mlmodel","durationMs":6478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e0b5cd5b646038da6ef0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for table","durationMs":8867,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e192c717ec35efbb64d4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for mlmodel","durationMs":9186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e194f00ae1a12a13554c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for databaseSchema","durationMs":8844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e34c8aed94d117851885","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for pipeline","durationMs":7037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e3cad63d1a8b0b4c2dec","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for database","durationMs":9041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e3fb9bdf40b67d9a1af4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless dashboard","durationMs":6667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e738a7e725f877070b42","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for pipeline","durationMs":9857,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ea6b87c9fc3944212e89","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for container","durationMs":52143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ebd41d2da61ea044cf0a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for dashboard","durationMs":8099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ec8c77e3c18d343605fe","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for topic","durationMs":11209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-eccdbe7dc40257a66039","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for databaseSchema","durationMs":14312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ed2e3b93c0b849fff721","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for table","durationMs":10233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-edced786962dcff47e08","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for dashboard","durationMs":7379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-edef11e1a1af8f147e7b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for dashboard","durationMs":7555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ee8242f1129ae6921c9b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for pipeline","durationMs":11828,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-eff9436d5c602a9c7b94","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for container","durationMs":11058,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f1c5fb133e74cb02ba04","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for dashboardDataModel","durationMs":15828,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f1fa161c211323ab8f5f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for topic","durationMs":9717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f2db6acc6a6d463a17a4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for databaseSchema","durationMs":6756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f3fbb9968dd464480148","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for database","durationMs":6370,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f4372152a4fcdb25efb7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for databaseSchema","durationMs":10070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f460875c4dd4aceea8ab","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for dashboard","durationMs":8363,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f5df5a41b9ea36e9a8c2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for dashboardDataModel","durationMs":8540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f77c37995878f4aa92bb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless database","durationMs":7981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f8d216682ae91929ed81","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for databaseSchema","durationMs":7468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fbb48b233aa1d7eb84e9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for dashboard","durationMs":7196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fbcddae2be02fc636284","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for dashboardDataModel","durationMs":8637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fc164bb0e2000feff2d2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for databaseSchema","durationMs":12692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fcd6c78be3acd0f339db","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for dashboardDataModel","durationMs":7290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-021e38b069566a0daa2e","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"task creator CAN close their own task","durationMs":237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-05984b7d2794709c41a6","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"task without assignees should still allow admin to resolve","durationMs":533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-0ae4f3085e70138d8eb2","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"assignee WITHOUT EditDescription should NOT be able to resolve RequestDescription task","durationMs":5300,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-3fc026dfedbe459b7b0b","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"assignee WITHOUT EditTags should NOT be able to resolve RequestTag task","durationMs":5535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-4ff4535b84dea3c9a774","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"assignee (owner) should see approve/reject buttons","durationMs":6809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-749c4f5bccd84796fcc1","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"owner (has EditDescription) CAN resolve task","durationMs":5872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-78bbb9afa7c6fd8804ec","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"admin CAN resolve any task","durationMs":397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-873f2c7f083db40f1b18","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"non-assignee without permissions should NOT see approve/reject buttons","durationMs":9012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-88c636be3e54d14ad5a1","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"admin should always see approve/reject buttons","durationMs":8939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-8bd75f03604a4d71ca36","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"non-creator non-assignee CANNOT close task","durationMs":8181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-936f1eccfe11f4493261","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"non-team member should NOT see approve button","durationMs":9422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-d7be48a39e974fcc4df8","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"team member CAN resolve task assigned to team (team owns entity)","durationMs":9253,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-f726bad0f784021dbbd5","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"resolving already closed task should preserve closed status","durationMs":304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-03f2be6de2c2761ec72e","project":"chromium","file":"Pages/Teams.spec.ts","title":"Delete a user from the table","durationMs":13432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-05575cd61e82f379b794","project":"chromium","file":"Pages/Teams.spec.ts","title":"Team search should work properly","durationMs":6362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-1a55f23c25c53060de8b","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New User in Group Team","durationMs":22526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-1f668e63ea29ab01be29","project":"chromium","file":"Pages/Teams.spec.ts","title":"Teams Page Flow","durationMs":44386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-2ae1f95f7a82d858d799","project":"chromium","file":"Pages/Teams.spec.ts","title":"Export team","durationMs":12892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-36f0b663f675c074e314","project":"chromium","file":"Pages/Teams.spec.ts","title":"Permanently deleting a team without soft deleting should work properly","durationMs":11716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-4f1e0c1f52584e8f4a5c","project":"chromium","file":"Pages/Teams.spec.ts","title":"Team assets should","durationMs":31016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-6880dd63ad3dc1c9041a","project":"chromium","file":"Pages/Teams.spec.ts","title":"Create a new public team","durationMs":8731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-7fa42402660989954fc2","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New Team in BusinessUnit Team","durationMs":20615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-8c42ddd21ea38410b62f","project":"chromium","file":"Pages/Teams.spec.ts","title":"Should not have edit access on team page with data available","durationMs":14083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-a496a11b02113f60becd","project":"chromium","file":"Pages/Teams.spec.ts","title":"Create a new private team and check if its visible to admin in teams selection dropdown on user profile","durationMs":12557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-a5acf3c890d0c5f803f0","project":"chromium","file":"Pages/Teams.spec.ts","title":"Should not have edit access on team page with no data available","durationMs":14308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-c5fe5613722668c57494","project":"chromium","file":"Pages/Teams.spec.ts","title":"should fetch teams with correct include parameter","durationMs":5377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-cc91d06ccdf4881127a6","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add and Remove User for Team","durationMs":17248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-d3248786cf8970f94aea","project":"chromium","file":"Pages/Teams.spec.ts","title":"Verify breadcrumb navigation for a team with a dot in its name","durationMs":10265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-d3d5abbdc9d39264f83e","project":"chromium","file":"Pages/Teams.spec.ts","title":"User as not owner should not have edit/create permission on Team","durationMs":14845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-dfff4b28227075cd2686","project":"chromium","file":"Pages/Teams.spec.ts","title":"Total User Count should update after a member is deactivated","durationMs":9162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-e3b63fffd21ca18f715c","project":"chromium","file":"Pages/Teams.spec.ts","title":"Total User Count should be rendered","durationMs":8119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-f21a59b81da22614e543","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New Team in Division Team","durationMs":21241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-f25d2e4da47eecaf9a5d","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New Team in Department Team","durationMs":16631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d689656782b1a6f7390-02e6d12455e39839a2aa","project":"Ingestion","file":"Features/ServiceAgentsLiveProgress.spec.ts","title":"agent discovered from the stream updates card and tab counts without reload","durationMs":3906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d689656782b1a6f7390-0359032648b44be54dd2","project":"Ingestion","file":"Features/ServiceAgentsLiveProgress.spec.ts","title":"agent discovered while on another tab updates count and appears on Agents tab","durationMs":3896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d689656782b1a6f7390-18b39c8b1f7b73274a0a","project":"Ingestion","file":"Features/ServiceAgentsLiveProgress.spec.ts","title":"agent card and summary update live from the progress stream","durationMs":4411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-26379e695749933a92ab","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Glossary - multiple rename + update cycles should preserve terms","durationMs":18495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-3e546bf80dc1c11ecdc8","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Domain - rename then update description should work","durationMs":9873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-68eddb3465aced4adc35","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Domain - multiple rename + update cycles should work","durationMs":17271,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-b01e664284f9a0880abb","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"GlossaryTerm - rename then update description should work","durationMs":12841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-b23330247ae47b829cbe","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Classification - rename then update description should preserve tags","durationMs":12151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-d1fcf7e4f6f6e75c9761","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Glossary - rename then update description should preserve terms","durationMs":11169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-dcf818914ebfbadca568","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Classification - multiple rename + update cycles should preserve tags","durationMs":17227,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-ebbe7e5db1a435a00b8f","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Tag - multiple rename + update cycles should work","durationMs":18249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-fb1fe9989fbcbf716ad2","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Tag - rename then update description should work","durationMs":11566,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8db3ea1719f4294139d3-393169e3864b22ec2ed6","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":29264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8db3ea1719f4294139d3-8c81d37581eec9265a23","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":28612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8e1475d7a8d4511cde98-9dcce7a238957e980241","project":"chromium","file":"Pages/OmdURLConfiguration.spec.ts","title":"update om url configuration should work","durationMs":5303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-2ca00a647f78c1967420","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Test result tooltip stays fixed while the pointer enters its incident link","durationMs":3961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-334d02c260205a6db082","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Pagination functionality in test cases list","durationMs":6781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-49cf503e6a93539fab49","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"shows exactly one banner for the latest test case run","durationMs":5322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-4c790438c32345b62a1b","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Table test case","durationMs":16415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-553212bab134ed00779b","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"shows every section for a scheduled failed test case run","durationMs":4752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-5ea2f7b91b5b348ee4ba","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Editing display name does not emit a phantom tags patch op","durationMs":5830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-61c21b5abf3c66acede8","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"TestCase filters","durationMs":30191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-9bccae9af98ba5a7c082","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"TestCase with Array params value","durationMs":9433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-b948b3260475ba5169a1","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Column test case","durationMs":12896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-00f9606596c3016580e0","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel allow entity-specific permission operations","durationMs":6137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-020742af52a481d6b34a","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database allow entity-specific permission operations","durationMs":16045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-02e76560310002da73e9","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"File deny common operations permissions","durationMs":15115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-048cd5bb07db0b092c46","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel deny common operations permissions","durationMs":14353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-07b9537cf71ed31371ed","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table allow common operations permissions","durationMs":6438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-09a091accaad0d82c91e","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel allow common operations permissions","durationMs":5996,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-0af671909bde7a013f64","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic deny common operations permissions","durationMs":18239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-0cc373dd04ff8030233f","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Worksheet deny common operations permissions","durationMs":13017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-10deae907d09b964fcfa","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database deny entity-specific permission operations","durationMs":14872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-13452946d5045d9f0db4","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline allow common operations permissions","durationMs":15666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-18ae617d79e5d7b7f079","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"File allow common operations permissions","durationMs":16249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-1f326d25e5fc9a9637ce","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard allow entity-specific permission operations","durationMs":11881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-393b9b78f8201b11c857","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline deny common operations permissions","durationMs":16796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-3ad159e3ed8c31713208","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database allow common operations permissions","durationMs":18778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-3c9a28545246bbdc73fb","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Metric allow common operations permissions","durationMs":17694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-45a17df84917860b8165","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Spreadsheet deny common operations permissions","durationMs":7200,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-4d8f171e51cb0d2e42e1","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Worksheet allow common operations permissions","durationMs":10275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-5bfaabe1489bae588f50","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table allow entity-specific permission operations","durationMs":6641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-638c851f124e342a619e","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline deny entity-specific permission operations","durationMs":15123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-6b2b0ce6cc129f162e51","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Metric deny common operations permissions","durationMs":14567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-7103f95de221bffd41e4","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex allow entity-specific permission operations","durationMs":13968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-76eeb463ff3652b7951f","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table deny entity-specific permission operations","durationMs":7592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-7ae5321fb8e02ddc6a2c","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel allow common operations permissions","durationMs":7711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-7afc5f7035b8498c6583","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard deny common operations permissions","durationMs":15239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-82058782f5a5195dbf14","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"EditAll allowed but EditTier, EditOwners, EditCertification denied – edit buttons not visible","durationMs":11409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-8497ba3282344447e2e7","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Container deny common operations permissions","durationMs":10885,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-852f1640c17c28a14391","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard deny entity-specific permission operations","durationMs":12690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-8cde431a28f77402aa93","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Container allow common operations permissions","durationMs":11457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-98622cead2f44658d0c6","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel deny common operations permissions","durationMs":10823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-9ecf0c8e4c89f192c4df","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table deny common operations permissions","durationMs":7020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-9ed49d22924150c2919d","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex deny common operations permissions","durationMs":15497,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-a21c41bd3db9957ede73","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Directory allow common operations permissions","durationMs":10385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-af9cea942959e42519d9","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"EditTier, EditOwners, EditCertification allowed but EditAll denied – edit buttons not visible","durationMs":11608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-b23b07500ce1df682796","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel allow entity-specific permission operations","durationMs":7373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-b6907275b5a16eba27dc","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic deny entity-specific permission operations","durationMs":15899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-be98efca59a108071401","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex deny entity-specific permission operations","durationMs":13954,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-c7b1063f20150b9224a9","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Spreadsheet allow common operations permissions","durationMs":6484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-cdc7161e3a6adaa0c2e4","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Directory deny common operations permissions","durationMs":9892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-ddfdf503467d77c54ffc","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex allow common operations permissions","durationMs":15841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-de36bce534daf48cb1ed","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel deny entity-specific permission operations","durationMs":10222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e064b13617abbe309243","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard allow common operations permissions","durationMs":8456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e4e4e805ca158b580f5f","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic allow common operations permissions","durationMs":18295,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e5bb4189f7681667f866","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline allow entity-specific permission operations","durationMs":15240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e84df0a6339c03bd5290","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database deny common operations permissions","durationMs":15495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-ee4a0b3aec10677417e2","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic allow entity-specific permission operations","durationMs":15478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-f2f190d2e4df85e59203","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel deny entity-specific permission operations","durationMs":12885,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-050339a5b3b27948c82d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"view modal switches to edit mode and saves changes","durationMs":9680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-0cbdc9f31920a92283d9","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"deleting a memory via the row actions menu removes it from the list","durationMs":10901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-115d742c3cab23b0a244","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"ArrowDown + Enter keyboard navigation selects the linked table result","durationMs":11451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-123127191309ad6f3c8a","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Add Memory button opens the create modal","durationMs":11972,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1574850a94a988ecbe44","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Private memory shows \"visible only to you\" description","durationMs":9835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-16b3484cc09d5255f8d6","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clearing search restores the unfiltered list","durationMs":9602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1aedfce00d8c5946c8bc","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"shared memory is NOT visible to a user absent from sharedWith","durationMs":12360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1b4f86b0208e986fc6b0","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"adding a linked asset in edit mode shows entity badge on the row","durationMs":14554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1c9d85e1c706f63a2d86","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"form is empty when modal is reopened after cancel","durationMs":11323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2a172730b1b53f63f35e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Create Memory button is enabled once memory content is filled","durationMs":9660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2aa5a395123a8c3cdc3d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Preview tab shows \"nothing to preview\" when content is empty","durationMs":9692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2ad5e7e1ef935567b0ed","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"row shows owner name and memory title","durationMs":8856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2ff20097b005186ec189","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"navigating back to page 1 shows original memories","durationMs":10452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-3867569b1addfa8a9f5c","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"selecting \"Most Used\" actually reorders rows by usageCount","durationMs":9038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-394aa041e4c80c1b07c7","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Preview tab renders markdown content correctly","durationMs":9227,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-46ebbf692c088e16f169","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking \"Total Memories\" count card activates the All view","durationMs":9456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-51a791024388a119e500","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing title updates the memory and the row reflects the new title","durationMs":11380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-54cb6b919c18ad54110c","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"entity-visibility memory is visible to every authenticated user","durationMs":12601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-55e0a815e60bb09ce57c","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"pagination controls are visible when more than 10 memories exist","durationMs":8514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5942dd11a9d4b64ec829","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"sort dropdown shows all three sort options","durationMs":8120,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5a7baea2b091d24da57b","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking a memory row opens the view-only modal with owner action buttons","durationMs":9021,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5bc1df2528c2b5058f83","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"private memory (admin-owned) is NOT visible to a non-owner","durationMs":12519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5bc84e17ae75eb005f5d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking \"All\" tab after applying an author filter clears the filter","durationMs":11416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5c94648cb13fa0cbffb1","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"copy link button copies URL containing the ?memory= param","durationMs":9260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-64649ab2041f5d3fe8f3","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking \"Created by Me\" count card activates the created-by-me filter","durationMs":8381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-6512f16c5a112b85a606","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"shared memory IS visible to a user explicitly listed in sharedWith","durationMs":11699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-72b54a939c562fb1c204","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"search box filters memories by title","durationMs":9354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-735e01e2899164788fe8","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"content typed in Edit mode is visible in Preview and preserved when switching back","durationMs":8616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-7b3fb940c312905d5060","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"linked asset card shows remove button; clicking it removes the asset","durationMs":9932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-8090e9d3ebd02b77c47e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"creates a memory with title, content, and type — card appears in the list","durationMs":11201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-833efd0cc52341230add","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"navigating to a URL with ?memory= param auto-opens the memory modal","durationMs":8541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-8b1f26e601d5baa9ff70","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"closing the modal removes ?memory= param from the URL","durationMs":9288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-8ecc1dad1c384a343e2e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"changing visibility from Shared to Private shows \"visible only to you\" after save","durationMs":15229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-93771ed3a6e8bed91a7e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"link an asset button opens the search popover","durationMs":9487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-94ab0b32cbe40c045b6b","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"row shows linked entity badge when memory has a primary entity","durationMs":8404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-95c9093fdd3ff5e51c44","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"cancel button in edit mode closes the modal without saving","durationMs":21626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-9e097128eef15ee87968","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"delete button inside the edit modal deletes the memory","durationMs":10637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-9e8a0babb0950a756604","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"\"Clear All\" button resets the author filter and restores the full list","durationMs":14378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-a506eaeb50a155ae247d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing memory type persists after save","durationMs":12858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-a6e380a210b52c7dda25","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Create Memory button is disabled when memory content is empty","durationMs":8213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-abc24ab8a7d2cbc7bbcc","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Shared memory shows the shared-with-specific-people description","durationMs":10243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-ad770b579565ae2fd108","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing visibility from Shared to Private saves and updates the badge","durationMs":13375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-b91c37ad31594d56093f","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"typing the linked table name in the asset search returns it as a result","durationMs":10473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-bd5714317a0b47826f87","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"data consumer sees a read-only modal for shared memories they do not own","durationMs":13332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-c89dfb6c8cf1605c7ebf","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"\"All Assets\" option in asset filter button resets the asset filter","durationMs":11950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-d1e2a2780b71025dac99","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"\"Created by Me\" tab shows admin's own memories and hides the second author's","durationMs":8500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-d71b0b2f0cec854dd4fe","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"navigating to page 2 loads a different set of memory rows","durationMs":8324,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-da46a9af079413eb60af","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"selecting the second author in the author filter shows only their memory","durationMs":10896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-e47a22c54616939b72ef","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking a memory row adds ?memory= param to the URL","durationMs":9470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-e651d4373580504f54fa","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Entity memory shows \"visible to linked entities\" description","durationMs":10192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-ec8e38c378a883334cb8","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"edit-memory button on the row opens the modal in edit mode","durationMs":9380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-ed83a3eeb82edd110766","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"no results message is shown when search matches nothing","durationMs":8531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-f0c1da1240b0e4613ed2","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"switching back to Edit tab restores the textarea","durationMs":11478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-f10ec76507ba30b98ad4","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"shows header with title, breadcrumb and Add Memory button","durationMs":11783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-f3277503da5d3d73f903","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing memory content updates the memory","durationMs":11537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-215a8878c531328977c2","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"rejected OwnershipUpdate should NOT change ownership","durationMs":477,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-2602a3aa080b731b4749","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should create and approve DomainUpdate task","durationMs":670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-3a096d2f4ebade0afd91","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"rejected TierUpdate should NOT apply tier","durationMs":467,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-5d012330bf9c4bc78527","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should approve description update task and apply to entity","durationMs":456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-6e386755207335934c43","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should create and approve OwnershipUpdate task","durationMs":636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-c0065d9d29e0659d6c34","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should create and approve TierUpdate task","durationMs":535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-cbee75183bf50baef2a7","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should approve column description update task","durationMs":385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90ed2060a2a8751f24f5-24638cee4dd18362bdb5","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Install application","durationMs":3726,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90ed2060a2a8751f24f5-b104994da51b7cdfaabd","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Edit data insight application","durationMs":4040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90ed2060a2a8751f24f5-e421dc1031935e8b877a","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Run application","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"90ed2060a2a8751f24f5-f7537948d9d62bd69376","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Uninstall application","durationMs":2726,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90f483905672abdab8d4-395ef9ff12b9b1cfd420","project":"chromium","file":"Pages/ProfilerConfigurationPage.spec.ts","title":"Sample Data Ingestion Configuration","durationMs":8242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90f483905672abdab8d4-d388e31b6ee015b2c18e","project":"chromium","file":"Pages/ProfilerConfigurationPage.spec.ts","title":"Admin user","durationMs":14612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90f483905672abdab8d4-d9c6a62871c623262969","project":"chromium","file":"Pages/ProfilerConfigurationPage.spec.ts","title":"Non admin user","durationMs":10764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-010947e1f2ae5f490fdf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":18516,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0204627a501622ee8deb","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":14906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-04a73b3abdf07d99230b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0515d537e10283b36e45","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":16764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-05cb4526aee30bf31b27","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":11009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-05cba1d1810b00e6da0c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":9858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-06621cfea096a95864a1","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12477,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-066ed7052e902f07afd7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":23790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-07d3752db441d6dcd5c9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":14845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0808415fef188619b0c3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-088ab01bbb6af83198b5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":27417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-08a72d1ea60f89919542","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":27506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-09d0849a721c46ed4e27","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":22225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0a52cbeb44d811c97ae9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0b285034c080279bfe87","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":10804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0b31a83be6093fccd9a8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":16567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0c601eb8ae577401535c","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":23489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0c9147c3faa959ed6d1f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":24231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0cae867a36cfb2330728","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0cca9e90033054e752e4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":18802,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0df78730b187b80fb609","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Search Index","durationMs":28108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0e9f56083fd2fb5d9faa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":27313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0f315b07f498e7688a32","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0fea7c50c0a5a82872e1","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":7904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-10586eb08b05b663021c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":19723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-10823933e7cc47252622","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":23535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-10ddfe5a92169df86b00","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":19432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-137ec6b7227be9ad99da","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":15119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-139c5016d99093c360b7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":22929,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-14011a0248e6b08f80a7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel key profile metrics validation","durationMs":16163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-14470019ffd97004dcbe","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":18769,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-149227e4460fabcd42c6","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-14ac924ed8bcb7e68832","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":18256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-15d1273f787e5fa2d04a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-163b977d15c76c372a6b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":62817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-164caa239e68ee9d019b","project":"chromium","file":"Pages/Entity.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":17403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1694b0714d00d5c71ac2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18200,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1699b841032a65cec187","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":26028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-183d1f957e327795eb4a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":19507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-18a47a9004653643fb64","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1943709640011d77ed36","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":17697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-19c2bb2e9c1e146d40e8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel - Data Quality tab shows test cases","durationMs":19488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1b72ac1fa7bcb9a1a474","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":9124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1c94f2df230f3f14fe7c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":17979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1cecbcaa17cb6913726e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":9205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1d091ca31ae29db2c8ea","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1d1fa86265503c79342c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":10503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1e2cf9c79c0a9525a66e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":15788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1e8f2077ec976b52a489","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":17293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1f106521cf5f4bc3d32a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":17451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1fee3fc39291ed69f8d2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-20f71b2d07418575475d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":33492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-20ff1e5b739d9faf71a9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":27606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-224784ca851aca125dc5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":15010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-22a6f18eb0af4e42f50e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":19243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-23222301ac380b5bdf2d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-255c0b0482bb4fe51e92","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":16574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-260a08f521c36666d45e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":22861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-26bf78922e154401df45","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":16357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-26c62f4d3d117052c242","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":25705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-286080b65df7a8bc3d85","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-298fdb3a31fa6071e859","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":24323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2b98e260a7accd3dd5e3","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2d387ded98f7768265c4","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":14188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2d76b56f14c39477bfa8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2e8162d5d22dc70ab80c","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2fb15765b5b25a485ab8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":9606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2fd19b049110a1f7576e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Api Endpoint","durationMs":27076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-30412ac8a486dbe6db56","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":12451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3049f221e1833056bb4f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":20380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-30604efc6717f760cb19","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":21745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3130e46417f6b8ee0ddf","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":14286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-31675e337df06a59163e","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-329014335b0953e9a963","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-33a2b8dcb127802d7ea4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3449766d9eea852cb02a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Topic","durationMs":27314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-355b38942f8be1c21038","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-37b56a8c64057cd16849","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-388ca052aec51e76c129","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":10414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3940d8d78d5447a24d94","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":26572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-39437ad5d0bb92bd3f56","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3a30f163c9cf41e7b0a2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":24003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3af3ec90e38be2bb9b8a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":13205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3c3dc27e5b016fad1c34","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":26309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3cff397f5942cb1e4415","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3d1743b61f22211f8cde","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":27885,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3fd66bb77526bc0549c5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":28249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-40abc10c3cbf325d0814","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":18983,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-40b5f757c2e50ab4c423","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":8316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4186a53379bf3038d6df","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":16084,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-41930b02ea7ae699543b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-423cbdd8a1649ef25e03","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-44558ad1c4b6295c42ef","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Dashboard","durationMs":24541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-44979265001c53ce1aa3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":27187,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-459f81112fb7567b0275","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-45ce2f3980113cfb8fc3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-48a178691f7d801b79b0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-490c4b163ecfb2791f11","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4924df03b181449afbff","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":21804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-492726a2addd8a53a89d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4a4f175326692f1e1df7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4ac150db5e30c650fbf6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":14711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4b66ca7fb325742907a7","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":16147,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4bc0347bfb50f8ba6efa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4bebf2eddb62c1c0a27d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":11789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4cb9c7949e76cfd2158d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4d4f0ab999224ca222c3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4ea337e0978f71f7787a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Complex nested column structures - comprehensive validation","durationMs":15617,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4eb7ba29ce3f14453e74","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":24426,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4ffc30215ba4fd0f309b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":21732,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-520498925292ca429e70","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":27824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-521bba060aebc0805243","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5237c058076927c64a4b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":23589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-528578f052a6a5d372de","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-52ded41a9f92477b9e8d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":26005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-545e1e1606596daba844","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22890,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-55c1c83398c224c17777","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":27688,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-57413ea2ee24eacebe86","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5760cca191d53021860e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":32045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-57656fc4e202f6fe94ae","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":25399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-576c627662fa68e8fdf5","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5783fe4fac5585eab4e8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":24166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-578975ad1fa2b90690ef","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":26824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-589a2251bfac9347931d","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":23290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-58fcb7bc23b74494562d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-58ff7eefdb13abde7b0b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":17970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-596d6153699326e4a88a","project":"chromium","file":"Pages/Entity.spec.ts","title":"DashboardDataModel page should show the project name","durationMs":9834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-59f0ea7d5c7e17ed7068","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":12141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5a2fd88bc28e89ca1895","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":26798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5a8a4f525e79dc02ee22","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":33898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5ae58d54d9462234aefd","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14138,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5b54086826771a0d829a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":12526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5b89a6d1f13278f64fb4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":23881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5bdd95036294d02d6aed","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":18484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5bfca70544447baacc27","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":19242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5c2dee6d5dee89070889","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5cca7fa93e2963965949","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":19685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5ce7395d57a38e605045","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":19963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5e5602eadda15814cb1d","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5f55cadeb5b75f2d9827","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":11548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5f73f22159832459f8d6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":19195,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5ffbcd9603be554d72cc","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":21014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6090b3469968428010ca","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-60d6762c4b0ae5b80aa3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-61888ffb206a1f9cd606","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":14693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-635acc3dd237ce3372f3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Array type columns with nested structures in NestedColumnsSection","durationMs":15373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-638bed0d16d0fe08b913","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-63d6f16376792bf39ec4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Dashboard Data Model","durationMs":25794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-64cbef5facf9a46414f7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Spreadsheet","durationMs":17251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-658673c37e533eeef774","project":"chromium","file":"Pages/Entity.spec.ts","title":"Data Consumer should be denied edit access in column detail panel when deny policy rule is applied","durationMs":14636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-65e50d3c39f208f5c8b8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":16173,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-660a5d76fe1e2a33c402","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-665622c28ce75a44b7d1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":28196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6688dd944533a6843776","project":"chromium","file":"Pages/Entity.spec.ts","title":"Data Consumer should be denied access to queries and sample data tabs when deny policy rule is applied on table level","durationMs":14016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-675a7eb6037656e443a8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":26436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-67b5ea7d270e6f0d7212","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":10055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-689e5012886587487afd","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":21570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-68c3d140aa232b18343a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":23772,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-69642132f4c8d46914f0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27903,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-69a4bb362989003c8fe5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":14725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6a7c1cfa25aee1b88332","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":21398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6bf622162eec9ddb280f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":14495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6c45206d1c7e364d3dab","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":24443,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6c6d5e53693ae91f974d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":8689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6cb3a9042fe63e651e6f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":19525,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6d27b11bd3329db0c3da","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":14109,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6db5a8684315b09e586b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":28294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6dd976c84561bec7292c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":21535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6f27ade629aa21259930","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":14472,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7033bd8a589efefc6460","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":22243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-714c7c04f6771c55b417","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-715e918fa77d52c93d3d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":23151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-717c3379a8b317c17d8a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":18823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-72de070373835646c330","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-73396497c9550736ee6b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":10966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-733d7d7ac05db37816ba","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":14131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-734125bcdd8222736844","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Ml Model","durationMs":26459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-738fa5dafee2cc5efba2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-74d0bd71eeeca6f080ea","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":25455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7557b6f4c5e94da74b0a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Metric","durationMs":26719,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-76f7c1dce024366a65ad","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":12229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-76fed440252571c4ac35","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":13694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7ac6d76c0b0762dc7654","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7c5857a17226f22628da","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":15202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7c7e74ca9adebcc53967","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":31052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7d3b7ccbffa26944736d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":26286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7dba101412de85e23071","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7e2e7b59a31556b2749f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":21506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7ed713af973c88618eab","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":19692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7f0a484980e667964f0b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":29258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7f9e6aef30246153c9f9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":21300,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-80c0a4b111e70096228f","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-81886e104470f3edf684","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-828bef0287fa1c5da67e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21724,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-831dbe32138dac09e7d8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":18065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-83395592d0affb7528ba","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-83854023e08436751e88","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel does not call /columns/name GET for DashboardDataModel","durationMs":9043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-83fd602de32ac38f1777","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8487bc28a50fe9aa2194","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":25650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-853d61f316a0d5af5ffd","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":26535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-85936fb882a2786fd7c7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-85b99b63d5290506f285","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":13888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-88f8bdd28e992ed4732b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":28708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-89255caaa20ed42f11c1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8a420f6c0389278e14a8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":9961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8c43a40bbe3dab735d28","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":14421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8c51774ba5e172b0e5df","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":12690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8e34dc2db65998150cbc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":14603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8ea4f124a947e104dfc4","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":10145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8fba808d32c7edb58b11","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Pipeline","durationMs":20052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9040c78d20f9f8c4dd0c","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":10090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-90bd676080f86b4a617f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":17841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-91428c93cc268ca60069","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-91543bc8d8167f5065a1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":6191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9231b4fba6be912c3a58","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":13151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-92a98accb4a75ac9bd41","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-93fb297d11c0da8eb925","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":32245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-94398585e76e7076dd89","project":"chromium","file":"Pages/Entity.spec.ts","title":"Switch from Data Observability tab to Activity Feed tab and verify data appears","durationMs":10720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-974cf3128b2fe509f68e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":13939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-981422561ba577ab278f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":16047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-98295172b077e968710d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":30163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-98a764c8f8883afbfc61","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":22852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-98beffeeb1691cfc46e3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":18454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9947441fa2bdd31d2579","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":20699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-99df0dd4ce461e379bf1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9bb7b088737745749568","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":11753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9bf8262a50e226dc14e0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Dashboard page should show the project name","durationMs":13122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9d47fed51de1a82ea61b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9e32c9c3455f40d45c51","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Table","durationMs":33226,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9eb19184071a33394559","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":30023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9eb5d4b065166f22f57d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":29127,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9ef758d01c78546f9e36","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":15385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9fca75ad842b940cc462","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a0b8122c30252e10af37","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":13637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a29f3c417fe4c951b553","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Container","durationMs":17692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a2cfcd0d99157a65bf75","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":31160,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a3c11ebaa1e3e2d4c067","project":"chromium","file":"Pages/Entity.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":9852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a492547f9007a342a812","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":19139,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a5998ef2edac55039257","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":9635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a5d17a88fd978d0b50f0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":15975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a7412694cacae19f6d47","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":19281,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a76b7d4955e681a340e2","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":22200,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a7c74023a04b469dc54a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":15937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a8a7d0dae0901dc05bbf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":10933,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a9d8535c0845968fbeae","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Worksheet","durationMs":21275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-aa3cf3f233e4209c62d7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-aa8f971f04aec8ed12d5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":13411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ab9125e3be00b247e5c6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":24323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-acf4ed1c6b31c9deb82b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":26541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ad454c2d5478c288a398","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":24379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ae1753b8395d90f206d5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15719,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ae2e3a33c620656a9e25","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":13389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-aed8de3b484856dea5b5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":18570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-af920abc6c341912e2c4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":16021,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b02919d12e5158bbd751","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":23526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b02c0574cfdb0a3c8631","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b03cf38e18dfe4fa6513","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Stored Procedure","durationMs":18065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b147c972de2ca1979612","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":23675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b1bc3c6efd67cde75543","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b2898eb27b3458212bb9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":9079,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b326e8761d37657c85bc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18839,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b32b7349dcb65de985b6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Directory","durationMs":24336,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b3d6c097f77e0b107d33","project":"chromium","file":"Pages/Entity.spec.ts","title":"Mixed sibling columns (simple + nested) at same level","durationMs":15586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b57f4cfea36c6106e54d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b72b1bcf49a07cf93c31","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":12734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b7d62202728d8accd1ff","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":29192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b80d667c0acf38204010","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b819774aa9824797ce0b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b8a1c25981278f288325","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Chart","durationMs":18667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ba27de8b1b49b885f461","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":33600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bbb4b786ce82a4dc2641","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":18722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bd64ed3fbf1b8cc239da","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":15522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bd7db5cd6f03951867e3","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":17570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-be0fc17cfe43ab5f959f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":10069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-beaa3406691cce197eda","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bf6e8dfcb77c6e2ca2ac","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":18520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c0a53f27e3c7f00c3183","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel - Data Quality Incidents tab","durationMs":16580,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c1805fb6858404bea377","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c1ba3f2ea3699ed7ba49","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":25652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c295439fe870d89f8e3e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":21663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c2ead24a21c62c63dddf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":12078,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c37a1dcd7a72a8ab98bc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20742,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c419e22430f8d60c5f38","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c4d5c714289b65cd5065","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":15571,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c723be406a26ef3415bf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15048,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ca5a4347882991d25ec0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":16251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-cbee4371fcd3aef15c86","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":16175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-cce5d4d36933d42e3bc0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":27511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-cd1b25a5a5e7c2a942f4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":30367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ce196a55488b928c2d30","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":20281,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ce268a04010e8041efb5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":25864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ce2c9e42affef0f8e984","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d03431d009cfb98964d5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":19886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d19f58e4d5f295f56efa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":13392,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d1c622df7f7867c3494f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d246aab59a2dd5f44424","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":9666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d247c88f16904422d795","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d2612844f69066702a65","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":22350,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d3b17d6328d0a5be8f9c","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":14397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d4574f5523cbdbd41ffb","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":8661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d485e529727a1a0f65a3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":14399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d7f2d6a1270f33fc5c96","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d8c173ce639ccb75f5cf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d91d2f8bb2e0cdc843fe","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":21120,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dad73eda2f4b068c10c8","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":20838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dbcb8ef877e0a29eaa84","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15713,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dd2889a0fa137f0ce3a9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dea1ccd58511090988d7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-debe98100f5126a60f3a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":19600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-df5a5db4037d28aa590b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":28211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e042722a07ea0a3de54d","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e1446c2f53e8f61fe0aa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":18514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e1bcfa96b3dd42189461","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":15007,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e1f23382e9baf6978200","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e241f0f086944e77301a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":52390,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e24c535d92bc2f637cdb","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e366da710e50f4f64e8f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":21169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e4e04c52194d563079e6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":10733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e5c2865265d1af10ee7d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":17347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e7bfd4ae8f07e04b2381","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e941ffbc92ab76be5259","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":15367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e9f5e0e08338ec03967f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":26415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-eb01173d188cbe8393dc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":12172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-eb0d5e5b36d7c532a4d6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":21629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ec00f7977e836a98c1d6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":20734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ec976ce21d731948f7ae","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":18734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ed3bfea6fbaba7b39813","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12164,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-eda0173586502e9586b8","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":18269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-edae0655ec0cb6bdc6a4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":19796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-edee178e64d24e4b5320","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":23065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ee704d960a0d87348125","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":20672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f3f9c17a2c9aa8bc7f09","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":31205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f50fa4fafad289f59bf0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f56e37113ccb0ba50171","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":24163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f5b5f7e6288392d9c64c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":6806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f6b50a299a49f1965028","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":25185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f793562b25de9479b901","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":10537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f83796dc12fc01216f2c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":24966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f9b076446ad4902e6057","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f9f0cc30af4d50635e45","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":25849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb095fce3e726deb2671","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":23327,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb1b344006049a57fe6e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":26961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb26f3d3063f75474b76","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":17576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb54e3be502528a811a3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":19917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb5aa2f181bc190325c7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fbb1b5d546048e8a6ce0","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":9333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fbf0ad523a6b32d423cb","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":23319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd02335b2dcae5e08711","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd73955b30bfc3f6b34b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":21358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd7481fb2c651161f990","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":24665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd930e32aac736574382","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":21843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fdcf50e13a6a2a4bbd2b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete File","durationMs":25393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fe5a4733fff8ccf670fa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":16040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-0e1b5c1c44a8f2279d06","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the MlModel Service entity item action after rules disabled","durationMs":14856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-1cd87d9dd281b2dece0d","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the SearchIndex Service entity item action after rules disabled","durationMs":17409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-2cb867da73a9a971f77a","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Container entity item action after rules disabled","durationMs":17805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-30575d4022cfb3b0782b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Storage Service entity item action after rules disabled","durationMs":18659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-38d54bc660f074f9097b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Dashboard Service entity item action after rules disabled","durationMs":14851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-3b609306040a234cbfeb","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Messaging Service entity item action after rules disabled","durationMs":16406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-4cc494c7283e8466765d","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Database service","durationMs":59144,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-52a8397186c3af51af32","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the DashboardDataModel entity item action after rules disabled","durationMs":17337,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-609686451a9f7a7ebeea","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Api Collection entity item action after rules disabled","durationMs":17597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-61b78ce0d330fc59d4ec","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Table entity item action after rules disabled","durationMs":24358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-6737dba688f9167420f0","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Database Schema entity item action after rules disabled","durationMs":20943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-68f16dbd339a5bdbe466","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Database Service entity item action after rules disabled","durationMs":13699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-6b2ea7bfd8bb286c24f3","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Drive Service entity item action after rules disabled","durationMs":16680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-6efff7b892881b0179ad","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"should allow multiple domain selection for glossary term when entity rules are disabled","durationMs":5423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-7333face1ace08be4fd8","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Worksheet entity item action after rules disabled","durationMs":20487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-7b50302fbb1ca636773a","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Directory entity item action after rules disabled","durationMs":19518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-80572a8c0e9e51d6d17b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Api Service entity item action after rules disabled","durationMs":17016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-90309c057da02ade63a0","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the File entity item action after rules disabled","durationMs":19311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-90c89420e6df7139aab1","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Topic entity item action after rules disabled","durationMs":19518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-913e01f78ba46179b9c4","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Pipeline entity item action after rules disabled","durationMs":20050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-982c393f021f67ee967c","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the ApiEndpoint entity item action after rules disabled","durationMs":20711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-98909ef36befccbe6fbb","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Database entity item action after rules disabled","durationMs":19494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-afbe709e30f6facd3dbd","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Database Schema","durationMs":51041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-b06f911eea6817b73cad","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Chart entity item action after rules disabled","durationMs":20574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-b13f119926cde07f3531","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Store Procedure entity item action after rules disabled","durationMs":19531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-c83bce24def2c5be23fa","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Metric entity item action after rules disabled","durationMs":12569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-cc81aa5e99065f424e4b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Spreadsheet entity item action after rules disabled","durationMs":17357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-d1dd9a785ec3db3fd0e3","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the SearchIndex entity item action after rules disabled","durationMs":19850,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-e4bf750e93899dca5942","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Pipeline Service entity item action after rules disabled","durationMs":18171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-e5bc6e17521e70fe27d4","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Dashboard entity item action after rules disabled","durationMs":19923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-eb3f22266d782e009e06","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Database","durationMs":59659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-f66c740a854d5362dc0f","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the MlModel entity item action after rules disabled","durationMs":15457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-010a5c0cb7d2aa43b4e6","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"built-in relation type shows M:M cardinality in the cardinality map","durationMs":34520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-26134fc2ed2b34ae9ce4","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"cardinality map is populated when edge labels are on (default)","durationMs":34076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-42930591193b65ce7249","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"MANY_TO_MANY relation type should have label \"M\" on both ends","durationMs":34150,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-43a99786fe79755b89b9","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"edges for cardinality-typed relations appear in the graph edge data","durationMs":34302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-4721e6b8fc9bcbc4080e","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"stats reflect the cardinality-typed edges in the relation count","durationMs":34054,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-4ad4422093a1862c9ac9","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"MANY_TO_ONE relation type should have \"M\" at source and \"1\" at target","durationMs":34090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-56c3132792953bd52609","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"graph renders without error when cardinality relation types are active","durationMs":33908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-70353e5908dbdf148f9d","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"CUSTOM relation type with sourceMax=1 and no targetMax should produce \"1\" → \"M\"","durationMs":36565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-ae82da3861a5051db70a","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"graph remains stable after toggling edge labels off and back on","durationMs":34136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-b276a74b45becd923aaf","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"ONE_TO_MANY relation type should have \"1\" at source and \"M\" at target","durationMs":33984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-c3ad9884715acf7b9b76","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"ONE_TO_ONE relation type should have label \"1\" on both ends","durationMs":37311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-05afe72e2517126b831c","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S01: Selecting ME child should auto-deselect siblings","durationMs":12388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-07c5485ffe70af9efaf5","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H05: ME glossary (top level) children render checkboxes with ME behavior","durationMs":11179,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-1fd7aeb46dbe55939735","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H06: Deep nesting - non-ME parent under ME grandparent allows multi-select","durationMs":10835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-39d8b39132ab09f17d4d","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-T02: Apply ME term to table column via detail panel","durationMs":14087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-490fe051b00e05508785","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S05: Mixed selection - ME siblings deselect, non-ME remain","durationMs":12841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-4eb760f5a611886c7801","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H04: Toggle ME flag via edit after children exist","durationMs":16277,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-59cbad295850012fe314","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-R01: Children of ME parent should render checkboxes","durationMs":13508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-7db74194a6481c407de8","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S03: Can deselect currently selected ME term","durationMs":11878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-982e188c2d0faee81352","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S02: Can select multiple children under non-ME parent","durationMs":12860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-c73698374be52746af65","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-T01: Apply single ME glossary term to table","durationMs":11428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-dd551949ba09fa30d34a","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H07: Non-ME parent under ME glossary allows multi-select for its children","durationMs":10662,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-19d2e2f60fe8424ceb98","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should cancel deletion and preserve sample data","durationMs":8027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-2d25e25ebbc138c884ef","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should display sample data tab with rows and columns","durationMs":5540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-60a661d10879c9cc9007","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should show only export option for data consumer without edit permissions","durationMs":7045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-887ef71abcfe0e95a672","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should show empty state for table without sample data","durationMs":4151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-955c7fc1aacedef99996","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should download sample data as CSV when export is clicked","durationMs":5782,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-aea7d9d516ae343cd09b","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should open delete confirmation modal","durationMs":6296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-bc8f12de342882c9876e","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should change row limit using the selector","durationMs":5581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-c79b78f0d0a5b6acc220","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should show export and delete options in manage dropdown for admin","durationMs":6106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-d03354ab10143b83b4f1","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should render sample data for columns with reserved names","durationMs":5161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-eabdba275e13219c035b","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should delete sample data and show empty state after confirmation","durationMs":6401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-f5b810780f21ec70c533","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should persist row limit selection after switching tabs and returning","durationMs":8374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"93bd9f4090791ca89375-80c585ad9ba6f0b328b8","project":"Ingestion","file":"Features/TestSuiteMultiPipeline.spec.ts","title":"Edit the pipeline's test case","durationMs":8448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"93bd9f4090791ca89375-9e57b2112f917b31f412","project":"Ingestion","file":"Features/TestSuiteMultiPipeline.spec.ts","title":"TestSuite multi pipeline support","durationMs":15355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9467adbab3a83cfec66c-3dae36d63205fa0caf33","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraphPerf.spec.ts","title":"opening Relations Graph tab does NOT fan out per-Id glossary term fetches","durationMs":12983,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-1e4bd98b74ceda0fe09c","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should not offer Test Login for a confidential client","durationMs":7319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-3aa538554a17e9a1b306","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should offer Test Login for auth0 as a public client","durationMs":8383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-80d48f5a288d4db55b18","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should show the resolved identity when the test login succeeds","durationMs":7943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-91d295ca2e48b253e2c9","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should offer Test Login for okta as a public client","durationMs":6949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-a25eb06064c876ff691a","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should not offer Test Login for SAML","durationMs":7381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-c1c499b12b7762408bb7","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should not offer Test Login for LDAP","durationMs":7489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-e21597b879b2be344862","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should show the failure reason when the configuration would reject the login","durationMs":8157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-fed6410cd76bffb3a1f0","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should offer Test Login for google as a public client","durationMs":5752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-28d3656567a51c3d6dd1","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":11188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-2bd6a7f1da1b57259832","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":10681,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-351b07cb01348ee01865","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":8609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-680178bebcb35c8d0570","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names in Explore Summary Panel","durationMs":10163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-addabe3e2b1839a794b3","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names in Version History","durationMs":7656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-c64a38d97f36769aaae3","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":9374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-e55a329b63a2050517c2","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":8442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f694e0831ef9afa291f6","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":9730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f73ff4b1baddd098ad83","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":9495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f8a6fc0f3baf8682f689","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names in Profiler Tab","durationMs":12157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f8d08bd67e5189c8a6e8","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":7468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-00c41106f8eca12d9a6a","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Worksheet","durationMs":18172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-0ec1ae19f5783c5db694","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Database - closing version drawer navigates to entity page without tab","durationMs":10411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-367e0529fecd218661bc","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Directory","durationMs":18897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-384ea6bd7b52e528d275","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Table","durationMs":27246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-3a435f2426b65f5fcb06","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Container","durationMs":23767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-46b4c939b2a66ef2b79a","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"DatabaseSchema - closing version drawer navigates to entity page without tab","durationMs":10871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-56bad44722170d3bf33b","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Dashboard","durationMs":19981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-5b4eee1a2c982dc07a0b","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"MlModel","durationMs":20537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-79688ef1070ce564ebe8","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"SearchIndex","durationMs":21968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-89220cdd73aa9b8291a7","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Store Procedure","durationMs":20002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-94b43b544c431b49fa87","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Table - should show historical column descriptions in version view","durationMs":10973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-a2db654e9810d2d0b299","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"ApiEndpoint","durationMs":20456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-ac166e994782e916f5d6","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Table - closing version drawer navigates to entity page without tab","durationMs":12106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-b5ec54360f22d1b13764","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Pipeline","durationMs":19463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-d2324e735fc64ab4d022","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"File","durationMs":19246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-d6a35e540eacbde345fb","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Topic","durationMs":22368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-dcb2e97f35988ad7b740","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"DashboardDataModel","durationMs":21177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-fd945c597e9f89b122f5","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Spreadsheet","durationMs":19213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"95abbb840354c898cbad-34fea57348ad3c34f876","project":"chromium","file":"Features/Glossary/GlossaryApprovalAfterMove.spec.ts","title":"rejecting an open task succeeds after the parent term is moved under a sibling","durationMs":15842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"95abbb840354c898cbad-3aaed8dc99103d883367","project":"chromium","file":"Features/Glossary/GlossaryApprovalAfterMove.spec.ts","title":"approving an open task succeeds after the parent term is moved under a sibling","durationMs":18800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-2fa097ab78b1de01ba8b","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"non-assignee should be able to add comment","durationMs":11666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-4044e26f020808eeeb02","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"assignee should be able to add comment to task","durationMs":11624,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-499a39f09e66aa4d428e","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"POST /tasks/{id}/comments should add comment","durationMs":31,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-6615c1b10bfdc115c4f2","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"GET /tasks/{id}?fields=comments should return comments","durationMs":7,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-7d04368e1ade72494167","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"selecting user from @ dropdown should add mention","durationMs":11286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-7d73e30d5f57254faedd","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"should be able to delete own comment","durationMs":8091,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-8d821b64fb7359981457","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"non-author should not see edit/delete options","durationMs":8116,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-8ecdb599b122929a7165","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"comment author should see edit/delete options","durationMs":7557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-b16f7fa7ab19dc6d68ab","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"admin should be able to add comment to any task","durationMs":10680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-e74262a4256762b27023","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"typing @ should show user suggestion dropdown","durationMs":10559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-ff55d1327b746f190307","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"should be able to edit own comment","durationMs":7637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"980a32fafab996c34f4c-3a5c1a8728e9f65e696a","project":"chromium","file":"Features/Tasks/TaskAssigneeManagement.spec.ts","title":"admin can reassign an existing metadata task from the task details page","durationMs":10461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-502ba903b9d98f4b6361","project":"Basic","file":"Features/Dashboards.spec.ts","title":"should change the page size","durationMs":7252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-606502ef644302893802","project":"Basic","file":"Features/Dashboards.spec.ts","title":"should be able to toggle between deleted and non-deleted charts","durationMs":13951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-a9186932ace2c0e8aded","project":"Basic","file":"Features/Dashboards.spec.ts","title":"should display data model when service name contains dots","durationMs":5934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-ab012b7a43d0b2fea651","project":"chromium","file":"Features/Dashboards.spec.ts","title":"expand / collapse should not appear after updating nested fields for dashboardDataModels","durationMs":14352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a109e5bd20f766cfd0b-cae5f8ac7fb76a194f42","project":"Basic","file":"Features/CustomizeNavigationNewItems.spec.ts","title":"new sidebar items absent from saved persona nav are toggled OFF in admin settings and hidden in sidebar","durationMs":14709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a109e5bd20f766cfd0b-f3a369e4a4413c840fc3","project":"Basic","file":"Features/CustomizeNavigationNewItems.spec.ts","title":"cancel button on customize navigation shows a single confirmation modal and Discard exits the page","durationMs":10550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-01bd0c44f0f49343c457","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":5318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-21df6d035bdfa80c9962","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5035,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-2ce7e69a85607992ac60","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-2f39ba17e3d032870fe7","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4736,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-3c75ccb62f351a160e0a","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a table-scoped user sees tables but never dashboards","durationMs":10988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-3cc9ff5d69980702f3cd","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":5086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-499cc24a0ae76d742af4","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-4abdb862b466e0e7c4ed","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4902,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-4d1b8bd26d4658097189","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-574ca7618da3f2f3ca61","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a dashboard-scoped user sees dashboards but never tables","durationMs":11522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-6c38a2a0c5e8fa49d2ef","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-6ddfec14585b9ddd1059","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"the browse tree only shows the asset-type categories a user can access","durationMs":13059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-740ca699b4783a25a25e","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-742a40dd2d1eb06da541","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-87cc8fd5ad9434623334","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a fully denied user sees neither asset type when browsing","durationMs":9254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-912df73111d625a0803d","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-950c1df173e71bdc12e8","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-956aebac642646bfa5dd","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4712,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-a9257c1d69db95a1fd68","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":6823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-b18d71356f6988da426f","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-ba2b5d8d484e2f24ea82","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4701,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-bb51860dedb5584d3392","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a user permitted on all asset types browses both","durationMs":12825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-bc6de9691f9f161ee64d","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-c079cb6b3b96546c506b","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4728,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-c268cdd384dadfb181a8","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-c54f4b84f6f604c133dd","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":7157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-cc3cb9faa9cc57493e9f","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":5591,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-ee381a738fbd0dc4377d","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-eed2b6cdaa2a0c64e969","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-05f708f2d1cdfd1fa6d1","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify if string input inside oneOf config works properly","durationMs":4297,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-15c93e78abaa0de33616","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should persist empty schemaRegistryTopicSuffixName when the field is cleared","durationMs":4798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-266d14068dc8b304eeca","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify SSL cert upload with long filename and UI overflow handling","durationMs":5036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-47ed6f62b24203eb27e4","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should show service name error and not open modal when test connection clicked without service name","durationMs":3634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-8d4708988dded1567bfb","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should include service name in missing required field count shown on test connection card","durationMs":3546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-a047a9cda0d5b9f201b1","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify form selects are working properly","durationMs":8030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-a5c7eb4bf34fc5b40e02","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify service name field validation errors","durationMs":5813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-f0abdfb7867ffaf3d72d","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should focus the service name input when test connection is clicked without a name","durationMs":4141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-2135732f3cee91474e0a","project":"chromium","file":"Features/Tasks.spec.ts","title":"task link should NOT navigate to wrong URL like /table/TASK-xxxxx","durationMs":8744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-4cc20545f3ea89a5cb3f","project":"chromium","file":"Features/Tasks.spec.ts","title":"clicking task in activity feed should navigate to entity page with task tab","durationMs":13568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-5f056158560407af55cc","project":"chromium","file":"Features/Tasks.spec.ts","title":"accepting task without edit permission should be rejected by backend","durationMs":1046,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-70993b1999a80774e963","project":"chromium","file":"Features/Tasks.spec.ts","title":"should create request description task from entity page","durationMs":9546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-9d610b2a4bf240005c7a","project":"chromium","file":"Features/Tasks.spec.ts","title":"non-assignee without edit permissions should NOT see approve button","durationMs":9905,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-cca01761a6bce7840070","project":"chromium","file":"Features/Tasks.spec.ts","title":"task should appear in \"My Tasks\" filter for assignee","durationMs":9312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-ce441478210b113bc6e8","project":"chromium","file":"Features/Tasks.spec.ts","title":"task count in Activity Feed tab should match actual tasks","durationMs":9659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-ce84dc240cc971195d1e","project":"chromium","file":"Features/Tasks.spec.ts","title":"should create suggest tags task","durationMs":7663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-cf8f3ae2b0df3d4acbae","project":"chromium","file":"Features/Tasks.spec.ts","title":"should allow manual assignee selection when entity has no owner","durationMs":11110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-d0117757d14e7f9f21e5","project":"chromium","file":"Features/Tasks.spec.ts","title":"tasks should respect domain filter when domain is selected","durationMs":414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-e340914676cf0a37e04a","project":"chromium","file":"Features/Tasks.spec.ts","title":"/tasks/count API should return correct counts for aboutEntity filter","durationMs":38,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-e4cc23c6e6759c544109","project":"chromium","file":"Features/Tasks.spec.ts","title":"assignee should be able to approve task","durationMs":9582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-ecba6f0d13b071ccda94","project":"chromium","file":"Features/Tasks.spec.ts","title":"creating a task should appear in entity activity feed","durationMs":9454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9ad28d1300bc7e823686-45b8fb897f98a5e0274c","project":"ImportExport","file":"Features/LineageExportPNGSnapshot.spec.ts","title":"exported PNG includes edge lines between nodes","durationMs":15879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9afd1effa5e585c919c1-0202e91439f881e1c55b","project":"chromium","file":"Pages/AppStopRunModal.spec.ts","title":"should show stop button for running app runs with supportsInterrupt=true","durationMs":4714,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9afd1effa5e585c919c1-e120f5235a1f6bdd9b6c","project":"chromium","file":"Pages/AppStopRunModal.spec.ts","title":"should close stop modal when cancel is clicked","durationMs":6808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9afd1effa5e585c919c1-fc943d277ec271917f28","project":"chromium","file":"Pages/AppStopRunModal.spec.ts","title":"should open stop modal when stop button is clicked and call stop API with runId","durationMs":5774,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-0f35c21074decaa9ede6","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import full ODCS contract with all sections from test-data file","durationMs":6679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-192e2055cc5d10d95676","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import button disabled when schema validation fails","durationMs":8755,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-19d6c07cf1b64b9600ef","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with wrong kind shows error","durationMs":8761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-1b2d52f8844a5db4ab7c","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import malformed ODCS YAML from test-data file shows error","durationMs":7558,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-1dbb8d203da32d4198bd","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import malformed JSON shows error","durationMs":8460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-2a4f6681e24c3ed945c5","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with wrong apiVersion shows error","durationMs":8062,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-2f6345811939517d83af","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Merge mode - adds SLA to existing contract and verifies export","durationMs":9832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-31f5f908ebafe7e82206","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import invalid ODCS missing required fields shows error","durationMs":8575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-3ced6bde454b2b7e8dd5","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Schema validation shows warning when fields do not exist in entity","durationMs":7887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-3d1f611b09e8c9ef621f","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Verify SLA mapping from ODCS to OpenMetadata format","durationMs":9410,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-4006caf2f955fd60d10c","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS full contract and export both formats","durationMs":9288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-460adca51a4ffd67a61f","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS and export as OpenMetadata YAML","durationMs":8787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-4a8aff38de2e68a8df0b","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Single-object ODCS contract does not show object selector","durationMs":7912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-5eaab8c7bd23d55a1e79","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Export ODCS YAML and verify download","durationMs":9068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-5ef3cdccd67443bc6683","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS missing apiVersion from test-data file shows error","durationMs":6963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-6625cb02e6927aa9d5f5","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Schema validation shows loading state during validation","durationMs":7710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-6711a9829a0c3d96f2fb","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import basic ODCS contract from test-data file","durationMs":7157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-68261486d0f6a0937ae2","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with security/roles","durationMs":8642,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-69ef911b31d21c257033","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with SLA, modify SLA via UI, export and verify SLA changes","durationMs":9324,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-716a0af0d51f4b0c05a3","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"OM format export and import round trip - create, export, delete, reimport","durationMs":10444,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-7289ec2ac14dfd1f6f3f","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Create contract from UI, export OM format, import with merge, verify data","durationMs":10412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-7e6cc49f08adc16d1b20","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS missing status from test-data file shows error","durationMs":6940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-81f8e3c6a41a1ca48ae1","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with timezone in SLA properties","durationMs":9469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-85188b1415ad6420ab68","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import minimal ODCS contract (inline)","durationMs":8785,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-8abf2104f87c2c423be3","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS contract with draft status from test-data file","durationMs":7565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-8f5576117ee809a480e6","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import button disabled for empty/invalid file","durationMs":8529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-955bd6b3717101c17e96","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import modal shows contract preview","durationMs":7940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-9bd1f1c0379d9ba1bc85","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Multi-object ODCS contract - selecting object enables import and completes import","durationMs":9483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-9cbea79159672c071dca","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS, modify via UI, export and verify changes","durationMs":10925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-9ecf02851221f72256af","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with quality rules","durationMs":7972,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-a067522af929e79d8feb","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS contract with v3.1.0 timestamp types from test-data file","durationMs":6830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-a739845e4bd30e73b5ca","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import malformed ODCS YAML shows error (inline)","durationMs":7703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-b6dd2e6c92f5df98758b","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import empty ODCS file from test-data shows error","durationMs":7416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-bf1bae508168e3d1e634","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with missing kind shows error","durationMs":8843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-c0fa5a97a138476da251","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Replace mode - replaces existing contract completely and verifies export","durationMs":10131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-cdde1df839425a25a0a1","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import basic ODCS contract from JSON file","durationMs":6204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-d6cd55a44daa5b90e276","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with team owner","durationMs":8452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-d811f2d3334254dcd9ed","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with team - contract created successfully","durationMs":8537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-d9eb674411099336a31c","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with description and verify OpenMetadata export","durationMs":8764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-e2b3327bc7912c609caf","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS contract with SLA properties from test-data file","durationMs":7219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-e6894a820e4c2bd0b240","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Multi-object ODCS contract - object selector shows all schema objects","durationMs":8847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-ed87d9c194896f26bca4","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import and Export round trip preserves data","durationMs":9131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-f28fe520f971d27d8446","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import modal shows merge/replace options for existing contract","durationMs":9096,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-fd4e6a08a2e6352429e4","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Schema validation passes for contract without schema definition","durationMs":8769,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-fd4fe81957752c4ec749","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with markdown description and verify proper rendering","durationMs":8198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-ff3c5fa9f1add6937c34","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Multi-object ODCS contract shows object selector","durationMs":8624,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-ffaf98193d721452ffae","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with mustBeBetween quality rules","durationMs":8721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-18e907f752a27b9fd8f4","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should remove color style from term via API","durationMs":5339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-2e06e5f79b5342eb895b","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle slow network gracefully","durationMs":6619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-4be98a038f7f6d90544c","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should toggle right panel if available","durationMs":11794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-60f3a3a6f980a1710221","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should maintain session during normal operations","durationMs":12234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-71c925d8cc7e6e9e0f84","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle multiple rapid API calls","durationMs":4683,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-76908643a0ccaaad6346","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle concurrent edits gracefully","durationMs":5725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-878af780737d76e41560","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should show error state when navigating to non-existent term","durationMs":9328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-8a7c4e91436fda6d3935","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle back/forward browser navigation","durationMs":8799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-924d084a3f4444d723a0","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should show error state when navigating to non-existent glossary","durationMs":13279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-965c8728bc5707ff2891","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should display vote count correctly","durationMs":9765,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-9c0db9327f0f692940cb","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle rapid UI interactions","durationMs":8644,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-9ef033615f0c8e9adaba","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should access activity feed for comment deletion","durationMs":10319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-a80bbe7b29b7f5294127","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should create glossary with unicode characters in name","durationMs":7814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-cfc97af221ec552f6cea","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should navigate to activity feed for potential reply","durationMs":10503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-d637d349d549b264ba20","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should show loading state during navigation","durationMs":7596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-db81d92799b0260ba3e1","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle deep nesting","durationMs":7605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-dd0193b528ac0cc08e96","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle special characters in search","durationMs":9148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-ddf92ab2430d94cef427","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should validate reference URL requires http/https prefix when creating term","durationMs":10702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-e1d992484f80ae957313","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should access activity feed for comment editing","durationMs":10468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-ecb9d2b60fc9eca2443a","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle unicode and emoji in description","durationMs":5124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-ed70fc607bee136a3107","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should remove icon style from term via API","durationMs":6249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-f43f9cd9f7fbd515d485","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should validate reference URL requires http/https prefix when editing term","durationMs":9918,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-f8941f3c4da10be24228","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle special characters in term fields","durationMs":5512,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-1335947fa4b03d96813f","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"emoji reactions can be added and toggled off on a feed card","durationMs":21708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-31479e975ac3666e1eb9","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Activity is NOT fetched on the Tasks tab","durationMs":22282,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-35c570d98d2467d720f3","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"All tab shows BOTH the change-event activity and the conversation","durationMs":13414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-46b3850bbde88dd8310d","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"clicking title navigates to explore page","durationMs":12930,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-4d4b4e89a4ca2e98410f","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"A change-event activity is read-only (no comment editor)","durationMs":13819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-61bc9c12ef74eb4cf8a2","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"feed body renders seeded activity and no empty state","durationMs":10735,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-64596f97a3fbdf51e660","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Auto-selects the first (newest) item on load","durationMs":16854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-68489d3f1d6a2809b41b","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Mention notification shows correct user details in Notification box","durationMs":53792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-68f33945efb071cc7b3c","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"All badge, header and rendered list agree on the count","durationMs":14770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-83cf6e6b868810252caa","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Should encode the chinese character while mentioning api endpoint","durationMs":28053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-a51da9cec73635e3f956","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Reacting to an activity updates its reactions in the right panel","durationMs":16819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-b34a388652104d9c2adf","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"renders widget wrapper and header with sort dropdown","durationMs":13301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-b7a79cfd6d332ab6a9ef","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"feed cards render header text and timestamp","durationMs":15249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-b917a15ff5b8cef9a210","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"activity cards expose no thread affordances on the landing widget","durationMs":11975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-cad6a5c4e6a065a22382","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Replying to a conversation stays isolated to that thread","durationMs":17849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-e3bfaac1e8763ed104e3","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"changing the filter refetches from that filter endpoint","durationMs":17401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-fe5f04441aa37dd7e33b","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"footer view more navigates to the user activity feed","durationMs":17528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-11140668a17507e05e02","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should decline suggested tags for a container column","durationMs":21111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-3fba22fa292eaa50e22d","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should add and accept requested tags for a topic schema field","durationMs":18751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-9dc22a9af80b1fa9cfae","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should edit and accept suggested tags for an api endpoint response schema field","durationMs":20504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-9fed25271f4f186bfcc7","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should add and accept requested tags for an api endpoint request schema field","durationMs":19759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-ba77fe27b9c8b69516b3","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should decline requested tags for an api endpoint request schema field","durationMs":19926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-d0551ac8b9f8301ca2c4","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should add and accept requested tags for a table asset","durationMs":21357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-d531746745c03d1762f1","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should edit and accept suggested tags for a table column","durationMs":20585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9ed17cc140d9dae5cefa-915b82974cf126a20c07","project":"Basic","file":"Pages/SearchIndexApplication.spec.ts","title":"Search Index Application","durationMs":94456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f4a33ecae6044b97b31-397a31ef612a9cd22653","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":24529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f4a33ecae6044b97b31-39f179a759a52a3cf6bf","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":23537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-0c77063b075cd2218b64","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Add multiple assets to domain at once","durationMs":23815,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-150901c3f10832888634","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Domain expert can edit domain description and tags","durationMs":10740,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-15e005f1d34e3a6e91bb","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User can access subdomain details page","durationMs":9937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-1fd742df39877e21d187","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Create domain with Consumer-aligned type","durationMs":5868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-282c644961afe61e396f","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User with domain policy is restricted by policy rules","durationMs":7321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-324394d635553ef6bbd9","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Move assets between data products","durationMs":16504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-32f02b57703f0fd30474","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Remove multiple assets from domain at once","durationMs":26583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-4dcdd2eebb877744a5c5","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"cancel on remove warning modal keeps the asset in the domain","durationMs":15493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-56b6436ccda2c8b73c52","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Domain expert can manage data products","durationMs":9876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-666ba1d32392604cd1bc","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User with domain access can view subdomains","durationMs":10119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-819313d6cecc45fab023","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Search for domain by name","durationMs":6707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-8dc0507b83acfc53b208","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"bulk remove with linked data product shows preview and commits on Remove Anyway","durationMs":16006,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-8e3f81f3f90e64078015","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Domain version history shows changes","durationMs":6603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-955a8dbabb161a4beaa0","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Move table from one domain to another via API","durationMs":15621,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-ab211f09d5811053d09e","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Data product version history shows changes","durationMs":6190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-adaeb2de85e70d54ae8b","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User can access assets in their domain","durationMs":6612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-c69dc92b1359a41fe17a","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Admin can edit domain description","durationMs":8665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-ce0ffa999074479a54bc","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Filter assets by domain from explore page","durationMs":10057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-d37104457e75884f3713","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Create domain with Source System type","durationMs":7384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-d9bf6730027f5b915dd3","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Move asset from domain to subdomain via API","durationMs":9619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-de11d803d3ba43723914","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"single-asset remove with linked data product shows preview and commits on Remove Anyway","durationMs":15973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-e563dc0fe24a7af54e2e","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Admin can edit data product description","durationMs":8909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9fe7868e0725fd08d542-2a33bc057bd25c30e0df","project":"chromium","file":"Features/GlobalSearchSuggestions.spec.ts","title":"Navigate to column from column suggestion","durationMs":10511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a0186dbcfd84f2af2f9f-a40369a24b242b3392ec","project":"Ingestion","file":"Features/SchemaSearch.spec.ts","title":"Search schema in database page","durationMs":5189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-0ae2bb3733d624c024dd","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"unchecking a section removes it from the save payload","durationMs":8333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-128faf764b2094a1dd47","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"blocks saving a rule whose name already exists","durationMs":6858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-13f15301823fa7fc290e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"fully-completed Service Is condition allows save","durationMs":9213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-165117ac5003f66952d3","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"reverts the enabled toggle when the settings update fails","durationMs":6763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-181d99405195b5be8571","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"measures the large-document preview render cost","durationMs":8905,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-1b2cccd7ba58f5524ae5","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"View in Explore link href reflects the selected entity type","durationMs":8767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-25e888b3698832fb24e1","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"preview modal closes via the Close button","durationMs":7544,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-40a176725b94f0690dfe","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"saves a rule that has no filter conditions entered","durationMs":7976,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-415ad87de311a2b1b6a4","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"closing the edit drawer without saving leaves the rule card unchanged","durationMs":7298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-4480787c897bd9dc2248","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"blocks saving a rule whose condition has no value entered","durationMs":8888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-6a82cd78885e2806d215","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"builds real version history and restores an earlier version","durationMs":7861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-8090445d856b4d0cd9e8","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"configures every entity type, behavior, section, filter, and setting","durationMs":13793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-828ef3dceb665f378f3e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"links View in Explore to the entity-type explore tab","durationMs":7094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-8dfdf276499f70900418","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"rule card displays the matched asset count returned by the server","durationMs":6103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-98bada33ef80e6d7e279","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"Custom Properties filter sub-fields load instead of showing No data","durationMs":6167,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-9aaf50b5db8b4df00c5c","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"previews one byte-consistent document in rendered and raw modes","durationMs":9602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-9c68cfb1faff12a1f1c0","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"compound OR conditions are serialized into the save payload","durationMs":10794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-a4b6b4cc72eb7ef6e32b","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"retries the preview after a failed document load","durationMs":7832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-b7fd2e2cd7de95d73f93","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"round-trips real configuration, rule CRUD, and preview endpoints","durationMs":320,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-b96d656abfc8d38d7e1e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"shows the empty version history state","durationMs":6552,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-c7732c7d2e3075a25bfa","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"clears the filter error once the unfinished condition is removed","durationMs":8469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-cdf1397a75540445ad46","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"clears and persists the character budget and cache TTL","durationMs":6934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-ce5988a4f5195a6025f0","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"edits and deletes a persisted rule and returns to the empty state","durationMs":9952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-cfcd775ce0067edae694","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"rolls back the optimistic rule and toasts when the save fails","durationMs":7349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d03dca810159c545c5e5","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"failed cache state shows the failed badge and the compilation error","durationMs":6257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d5681daa733b359d418e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"stale cache state shows the stale badge on the settings card","durationMs":6289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d800895fca74449be850","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"shows the truncated count in the preview stats","durationMs":7247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d966f6ff2e1a264ff9dd","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"rule description is included in the save payload","durationMs":7715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-ee53f7c7d6fb560349ca","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"surfaces the generating cache state and settles to fresh","durationMs":9847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-12ea21bc43a14aa83acc","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Certification field","durationMs":11702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-246e661506d36a1825dc","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Domains field","durationMs":10971,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-28f6e412ffc6df40796a","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Tags field","durationMs":8880,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-6741225215bb41e46a05","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Database field","durationMs":13603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-91cd076c579f49087395","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for API Collection field","durationMs":10188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-9e5984c4da4bd77a035b","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Database Schema field","durationMs":11953,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-b66659cc52783fdf9373","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Glossary field","durationMs":9572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-d47b5c11bf1fb831cc62","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Data Product field","durationMs":10707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-e22c85dbbb620fba80b6","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Tier field","durationMs":10496,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-009d9c01a74b2fc9aee4","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Verify columns are visible in explore tree hierarchy","durationMs":8362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-020e72fabdce33d085db","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link button should copy the field URL to clipboard for SearchIndex","durationMs":13882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-17559e58aad3ece85d94","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Check listing of entities when index is all","durationMs":5220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-237705007de3a03c4b7b","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link button should copy the field URL to clipboard for APIEndpoint","durationMs":13780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-363cdb367cd5173de8de","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Explore Tree","durationMs":9911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-39d0a4ec826f84977548","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Check the listing of tags","durationMs":8735,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-3ce419b0b546761dee81","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Verify Database and Database schema after rename","durationMs":15290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-4ebd5bf5ff4dfe3d77ef","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Check listing of entities when index is dataAsset","durationMs":5653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-6b458a8502d75fbed179","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link should have valid URL format for APIEndpoint","durationMs":16919,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-95045ebebe3be165bea5","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link should have valid URL format for SearchIndex","durationMs":18190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-99044d1988ae10656e86","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Verify charts are visible in explore tree","durationMs":12813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-990a0328aaf5e714a575","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Clicking Columns node filters search results to show only columns","durationMs":9656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-d04d62e4248018c26b48","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Verify Database and Database Schema available in explore tree","durationMs":8266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-da2efa16e6d48290a45c","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Verify Tags navigation via Governance tree and breadcrumb renders page correctly","durationMs":7005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-10b386b2aacc3b6d727e","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only VIEW cannot PATCH results","durationMs":16748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-142636b5255a95e79080","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TABLE.VIEW_TESTS can view test case and results in UI (alternative)","durationMs":22020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-3963fdcac9489a95ffa4","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only TABLE.DELETE (no TEST_CASE.DELETE) cannot DELETE results","durationMs":26442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-44ca4292889113c47191","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only VIEW cannot see edit action and cannot POST results","durationMs":16989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-458487367c118e1442da","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view test case and results in UI","durationMs":21442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-461ccb242873c7e52186","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TEST_CASE.EDIT_ALL can see edit action on test case","durationMs":17771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-6a3dcd200430fdb22666","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TABLE.DELETE + TEST_CASE.DELETE can see delete option for test case","durationMs":18278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-87ff09dffe6df7343c00","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TABLE.EDIT_TESTS can see edit action on test case (alternative)","durationMs":19476,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-a7bebf9b05558d999a1b","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only TABLE.EDIT_TESTS (no TEST_CASE.VIEW_ALL) can still view results in UI via TABLE.VIEW_TESTS","durationMs":9952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-c1ce7eca2ef10ed65ea3","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only TEST_CASE.DELETE (no TABLE.DELETE) cannot DELETE results","durationMs":25861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-e8a653dfadd848daaadd","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view test RESULT CONTENT in UI","durationMs":11549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a45d1fef427e51507f17-4849e68d9f25db425e8f","project":"chromium","file":"Features/LanguageOverride.spec.ts","title":"App language should override browser language on landing page and user dropdown","durationMs":9749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-4bc0e6edaa3ee5e42269","project":"chromium","file":"Features/Topic.spec.ts","title":"Copy field link should have valid URL format","durationMs":15875,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-5f9f332c0569746f0158","project":"chromium","file":"Features/Topic.spec.ts","title":"Copy nested field link should include full hierarchical path","durationMs":15939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-72ed26bcb15b71c6c253","project":"chromium","file":"Features/Topic.spec.ts","title":"Copy field link button should copy the field URL to clipboard","durationMs":11538,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-fbfc851a2c0e73a5f14d","project":"chromium","file":"Features/Topic.spec.ts","title":"Topic page should show schema tab with count","durationMs":8995,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a59d6b7c9ea22f8d26d1-93579c51cbed397e9691","project":"Reindex","file":"Features/SearchSeparation/DomainRenamePrefixCascade.spec.ts","title":"domain prefix rename keeps linked asset domain reference consistent","durationMs":978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a6994b74a6f977f55289-e72f2d4a951041c36cef","project":"Basic","file":"Features/DataQuality/TableTestCasePagination.spec.ts","title":"renders pagination and navigates when test cases exceed the page size","durationMs":7414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-09775213f3613c59416b","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display test definitions table with columns","durationMs":9133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-253b00b0981e1e2a783f","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should handle external test definitions with read-only fields","durationMs":14431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-28bcc3dbcea1ef961645","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display pagination when test definitions exceed page size","durationMs":8577,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-3dde97e966710259e666","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should not show edit and delete buttons for system test definitions","durationMs":7913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-3dfa7d5d186ea5d05eda","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display test platform badges correctly","durationMs":7790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-4c71c4955b660cfea637","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should disable toggle for external test definitions","durationMs":8103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-815b9cf7d82eb0cb5f0d","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should navigate to Test Library page","durationMs":8283,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-8c170a06fbda932dbf49","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display system test definitions","durationMs":8357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-8c3c478a7ed4dc0b0d82","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should handle supported services field correctly","durationMs":18428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-a6f857458ffc3102916c","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should require supported data types only when OpenMetadata platform is selected","durationMs":11171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-ae3d0ee4a3aa7eb16c12","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should maintain page on edit and reset to first page on delete","durationMs":16960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-b19e61f67023bc106e0c","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should cancel form and close drawer","durationMs":9136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-cf4dbef040a07d52aa1f","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should create, edit, and delete a test definition","durationMs":15049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-d0b196e35b293eca54cf","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should allow enabling/disabling system test definitions","durationMs":8622,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-df06e19168d3f9683dcb","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should validate required fields in create form","durationMs":9266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"acc5d0eeb3cee45912c8-eec5f01af3a022ae6d87","project":"chromium","file":"Flow/IngestionBot.spec.ts","title":"Ingestion bot should be able to access domain specific domain","durationMs":99221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ad818a91d010e372c30f-6defd7b1cd04246cf88b","project":"Basic","file":"Flow/Tour.spec.ts","title":"Tour should work from welcome screen","durationMs":7725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ad818a91d010e372c30f-9a8d36386767ad693933","project":"Basic","file":"Flow/Tour.spec.ts","title":"Tour should work from URL directly","durationMs":11886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ad818a91d010e372c30f-dc6831d44a4eda4a1911","project":"Basic","file":"Flow/Tour.spec.ts","title":"Tour should work from help section","durationMs":32434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-0d2a8343f2a5a121cb1f","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should render entity title section with link","durationMs":7154,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-0f78279b7cd0d2ea968f","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for dashboardDataModel","durationMs":6326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-18c7d8658b0b67febc27","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should edit display name from entity summary panel","durationMs":11202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-299bab0048d02d5a1ac1","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for databaseSchema","durationMs":6723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-4ccfbac3fd35b05b41ae","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display domain section","durationMs":6675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-4cd6a15a5a4f8e5fa548","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for table","durationMs":7718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-5974da0a98d9ff41bfef","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for database","durationMs":6771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-6e96b7009731b3128a6c","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display owners section","durationMs":6654,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-71b91d4510ddc05ada9d","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for dashboard","durationMs":6973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-9ee466321a0f343c2ebf","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display tags section","durationMs":6358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-b551fb9cd1206bb59afa","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for container","durationMs":7665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-bb37fdee3aa482bb760f","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for pipeline","durationMs":6678,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-c20815e6048903c01440","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should cancel edit display name modal","durationMs":10716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-de6f03d218c62993258e","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display description section","durationMs":6485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-e46c0fa6f29410cb4325","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should navigate between tabs","durationMs":5692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-e9ea0b76744be28bb3a9","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for tableColumn","durationMs":5361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-ec7d85f516045c6b6e83","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for searchIndex","durationMs":7383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-ee23b3ba8289eba1fc99","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for topic","durationMs":7466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-f6ec16f78eaf97f57e33","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for mlmodel","durationMs":7303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afb2f5a0d4a7b4e36b1b-300bb01fd40e114637cf","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":24593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afb2f5a0d4a7b4e36b1b-45178ac7f9360cca1780","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":23645,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-1b2fe4c0f4b3e40c68aa","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit description for knowledgeCenter","durationMs":8282,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-200ecb1a398820cba8d1","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Consumer to edit glossary terms for knowledgeCenter","durationMs":10068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2219de8dbcf16282e851","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Consumer to edit description for knowledgeCenter","durationMs":10107,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2adde21732850322e910","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update/edit tags for knowledgeCenter","durationMs":9925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2ce281911970fdcbad04","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"validates visible/hidden tabs and tab content for knowledgeCenter","durationMs":6296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2f0073a8f865128ed4f0","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should remove glossary term for knowledgeCenter","durationMs":14083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-431e80d685d3040a591e","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should verify deleted user not visible in owner selection for knowledgeCenter","durationMs":17980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-61dfa16835a0fc53a710","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should add multiple tags simultaneously for knowledgeCenter","durationMs":15592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-62c2c0de67ca104c110b","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should clear description for knowledgeCenter","durationMs":18378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-63aa7ba27f3e16c0b541","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update description for knowledgeCenter","durationMs":10612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-655098bd2e2891f71af6","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should verify deleted glossary term not visible in selection for knowledgeCenter","durationMs":14917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-77c03226c16367ca687a","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should remove user owner for knowledgeCenter","durationMs":96715,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"afc48ed87f02c4253cb9-7c35b7b765009e454966","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for knowledgeCenter","durationMs":6235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-b20ba9df57bb0bbeb9e5","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Consumer to edit tags for knowledgeCenter","durationMs":8925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-befd9930c632eef22c86","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit glossary terms for knowledgeCenter","durationMs":6420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-d3e2270239e49f6934d0","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit tags for knowledgeCenter","durationMs":9125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e39b2e3c5774cb85f940","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update owners for knowledgeCenter","durationMs":10453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e55d1d3c57e57a116537","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit owners for knowledgeCenter","durationMs":9898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e5b2e0783f40c95ca366","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update/edit glossary terms for knowledgeCenter","durationMs":10618,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e5dcf26ca9b2cb634758","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should verify deleted tag not visible in tag selection for knowledgeCenter","durationMs":16441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-edf1487a938c1cea5168","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should follow Data Consumer role policies for ownerless knowledgeCenter","durationMs":19316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-f603a841c789bd2d4743","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should remove tag for knowledgeCenter","durationMs":15091,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-08f24e3da77cd21ce3b3","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edits only selected metric rows","durationMs":7028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-178e2b77ae6556aa3efc","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Adding a new metric row shows CREATE badge once name is filled","durationMs":6783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-2777402b380093228942","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Custom metric editor role can import export and bulk edit metrics","durationMs":15914,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-2af739fb696d58987e61","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin can cancel a metric import mid-flight and cancel API is called","durationMs":8909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-591a014ecb6929685d23","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage unchecking header checkbox clears the selection bar","durationMs":5444,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-6b17e53c8020ed09e983","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"New metric row without a name shows error pill and SKIP badge","durationMs":6301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-6c741b436f4e5a01b0ad","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edits filtered metrics from the listing API without export jobs","durationMs":19609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-76711958c8d3b0e576ea","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Cancel from metric bulk edit returns to the metrics listing","durationMs":7917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-7daeb1a73fe3cc3529a7","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin imports a metric CSV through preview and async apply","durationMs":19623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-85ed20b16efbca3760aa","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Restricted roles cannot access metric import or bulk edit","durationMs":41097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-a3f990ae4c749a36d952","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edit renders complex fields from listing hydration","durationMs":6640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-b003905d27f3c841d948","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Bulk edit grid shows NO_CHANGE badge on unmodified rows","durationMs":6553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-b42b25528f0bc555a130","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Clearing the bulk edit search box restores all rows","durationMs":4961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-baa952ede54ac2d44a2d","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage header checkbox selects all visible metrics","durationMs":6342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-c9058e368b41cced0d25","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin imports a CSV update for an existing metric","durationMs":20312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-d618b90203504b6eb375","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage clicking the row checkbox selects without navigating","durationMs":5193,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e593eda82739e1962b02","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edit keeps text edits on blur and can revert to no changes","durationMs":5183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e73a3bbef909ec39ca07","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edit hydrates filtered metrics across cursor pages","durationMs":5668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e7724451b74703d8bd55","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin starts exactly one async export job from the metrics listing","durationMs":6307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e7fecf7152863cfba0d2","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Bulk edit grid search filters rows to match the search term","durationMs":5616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e96615940597b28ada02","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage clicking anywhere in a row navigates to metric details","durationMs":5125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-ebb437f18124523e7ce3","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Removing a newly added metric row restores the grid state","durationMs":5801,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-ef81d70712fff3b3f5d7","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin sees metric CSV validation failures for missing names and invalid references","durationMs":10224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-ff1aaa2410e296101d5d","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Bulk edit grid shows UPDATE badge and increments summary after editing a cell","durationMs":5908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b1b675f17c811fa8c75f-2df47237b83960fcce36","project":"chromium","file":"Features/DataProductDomainMigration.spec.ts","title":"Data product remains visible after moving domains and deleting the original domain","durationMs":15083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b1b675f17c811fa8c75f-5843ab60a742af1caac8","project":"chromium","file":"Features/DataProductDomainMigration.spec.ts","title":"Data product with no assets can change domain without confirmation","durationMs":15751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b1b675f17c811fa8c75f-82e7f9a502c188f6f02d","project":"chromium","file":"Features/DataProductDomainMigration.spec.ts","title":"Changing data product domain via API migrates assets to new domain","durationMs":29024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-023d22dc39c48e8d53f4","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.VIEW_BASIC can view test case in UI","durationMs":15526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-225d15df6f71e5d6038d","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.CREATE cannot delete test cases","durationMs":16506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-2344f0d9500623421fb8","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer cannot create or delete test suites","durationMs":8721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-36d66c70ea2381068e2d","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer can VIEW test cases but sees no edit controls in UI","durationMs":16369,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-3b2675937f5dccd75d2f","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.DELETE can see delete option for test case","durationMs":15731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-41cfeb97e29ffcfe25f5","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.VIEW_ALL can view test suite CONTENT but cannot add test case","durationMs":10629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-505fe28532602c99aab7","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer cannot edit test case","durationMs":15250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-597de0139daf1d0e4d01","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Steward cannot create or delete test cases (default)","durationMs":17303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-7805715b82208927b353","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Admin can see Data Quality UI controls (add test case, add test suite)","durationMs":16876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-7a64848a6500dadc0c80","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.DELETE cannot create test cases","durationMs":16789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-7a85c789b019754693f6","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.CREATE can see Add test suite button","durationMs":11173,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-867f3068db9da0d14660","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.EDIT_ALL can see edit action on test case","durationMs":16111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-8d4b1e27cb6ab75b49f4","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.VIEW_BASIC cannot edit test cases","durationMs":17036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-9d7d81e12e2bea1146ad","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.CREATE can see Add button for test case","durationMs":16620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-a12338af018616a5c43d","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.VIEW_ALL can view test suites page and list suites","durationMs":10970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-bf3ff4cd06cdb0ec6934","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.VIEW_BASIC can view test case CONTENT details in UI","durationMs":20844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-c53bcbe763c0939caa91","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.EDIT_ALL can see add test case button on suite details","durationMs":11301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-cfbd7e7f4484702c01f0","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TABLE.VIEW_TESTS can view test suites page (alternative permission)","durationMs":10456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-cfbe5dcb809fce114ce5","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with VIEW_BASIC cannot see edit action in UI","durationMs":15593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-d7319bc5b90ed2cb0a11","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User without TEST_SUITE.EDIT cannot add test case to logical suite","durationMs":11575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-e280555757f349c72854","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer cannot create or delete test cases","durationMs":16914,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-e4e1a2ebe615aae2117c","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TABLE.EDIT_TESTS can see edit action on test case","durationMs":16332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-eae7b64629c9d1a12de2","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User without TEST_SUITE.DELETE cannot delete test suites","durationMs":10821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-f34cdcd4f8d4edd4cdfe","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User without TEST_SUITE.CREATE cannot create test suites","durationMs":9818,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-ffe3f0d85ac3d552eb09","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TABLE.CREATE_TESTS can see Add button (Table Permission)","durationMs":16041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-07c6afb9a23ebfeb2a6b","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Data product linked to subdomain","durationMs":6218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-0921be7b13e4f8bb54b9","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Navigate between sibling subdomains","durationMs":9431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-1b8348aa29026ad058d3","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Search data products by name","durationMs":7721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-22b7e17ead94a9522c35","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Search data products by name","durationMs":6400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-474ca9f2afe893e8b7ac","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Create nested subdomain (subdomain of subdomain)","durationMs":9226,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-5783990ffbdcaeb86ef5","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Entity name cell shows both display name and name","durationMs":7829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-6dbb46279d8e346845b4","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Filter data products by domain in global selector","durationMs":12470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-720615fe1fb8b4168b26","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Assign assets to different subdomains","durationMs":14130,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-73dc3ed8540a79ec973c","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Delete subdomain with data products shows proper cleanup","durationMs":10689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-7d6b5a8d9596aebe56a3","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add expert to data product via UI","durationMs":8754,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-81165f95ed1499970253","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add tags to data product via UI","durationMs":8086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-91793eae76cc059f0892","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add assets to data product and verify count","durationMs":9440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-adf89ee01b3fc4f97129","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add-Assets drawer quick filter - behaviour matrix","durationMs":13043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-b492800937e43dace798","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Edit data product description via UI","durationMs":8036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-c0f886b6be5ebe890a69","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Create multiple sibling subdomains under a domain","durationMs":7063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-c332ba9a2b88fe69b9cd","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Create data product via UI with description","durationMs":9343,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-cb1344fd55e961f79574","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Data products under different subdomains","durationMs":10572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-ffec821644fa472c4af7","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Subdomain assets count reflects in parent domain","durationMs":12192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-197763039c01ba157836","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Owners filter for Lineage","durationMs":12479,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-2c56f77f0afe01f5283e","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage service filter selection","durationMs":37822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-5901fe256dc6d4261268","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Tag filter for Lineage","durationMs":12767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-60b7003c6bf6f5744f3f","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage schema filter selection","durationMs":11048,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"b239f9808ff1b1045021-6e20bd657decc40af6c7","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify LineageSearchSelect in lineage mode","durationMs":12348,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b239f9808ff1b1045021-70762ee7ffaf711b90f6","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Tier filter for Lineage","durationMs":13272,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-76596bc125ee10098e5c","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Impact Analysis service type filter selection","durationMs":16085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-7ae9968177c8c6307df6","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage filter panel toggle","durationMs":6596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-886f4edb739677df5421","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Domains filter for Lineage","durationMs":14074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-ba38e82802a16ac8b3c2","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"verify upstream count for all the entities","durationMs":104905,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b239f9808ff1b1045021-e36a3455bccfbb250aa8","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Impact Analysis service filter selection","durationMs":23908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-e781b4dbfe0117c8e731","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage database filter selection","durationMs":10071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-eb93467a60001bf9c40c","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage service type filter selection","durationMs":40702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-faeb0eea7f413d0942a1","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage column filter selection","durationMs":10402,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b239f9808ff1b1045021-ffd6ada4fc4adecb41b8","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"verify downstream count for all the entities","durationMs":127066,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b4b9aac556686af843f1-1ee660123e4e2cf43b3d","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should create term with all optional fields populated","durationMs":13677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-63880e3b520f38fa0e1c","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should add and remove related terms from glossary term","durationMs":8302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-87e39a7c7fc3fd2476a4","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should keep multiple relation types for the same related term across reload","durationMs":12254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-c2f9db0d41f956eccc6b","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should add and remove synonyms from glossary term","durationMs":7793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-c368857de9562394274c","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should edit term via pencil icon in table row","durationMs":7502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-d58ed71b3e1a1f7f3079","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should verify bidirectional related term link","durationMs":8666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-f5dc38dfffc509f2dc8e","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should add and remove references from glossary term","durationMs":8819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-1eb38a10ca22dc7e41b9","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab is not visible for other applications","durationMs":6201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-8c55296c911ed9b878fe","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab shows empty state when no records","durationMs":6492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-bccbe41b46287af5da95","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab displays records with correct status badges","durationMs":5615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-f6f19e89bc91d7bbaef2","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab is visible and loads data","durationMs":6240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b5ac74643fe7ba2d8fe3-ce9f73536f00a5d45e01","project":"Reindex","file":"Features/DataQuality/TestSuiteSummaryAfterReindex.spec.ts","title":"Test suite lastResultTimestamp survives a full entity reindex","durationMs":1183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-0548815eb142c00104e1","project":"chromium","file":"Features/Table.spec.ts","title":"Tags term should be consistent for search","durationMs":18010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-12dbdff48f072e317aba","project":"chromium","file":"Features/Table.spec.ts","title":"Search for column, copy link, and verify side panel behavior","durationMs":28002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-1778f18ede2a1820b4d5","project":"chromium","file":"Features/Table.spec.ts","title":"Table filter with sorting should work","durationMs":7245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-17efa24eeee45d8e3bef","project":"chromium","file":"Features/Table.spec.ts","title":"expand / collapse should not appear after updating nested fields table","durationMs":28790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-2fb31f7270b5a3caefb9","project":"chromium","file":"Features/Table.spec.ts","title":"should persist current page","durationMs":10575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-55f37c83b82714bc44fe","project":"chromium","file":"Features/Table.spec.ts","title":"Table search with sorting should work","durationMs":7152,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-5faa0ca4d02a0d62d909","project":"chromium","file":"Features/Table.spec.ts","title":"Table page should show schema tab with count","durationMs":6738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-66a209a1e3b6ada95aa1","project":"chromium","file":"Features/Table.spec.ts","title":"Glossary term should be consistent for search","durationMs":13075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-930ae77b2adf34892aed","project":"chromium","file":"Features/Table.spec.ts","title":"should persist page size","durationMs":9764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-9a7b47c6d7d4c115c405","project":"chromium","file":"Features/Table.spec.ts","title":"Table pagination with sorting should works","durationMs":6781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-b44fe1be53d0f0e7e757","project":"chromium","file":"Features/Table.spec.ts","title":"open-task stat shows the count and links to the Tasks tab","durationMs":6894,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-bc1c352c1584708aae20","project":"chromium","file":"Features/Table.spec.ts","title":"expand collapse should only visible for nested columns","durationMs":9429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-bf9aa70f500df59e999a","project":"chromium","file":"Features/Table.spec.ts","title":"source URL button links to the configured source","durationMs":7463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-d5b31f77c93ec1b8e2b9","project":"chromium","file":"Features/Table.spec.ts","title":"should show dbt tab if only path is present","durationMs":9650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-fd7508676be39f5779fc","project":"chromium","file":"Features/Table.spec.ts","title":"should show dbt tab if only source project is present","durationMs":9910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-067f93c6eeb260535c41","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Editor operations","durationMs":12404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-15e9f69ba626aec0884b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Quick link lifecycle validates, creates, edits, and deletes from card","durationMs":32083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-1a8244c504b33bd9537b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"displayName: switching articles does not bleed unsaved title into next article","durationMs":19456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-204381832cab1ede446d","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Editor operations","durationMs":12258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-24dc340d8dafc3a9667e","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Slash commands and basic blocks","durationMs":16899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-26157f59f7cb7332dc0b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Nested lists","durationMs":14095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-2ac62df99361241c8ae1","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article listing search filters, clears, and shows empty state","durationMs":15029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-2ba8f331893d4140692d","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Slash commands and basic blocks","durationMs":13676,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-30e867f4c2cb533197c0","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Content persistence","durationMs":15783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-33312fa3fcba8fd1eb7f","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Global search and Explore Knowledge Center filter navigate to articles","durationMs":12533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-3b4001e65d812e269530","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Nested lists","durationMs":13775,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-3d7c9dc3feed478080fe","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Content persistence","durationMs":21185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-3e336ce29aecac2276b5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article copy, delete, sidebar delete, and same-name recreate do not preserve stale metadata","durationMs":32857,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-44141f0094dacc65fb03","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Advanced blocks","durationMs":16721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-4651a3d8ca18fd5978a8","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article detail layout, drawer, activity tab, and version page work","durationMs":27015,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-51e828109a715ff2b402","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Advanced blocks","durationMs":16404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5caea89669fac360aeb4","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Left hierarchy pagination and expand collapse actions work","durationMs":23053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5d349d5ef24e6a752ff0","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article edit persistence and unsaved title behavior are correct","durationMs":50553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5e7ba62f70111436e4bb","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article card metadata, widgets, and listing search update from UI edits","durationMs":57697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5f9b4fb91211a9239460","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Text formatting","durationMs":15202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5fe7c1a8b26384d38c3a","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Slash commands and basic blocks","durationMs":14909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-68a6c0a93ff080139c4b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article tags added on the article page are visible in the Explore right-panel summary","durationMs":22133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-69f43bc4beb330d729a2","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Editor operations","durationMs":11990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-729476f400ca746921b3","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Empty article can be deleted immediately without polluting the list","durationMs":15810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-76e359fc969880358083","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Expanding a multi-level hierarchy does not throw and renders no duplicate nodes","durationMs":12111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-7c113e606a888c1f3f14","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Advanced blocks","durationMs":19282,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-81c3fb7f005013a8c26d","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Quick link created from API can be opened and deleted from hierarchy","durationMs":14978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-93a7f2bbd8e1b2c406fe","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"multiple articles hold independent drafts simultaneously","durationMs":26097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-9c5563ee05c5f3483575","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article list basics and creation entrypoints","durationMs":25662,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-b641a2040579b23d75c5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Related assets, activity feed, user mentions, and article mentions work","durationMs":46223,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-bb081fd8a6faef23cf41","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"draft cleared from localStorage when article is deleted","durationMs":26949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-cb1726ba98fa649c2682","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Nested lists","durationMs":12505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-d35e8e76a8cbb00b80cf","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Text formatting","durationMs":14527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-dafef3bc55c97adddca2","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"no spurious sync when content is already saved — no PATCH on clean reload","durationMs":19114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-e0fab1039a57c80c069c","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article list cards, recently viewed widget, and pagination work","durationMs":22383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-e4dd3c0f394f33812eb5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"draft syncs on page reload — skeleton shown, content saved","durationMs":13518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-ecee0ea08bf9947064c5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Content persistence","durationMs":21550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-efefa0a8bc5fbc7f29ae","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Quick link card opens the configured url in a new tab","durationMs":11145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-fa401e6d00626065b924","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"description: switching articles does not bleed unsaved content into next article","durationMs":23340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-faf8bd343ccd2da9f03f","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Text formatting","durationMs":14406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-feeaee8a079d7e5adfca","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Other user editing is visible in the article header editor list","durationMs":22261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-53ee56c1e5fef5ae703b","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"keeps the full Russian severity label reachable when the chip is truncated","durationMs":22000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-55282d41804a711d18ad","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"leaves a short severity label sized to its content, with the nav expanded","durationMs":21000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-8920f0ec33c9ca9955ab","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"bounds the Russian severity chip regardless of its column, with the nav collapsed","durationMs":30000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-982d99e87fec992b640c","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"never truncates a status chip, whose labels are longest in Russian","durationMs":21000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-9fb88b89adb2374cf977","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"leaves a short severity label sized to its content, with the nav collapsed","durationMs":21000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-af868572f1b5280abf4d","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"keeps the Assignee column on screen when the Russian severity placeholder is rendered","durationMs":31000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-dc07ec68eea589c12b0e","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"bounds the Russian severity chip regardless of its column, with the nav expanded","durationMs":31000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b833d1df0ed59e353274-cfcdbc6fef10b7352962","project":"chromium","file":"Flow/GlobalSearch.spec.ts","title":"searching for longer description should work","durationMs":9661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-0d0894d0eff588acbda5","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify tag filter for column level impact analysis","durationMs":10063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-0e2a39039601d66193f7","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify search functionality filters table results","durationMs":8437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-14ffe4f55cb631cf8053","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column level table has correct columns","durationMs":10106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-17e3e557dc5d7daf0a70","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify table columns visibility and content","durationMs":8706,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-45988883f9736aa212aa","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify impact analysis requests include entityType and explicit depth bounds","durationMs":9354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-4ab0e07a210458f91a36","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify glossary term filter for column level impact analysis","durationMs":11187,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-5c9c089589d1b6546ae9","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify node depth display in table level impact analysis","durationMs":9075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-5d1a8029ecad9ed2f200","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify upstream/downstream counts for column level","durationMs":17448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-6eb1d52223d4236a9d5e","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column mode switches direction with directional lineage requests","durationMs":15668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-a21ab6be616ec8d2b646","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"validate upstream/ downstream counts","durationMs":9203,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-b6bc96b8f727cbe93b20","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"verify domain for Asset level impact analysis","durationMs":10879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-bd2f8536c50f80a40c78","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column level upstream connections","durationMs":15709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-c5e909fa0bda66087277","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"verify tier for Asset level impact analysis","durationMs":10263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-c9f25440f3b28869b7f1","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column search in column level impact analysis","durationMs":11571,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-de731b18c2794ea1d269","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify Upstream connections","durationMs":15313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-dee5fc58e2ec8e454aea","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify service type filter for Asset level impact analysis","durationMs":9281,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-e501b68bc994f0c9a2a0","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"verify owner filter for Asset level impact analysis","durationMs":9188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-e9b173ac180a81ce4678","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify upstream downstream toggle persists pagination","durationMs":10904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-e9d899efa5a5e8c7852b","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column level downstream connections","durationMs":9085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-efe35888f94fa46c4770","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify depth configuration changes impact analysis results","durationMs":11671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-f938981feaa7b431fef5","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify entity popover card appears on asset hover in lineage-card-table","durationMs":9595,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-fa91fe5a25c3405e9b2b","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify Downstream connections","durationMs":15216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-fe838344992277ee44da","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify switching between table and column level clears filters","durationMs":10340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b9d345b1f0052cfce4e3-50adca26c4f0573f2431","project":"chromium","file":"Features/ServiceAgentsRefresh.spec.ts","title":"should refetch the agents list and nothing else","durationMs":6962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"baaea988202fec9da880-ce88b9d90ae9ffa0b5c6","project":"Ingestion","file":"Features/DataQuality/Dimensionality.spec.ts","title":"Dimensionality Tests","durationMs":8404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"bca4445f78bc23d9198a-2d3e5bd59f9abf98d8d0","project":"Basic","file":"Pages/Bots.spec.ts","title":"Bots Page should work properly","durationMs":36038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"be1908fe012aeef38284-23b97f41f72ab99a4a7a","project":"chromium","file":"Flow/PlatformLineage.spec.ts","title":"Verify Platform Lineage View","durationMs":83738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-112f974de894495fbe0f","project":"chromium","file":"Pages/Tag.spec.ts","title":"Tag toggle should be disabled for user without EditAll permission","durationMs":11624,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-21b333b8ba624e722147","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets for Data Consumer","durationMs":40556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-26de7b0bca5c04a95283","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Owner Add Delete","durationMs":23902,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-36fa997930433fb32eb8","project":"chromium","file":"Pages/Tag.spec.ts","title":"Restyle Tag","durationMs":17620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-43a3e97741d61e4e08ed","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets","durationMs":34072,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-4996201f40fba2b4706b","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets and Check Restricted Entity","durationMs":41944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-5529639e695d00eba7e3","project":"chromium","file":"Pages/Tag.spec.ts","title":"Certification Page should not have Asset button","durationMs":14892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-5d78f990ea88fe859e6d","project":"chromium","file":"Pages/Tag.spec.ts","title":"Edit Tag Description for Data Consumer","durationMs":14706,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-765dc0d5ad900f88800e","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Tag UI for Data Consumer","durationMs":18184,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-7781e587de258e712ab1","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Tag UI","durationMs":14652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-77fb8739144fe03d6137","project":"chromium","file":"Pages/Tag.spec.ts","title":"Certification Page should not have Asset button for Data Steward","durationMs":10730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-7c8d2d4b3a5a6b5c5885","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify tag enable/disable toggle","durationMs":13159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-c1a6747ea2611120acd7","project":"chromium","file":"Pages/Tag.spec.ts","title":"Create tag with domain","durationMs":17141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-c6f548dea68f98c1a019","project":"chromium","file":"Pages/Tag.spec.ts","title":"Certification Page should not have Asset button for Data Consumer","durationMs":12163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-cba3bfab34284be22556","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Tag UI for Data Steward","durationMs":13363,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-d0c11c5caf849cf711d3","project":"chromium","file":"Pages/Tag.spec.ts","title":"Rename Tag name","durationMs":20572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-dbf18648002dd3ebc901","project":"chromium","file":"Pages/Tag.spec.ts","title":"Edit Tag Description for Data Steward","durationMs":14478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-e25c1fb74b2b0468a491","project":"chromium","file":"Pages/Tag.spec.ts","title":"Edit Tag Description","durationMs":16936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-e535042dd7255d039f34","project":"chromium","file":"Pages/Tag.spec.ts","title":"Delete a Tag","durationMs":17642,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-ef2d4407841e571e6b90","project":"chromium","file":"Pages/Tag.spec.ts","title":"Tag toggle should be disabled when classification is disabled","durationMs":17162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-f4c820b1962c81bd03a4","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets for Data Steward","durationMs":32332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-180a75d5076d96f27c9e","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"team member should be able to approve task assigned to team","durationMs":13057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-212799dfdd593ee4c6ca","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"resolving task should require edit permission on target entity","durationMs":483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-231982a7067ce2e93f31","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"assignee should see approve/reject buttons","durationMs":6486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-3dac766449e6b290b2c9","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"admin should be able to approve task","durationMs":7791,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-8e21f7221e157bfcee70","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"recognizer-style data quality task should reject via /tasks/{id}/resolve","durationMs":4468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-8e4fd7cced46a3626635","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"owner/assignee with edit permission should successfully resolve task","durationMs":430,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-9aaa4c31cd0d498e6084","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"non-assignee should NOT see approve/reject buttons","durationMs":7671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-af01b3d405099b46a381","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"non-team member should NOT see approve button for team task","durationMs":13284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-f6dedc77d796ebcc1ac8","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"task creator should be able to close/reject their own task","durationMs":583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c149cc7f2afeaafc22a5-61cfff024ab316b5e7cd","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":25660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c149cc7f2afeaafc22a5-c2d70e372af0aacb7e7a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":24983,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c2f2fb43f3574526e3cf-47ef5a94739346607a50","project":"Basic","file":"Pages/UserCreationWithPersona.spec.ts","title":"Create user with persona and verify on profile","durationMs":11450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-01fad5a002847d8d58c0","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow adding a semantic with multiple rules","durationMs":11461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-0323470366a0f662aa12","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Store Procedure","durationMs":48504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-07cd60e8fb8b6f4d333a","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-189e36fb58340c1da0bc","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Database Schema","durationMs":43172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-25f202a29cb96dee010f","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":26192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-26840c03b806453e7fcc","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Semantic with Contains Operator should work for Tier, Tag and Glossary","durationMs":29883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-2d42dd2032ba827235d2","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Container","durationMs":42191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-39d6283757ce29d63cce","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Topic","durationMs":52603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-3c0a5f962a565d161122","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for SearchIndex","durationMs":49693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-3cb384ab3e3bfc745ae8","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-48ecd1973fefd27da4bb","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":24605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-4acb103d01514e7c8e4c","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for File","durationMs":41804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-5d1101e26207fbfe86fa","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":37821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6003134a749e5f980b90","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":24698,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6582ca87cba7ae106b27","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for MlModel","durationMs":45708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6a4cf3a311c440118bec","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":34806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6e4e567d889a4a7c6478","project":"Ingestion","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Table","durationMs":42758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-711bfe9176f5142d1380","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":29723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-72a144851856bc18e7c8","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":25131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-7512c8036edd600f06e0","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-7ad1c8de93884df3b4fe","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Worksheet","durationMs":48119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-7d700e25a598ac302bd4","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow editing a semantic and reflect changes","durationMs":10653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8069e46712c959e12df3","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Spreadsheet","durationMs":42216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8b603616c0839438800d","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Operation on Old Schema Columns Contract","durationMs":25659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8d0913db8fc367e458fd","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Semantic with Not_Contains Operator should work for Tier, Tag and Glossary","durationMs":41557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8f3a2bc034218b7f11f7","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow adding a second semantic and verify its rule","durationMs":20063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-914f9dfd0316df153e96","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Api Collection","durationMs":48638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-974ffe89078f5491207b","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Directory","durationMs":39810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-99df91fb3dd32d41f319","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":32117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-a3d274cc242d5d110427","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow deleting a semantic and remove it from the list","durationMs":17486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-a87bb726b61df4c7041d","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":40485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-b331405338cbb0ab4acc","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Nested Column should not be selectable","durationMs":14652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-b8223a97360afdf32065","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":38112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-b9d5c52175a64817de15","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Add and update Security and SLA tabs","durationMs":19532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-c4fa0bc60e2e6a8dd707","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":40341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d28de6dfa66c9a5efc16","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Chart","durationMs":46695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d668b72a65efdcabafb1","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Pagination in Schema Tab with Selection Persistent","durationMs":26573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d8147f11241541ff9323","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Dashboard","durationMs":38901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d8338405b37a0779887d","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":36774,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-dbf5e444accfa300b508","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"ODCS Import Modal with Merge Mode should preserve existing contract ID","durationMs":13656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-dc6f6a60c0682cee8023","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Database","durationMs":46240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-df38484d393a5065dad8","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":39246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-e377248f44940da3b646","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"ODCS Import Modal with Replace Mode should overwrite all fields","durationMs":14795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-e82f3725ee0553a9eeaf","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-e83c33dcd2e14a49b397","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for ApiEndpoint","durationMs":43346,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-f27dd1f4ed08302ad3fa","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":48698,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-fe80e1a6b808452d5670","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for DashboardDataModel","durationMs":41275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-fffaa929851105d619ee","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Pipeline","durationMs":52843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c39768dc6aa2e0276e68-10caaec99edb45710f85","project":"DomainIsolation","file":"Features/DomainIsolation/DomainTaskIsolation.spec.ts","title":"userA sees only their own-domain task","durationMs":3098,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c39768dc6aa2e0276e68-4f3310973531f919b5b8","project":"DomainIsolation","file":"Features/DomainIsolation/DomainTaskIsolation.spec.ts","title":"userB sees only their own-domain task","durationMs":3114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c39768dc6aa2e0276e68-da91b22f9303a7b822f0","project":"DomainIsolation","file":"Features/DomainIsolation/DomainTaskIsolation.spec.ts","title":"admin sees tasks from both domains","durationMs":4060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-2242f6cb6cab5485702b","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Widget drag and drop reordering","durationMs":15809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-6f0dbf5beb7bc3c697a2","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Cancel button should show a single confirmation modal and Discard should exit the customize landing page","durationMs":12400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-d2792ca6ac76dfdb0b60","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Check all default widget present","durationMs":8198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-e40a9d9532d26fa1fcf8","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Add, Remove and Reset widget should work properly","durationMs":23415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-0173c4913e3c4c2ceeac","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should support pagination and page size selection","durationMs":6166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-02767019d7873edaa6f6","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is restored","durationMs":14630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-029bce62073efbde0c0e","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is soft deleted","durationMs":13762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-102a6a666663aa204ff8","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should support multiple filters from different categories","durationMs":8137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-1542609facbc6309558a","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should include filters and search in export request","durationMs":6954,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-1718ce29678e9bfb5835","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should support case-insensitive search","durationMs":6869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-2c47025e103ba0cf18e5","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should complete export flow and trigger download","durationMs":13052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-31bc9a7d808b23935bf4","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should apply both User and EntityType filters simultaneously","durationMs":12958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-364093191ceee41ad0ef","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is hard deleted","durationMs":12422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-3761fc0928da9497c624","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should apply and clear filters","durationMs":7316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-3ab9ba83e401655059c9","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should handle audit logs access for non-admin users","durationMs":7493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-3bcbbb77fedde5a10c87","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display audit log entry in UI after entity creation","durationMs":7614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-4777f4d3e3c3581f8b00","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display list items with profile picture and user info","durationMs":5749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-52a0b9a9306a5955396c","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is created","durationMs":6707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-57dad4b9c1a39e25d0dd","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should verify complete audit trail for entity lifecycle","durationMs":24020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-5ff18772f15eae7292d5","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should verify search API returns proper response structure","durationMs":7133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-6c1cf735098804c92262","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should allow searching within User filter","durationMs":5894,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-6c2cbb1a4c0ab7593cbe","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should search audit logs","durationMs":8347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-73f0cb6723ad9eb2a8b1","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display entity type in list item metadata","durationMs":6763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-8bababb17ab053dd01bf","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should remove individual filter by clicking close icon","durationMs":7807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-a22442a667f924534986","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should deny export access for non-admin users","durationMs":5820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-bc6f6e1c30715e27cfcf","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should allow searching within Entity Type filter","durationMs":6824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-be673c6ff393f52ea948","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display page header with correct title and subtitle","durationMs":6452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-c2b2962c03fbe62d08e7","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is updated","durationMs":10229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-ded0959fe0acb519f6a6","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should validate export response structure","durationMs":6008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-eabfd904a9633233e517","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should replace filter value when selecting new value in same category","durationMs":6341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-f01b7d7c94af12be0cc4","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display relative timestamp in list items","durationMs":6478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-1e1c6cc845ecf39d2205","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can include three custom properties and require one for Data Product","durationMs":6321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-26d55d23606060e07469","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can remove included and required fields from the Domain intake form","durationMs":6685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-2a62a47a84b7cc428b4f","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting an intake form removes it from the list","durationMs":5284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-3519dafa5283f7746e3d","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"\"Data Product\" option is disabled when a form already exists","durationMs":4767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-58d8629ab3c486f2924f","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"required intake fields are submitted on create and omitted on edit","durationMs":6272,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-5d1a4b14949b0f9586c9","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can include three custom properties and require one for Glossary Term","durationMs":5368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-5f404feff62948446f45","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting a required custom property prunes it from the Glossary Term intake form","durationMs":4773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-6289854265d95dec9d0d","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can remove included and required fields from the Glossary Term intake form","durationMs":6741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-6dac8417d0d497aaac00","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting a required custom property prunes it from the Data Product intake form","durationMs":4730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-745ad2dbeb0baf7b89c9","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"Domain uses the shared reference and hyperlink intake fields","durationMs":5577,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-7a224ded94f3d9482d6d","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can open the Intake Forms settings page","durationMs":4540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-7ba93be75799bd8bb941","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"intake form — toggling enabled flips enforcement in listing","durationMs":4758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-a604d8c398d1b3c9e897","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can remove included and required fields from the Data Product intake form","durationMs":7271,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-aa15a66e0739e3407915","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"custom property required via intake form renders in Data Product create form","durationMs":6047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-ab8fd64d057f8b4e104b","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can include three custom properties and require one for Domain","durationMs":6209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-b83a4150530f02e4de1e","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting a required custom property prunes it from the Domain intake form","durationMs":4546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-b94a856ca3586b5fc175","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"designer does not list schema-required fields","durationMs":4542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-c1893bc7c79b8a2c6792","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"pick admin user → DP create succeeds with correct extension payload","durationMs":7921,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-cc65a75585a345725083","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"intake form with required field blocks Data Product create when missing","durationMs":6830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-e7165978ff4c41277836","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"delete popconfirm cancel keeps the intake form intact","durationMs":5319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-fb3de0f6b91c1640f58e","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"Data Product serializes each custom-property type for the create API","durationMs":9759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c701921c8f8a6352b747-1d0279d918ed98fbd853","project":"chromium","file":"Features/Glossary/GlossaryPersonaCustomization.spec.ts","title":"Saving a persona Glossary Term customization keeps Relations Graph visible on the term page","durationMs":26565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c701921c8f8a6352b747-3e4cbd0d17abcacbd4ae","project":"chromium","file":"Features/Glossary/GlossaryPersonaCustomization.spec.ts","title":"Customize UI lists every documented Glossary Term tab including Relations Graph","durationMs":8222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c701921c8f8a6352b747-6b7c8374eaa7bfc7561b","project":"chromium","file":"Features/Glossary/GlossaryPersonaCustomization.spec.ts","title":"Customize UI lists Relations Graph at the Glossary parent level","durationMs":9839,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-0324d60b6dbd8f8464f8","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Date picker shows placeholder by default on Incident Manager page","durationMs":5967,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-0e4423b59bb3b0def9f6","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should switch back to \"Created at\" and call API with dateField=timestamp","durationMs":6524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-125027e4b32a62c75284","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should show \"Created At\" as the default sort field label","durationMs":5814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-32d7e88cbf346af3509b","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Date picker shows placeholder when no date is selected","durationMs":8667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-4cdd71db2b45b447c142","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should switch to \"Updated At\" and call API with dateField=updatedAt","durationMs":6312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-7070354043463bf443d1","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should open sort field dropdown on click","durationMs":5895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-79b5270c77a649310404","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Select preset date range","durationMs":9584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-7c786efc5cc1d9524a5a","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Clear selected date range","durationMs":9307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-80618b8599611058eab3","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should close sort dropdown after selecting an option","durationMs":6080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-849cf580e259e941a478","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Select and clear date range on Incident Manager page","durationMs":7723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-f84790313494695fc98e","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Date filter persists on page reload","durationMs":12845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-501f5e15e901e7595667","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should count a run once when every step reports the same rows","durationMs":3743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-80f30314e037b61caf57","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should not treat a queued agent as complete","durationMs":4309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-aa3bafb435a4775d0dcf","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should open the run history drawer oldest-first with the newest run selected","durationMs":4680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-d7e791516d91072c1764","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should render the card run dots oldest-first with the latest one highlighted","durationMs":4687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-d9252481963da7628280","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should report the newest Metadata run rather than the sum of both agents","durationMs":3760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-23c1b9c19b77e1fc296f","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"exports a data product to a valid ODPS YAML document","durationMs":127,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-2d68245dcb607af8c0af","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"merge preserves the existing product domain and owners","durationMs":259,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-31ec80fca2a586fb193f","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"imports an ODPS document onto an existing data product via the modal","durationMs":10772,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-43821278f0e90b25159f","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"rejects an invalid ODPS document on validation","durationMs":15,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-77e3363f6dbe1ec9bec0","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"exports ODPS YAML from the data product manage menu","durationMs":7962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-89d478c0ae8f83c66123","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"name guard blocks a YAML whose product name targets a different product","durationMs":10247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-8a42f9aa131de5003d2b","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"edits data product metadata (type, visibility, priority) via the modal","durationMs":11863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-a9c2fd5fb6c0b42a6b96","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"name guard blocks a YAML with no readable product name","durationMs":10895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-bab6dc59de12de6a2338","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"validates an exported ODPS document as valid","durationMs":140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-c475de5d3a03ed61c517","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"round-trips an exported ODPS document into a new data product","durationMs":292,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c86397fc7242347df33b-dc47567d7f4a93925962","project":"chromium","file":"VersionPages/TestCaseVersionPage.spec.ts","title":"should show the test case version page","durationMs":10954,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-1744342f23a91efe2ac9","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display terms matching multiple selected statuses","durationMs":5453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-17aa0807877786e6d2a1","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should revert changes when Cancel is clicked","durationMs":5862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-290c0b0873f5187f1fe3","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Deprecated terms when filtered","durationMs":9242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-2e04698b958b1f4e22b9","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should return matching terms for search query","durationMs":4192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-497fd1b32f9258b6cdcf","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should maintain search when status filter is changed","durationMs":5358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-5988bf438e2f39e4958e","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only In Review terms when filtered","durationMs":8773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-5c5d66935a2f20a348b2","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Rejected terms when filtered","durationMs":8576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-71684791e23a0abe70af","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should paginate through search results","durationMs":6756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-7939c6042ce0adcaac14","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should maintain status filter when search is cleared","durationMs":5629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-81598be60b1e8ceceb18","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should restore all terms when search is cleared","durationMs":5275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-8388ea65928d980767ca","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should show no results for non-matching query","durationMs":4729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-9332080e850ab8fb8fd7","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display all terms when All is selected","durationMs":6513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-9c52dee2717033c6e708","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should apply status filter within acceptable time","durationMs":5060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-9fa4a97d5d3f5ab0ac59","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Draft terms when filtered","durationMs":9586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-c8d59fcb5e7f1932a6a5","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should reset pagination when filter changes","durationMs":8016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-dc48d37df803beca4aac","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Approved terms when filtered","durationMs":9325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-e4e0242ef9806b0b92bb","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should maintain filter state across pagination","durationMs":5204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-ea41c0a0b7941de733e5","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should filter search results by selected status","durationMs":5211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-fcff743587908a5e53e7","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should paginate combined search and status results","durationMs":7911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-1dbd614d29e180690a85","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should search for multiple values along with null filters","durationMs":17334,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-259e61db1c16d9ad2c56","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"sort order is preserved in URL when explore tree node is clicked after applying a top dropdown filter","durationMs":8095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-3c750142c90fdc4d2ea3","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"search dropdown should work properly for quick filters","durationMs":9422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-41d7cc4f62d5990c09ec","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"tier with assigned asset appears in dropdown, tier without asset does not","durationMs":8880,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-440fb6c33a860d6545a3","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should persist quick filter on global search","durationMs":10016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-6779cdbcc9be1e4ce757","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"tier filter option label uses original casing from _source","durationMs":9581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-6a16b691836f9597267b","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"service filter option label uses original casing from _source","durationMs":8020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-7ac27f96d42f8e47da96","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"selecting a tier filter shows only assets tagged with that tier","durationMs":8459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-7eae1a0879cfe84f3664","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"explore tree sidebar selection is not cleared when a top dropdown filter is applied","durationMs":8794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-848cdf4243eb28f21ee1","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"domain filter option label uses original casing from _source","durationMs":8507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-8d58a7be6a15f6cea337","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"tag filter option label uses original casing from _source","durationMs":6860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-b210b47079c7e8e1b96c","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"Filter by column entity type shows only column results","durationMs":6260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-c33910a88a1d9ed52dda","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"owner filter option label uses original casing from _source","durationMs":8284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-d8b943596fe73627a88c","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should search for empty or null filters","durationMs":19009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-dd2ed41905ade0359cc9","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should show correct count for tier filter options from aggregation","durationMs":7386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-dd9f678b3ba6fdaee2cc","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"breadcrumb shows the entity category and display name header should have highlighted terms","durationMs":6650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-54366d53e73519025581","project":"chromium","file":"Pages/Tags.spec.ts","title":"Classification Page","durationMs":37455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-584eb3fb0a38160ba39b","project":"chromium","file":"Pages/Tags.spec.ts","title":"Adds one tag and removes another in the same save preserves appliedBy on the kept tag","durationMs":10934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-816f4c77f914a4a50b2e","project":"chromium","file":"Pages/Tags.spec.ts","title":"Search tag using classification display name should work","durationMs":10570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-b188ae54e303d89cddb7","project":"chromium","file":"Pages/Tags.spec.ts","title":"Verify system classification term counts","durationMs":5347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-f2107feebb5f4a23b7cf","project":"chromium","file":"Pages/Tags.spec.ts","title":"Disabled tag should not allow adding assets from Assets tab","durationMs":13269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-ffaf7183a75f1eb38486","project":"chromium","file":"Pages/Tags.spec.ts","title":"Verify Owner Add Delete","durationMs":11982,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-1eb1b3406ab1523f2de6","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Pipeline Services with the tag","durationMs":17703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-22c58402d71610571ef9","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Mlmodel Services","durationMs":13583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-2bf7f552e5db3d18b8ca","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Container with the tag","durationMs":15253,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-315faad65c8ba4786093","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Messaging Services with the tag","durationMs":13837,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-42713439b68b86645f59","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Storage Services with the tag","durationMs":17325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-63da70180686ef526abb","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Api Services","durationMs":8675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-6f451e1ed0db30ada664","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Messaging Services","durationMs":15248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-73757c787b1e891e4942","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Dashboard Services","durationMs":18406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-80ec08540ad5cea8b4bb","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Database Services with the tag","durationMs":10807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-84c48a5cf550dc52c755","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Database Services","durationMs":14718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-9933c0dcae522f034354","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Storage Services","durationMs":16122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-ac002e6c6d6ef1577d60","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Database Schema with the tag","durationMs":12204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-b103417ab8c8c1e51644","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Database Schema","durationMs":14464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-b602604bfc080aa12682","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Database with the tag","durationMs":16911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-bc1209cc5597e98ef443","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Mlmodel Services with the tag","durationMs":11344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-bd75914d1b83464a8474","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Search Services","durationMs":17204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-d153874b1daabe75e2c9","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Api Services with the tag","durationMs":17543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-d52c7043aa0749c2f533","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Pipeline Services","durationMs":12381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-e55cee40e3dc00883adc","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Database","durationMs":15991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-ee63ecc5cd12d5f14e65","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Container","durationMs":18025,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-f299fb8782d3bc530837","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Dashboard Services with the tag","durationMs":12897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-f9fe927671719a4618d6","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Search Services with the tag","durationMs":11499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-05cc587e9bcc4ffc92a5","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should show correct last activity format","durationMs":4389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-185ba09a3ff40aadfbe2","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should show user displayName in online users table","durationMs":17585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-38ca992a32ea90db749c","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Non-admin users should not see Online Users page","durationMs":4796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-60029151e6f114b7185b","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should update user activity time when user navigates","durationMs":17066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-9635dbc86785af16b680","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should not show bots in online users list","durationMs":4786,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-b0a8e448e4aef58b283f","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should filter users by time window","durationMs":4793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-e0123993246421502cb5","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should show online users under Settings > Members > Online Users for admins","durationMs":4813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-0b48b047051e780992f2","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"an edge with the correct relationType exists between the term and its related term","durationMs":9341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-23f4dd06dfefb5daf1e5","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"the directly related term appears as a node in the Relations Graph","durationMs":9165,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-40326bcc58edf3800037","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"search in the term Relations Graph returns empty state when no term matches","durationMs":9686,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-42b334d07c7288f87fb7","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"Relations Graph tab renders the ontology explorer for a term with a same-glossary relation","durationMs":10136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-58f0495abfd1f627c778","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"all relation types from the same term appear as separate edges","durationMs":9938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-8446918a7f96b8df7a01","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"search in the Relations Graph filters to matching node and its neighbours","durationMs":9548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-93c4b3dab6eb63fdc804","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"cross-glossary related term has an edge to the viewed term","durationMs":9326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-ab0d405c8cc01c4864f2","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"the term itself appears as a node in the Relations Graph","durationMs":9378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-bb529b7f961d4f4e8a9a","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"unrelated term from the same glossary is NOT shown in the Relations Graph","durationMs":9427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-c656cbb70e6b22b42ae1","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"cross-glossary related term appears as a node in the Relations Graph","durationMs":9930,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-d160269e303147685186","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"clicking a node in the Relations Graph opens the entity summary panel","durationMs":9496,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-dbe5441e2495e4497f75","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"a term with no relations shows only itself as a node with no edges","durationMs":10608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cdd6b2b4fe4563ae6f55-bc4aa4f69f836af1efe2","project":"Basic","file":"Features/Markdown.spec.ts","title":"should render markdown","durationMs":7423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ce9a0dc862be823369ca-a412c4cd2b7d78e6c991","project":"chromium","file":"Features/ArticleReviewerWorkflow.spec.ts","title":"Context Center article reviewer approval flow","durationMs":97851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-1ad99eb42c6a6c2096a1","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Search popover dismisses when input is cleared","durationMs":4742,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-976fa9972540355a732f","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Page renders with greeting, search, and default widgets","durationMs":4744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-ac16f93f70cd16752560","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Search with no results shows empty state","durationMs":4853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-adf188e977cee75f20a1","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Admin can create a domain via marketplace drawer","durationMs":5584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-c74336c0b248b65ccc9f","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Admin can create a data product via marketplace drawer","durationMs":6317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-1bae42cb06598b17b7fa","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"SearchIndex Service","durationMs":19097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-2597a651b0fd7aa710b6","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Api Collection","durationMs":19473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-5df1b00d3538afc3fa45","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Api Service","durationMs":19799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-5e6cd82cadd8b98f7f63","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Database","durationMs":20287,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-6554bce0546a1f330453","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Database Service","durationMs":19489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-6e4bf15cd073001e79cd","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Messaging Service","durationMs":19101,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-8ff37410faada701752e","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Mlmodel Service","durationMs":18645,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-9459bfdca9bc51b4e6e3","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Storage Service","durationMs":19222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-d311a09902e6d3b6232d","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Drive Service","durationMs":19085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-e3a737a636c50d641ee8","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Dashboard Service","durationMs":18636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-e88d4ed4325a35faf927","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Database Schema","durationMs":20478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-ec14d67dcd8f2fff65e6","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Pipeline Service","durationMs":19129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5e7fcfd64428f1fc30-b5b1e23a960dc4431ef0","project":"chromium","file":"Features/Announcements/EntityHeaderAnnouncements.spec.ts","title":"shows announcements one at a time and pages through them with the counter","durationMs":14896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5e7fcfd64428f1fc30-d1e3929c06f470275dc0","project":"chromium","file":"Features/Announcements/EntityHeaderAnnouncements.spec.ts","title":"opens the announcement drawer from the View all button","durationMs":10699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5e7fcfd64428f1fc30-e7fa692cbffac1b4f868","project":"chromium","file":"Features/Announcements/EntityHeaderAnnouncements.spec.ts","title":"hides the counter when a single announcement is active","durationMs":12347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-0844eeb3c8f64dcebe8f","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"delete-node-button absent in node config sidebar (structural edit blocked)","durationMs":10175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-08877a68185e63ad1c70","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"save, cancel, and validate buttons visible; delete absent in edit mode","durationMs":9380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-0b801c2b82a82d70400b","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"save-workflow-button fires PUT API and returns to view mode","durationMs":9927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-150069a8255116907ea7","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"cancel workflow opens confirmation modal; close-without-saving returns to view mode","durationMs":10537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-18b487d25856aa924680","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"data-asset selector is disabled in OSS","durationMs":10031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-2abad226603f3454795f","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"edit-workflow-button visible; delete-workflow-button and run-workflow-button absent","durationMs":9121,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-2bfb42a91f8a9136c462","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"add-event-filter-button is enabled in OSS","durationMs":9949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-412275bb43efcecd6fcc","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"include-fields-select is enabled in OSS","durationMs":10864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-41c9d3565357573bcecf","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"batch-size-input is enabled in OSS","durationMs":10118,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-4467d61b5a65f3cd8bc4","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"graph canvas contains workflow nodes","durationMs":9901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-4470c11ebbf089c50e17","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"save-node-configuration-button closes sidebar (local state update)","durationMs":10312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-67ca6377f9ff6be4639b","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"clicking a node in view mode opens read-only config sidebar (no save or delete buttons)","durationMs":10331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-783c6d9cebc65323299e","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"create-workflow-button absent on OSS","durationMs":8409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-8745ccab715b20fcb20f","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"editing a form field and saving node config then workflow fires PUT API with updated data","durationMs":11014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-9723cd69d43bc54d2eb1","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"workflow-name-input is disabled in OSS","durationMs":10139,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-9f41bef4230cdec8bde6","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"workflow-node-sidebar (node palette) not rendered in edit mode","durationMs":9798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-baef39c5b1e533c7ce7a","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"trigger-type-select is disabled in OSS","durationMs":10269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-c71f895d70c3ecd5dc4c","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"event-type-select is disabled in OSS","durationMs":10707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-c7fea7d29c8d8403489a","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"workflow-description-input is enabled in OSS","durationMs":10243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-cf2b0237655a0ceb88f4","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"execution history tab loads and API call succeeds","durationMs":8990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-d93adb831434700a4faf","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"task node config sidebar opens and save button is enabled","durationMs":10400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-f0673f264fa79c7dd7ee","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"schedule-type-select is disabled in OSS","durationMs":10268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-fe7465f17d878dccc48d","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"exclude-fields-select is enabled in OSS","durationMs":10925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-2e6774898e81ffe4c017","project":"Basic","file":"Pages/Login.spec.ts","title":"accessing app with expired token should do auto renew token","durationMs":142116,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-82c5ddfb9ec2446b9149","project":"Basic","file":"Pages/Login.spec.ts","title":"Signup and Login with signed up credentials","durationMs":8332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-99d8d08a1bca0dfb45e7","project":"Basic","file":"Pages/Login.spec.ts","title":"Forgot password and login with new password","durationMs":5338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-d5d492b6a1719fc4c6bb","project":"Basic","file":"Pages/Login.spec.ts","title":"Signin using invalid credentials","durationMs":5620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-db2809b113bd2372c8c0","project":"Basic","file":"Pages/Login.spec.ts","title":"Refresh should work","durationMs":146336,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d0ed2e2518dfce56f3f7-055a575d29a60700f8c8","project":"chromium","file":"Flow/MetricListSearch.spec.ts","title":"typing in the search box filters the metric list server-side","durationMs":7308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d279ac61280d1069feb3-b65e7f64e44f953e7467","project":"chromium","file":"Features/LandingPageWidgets/DomainWidgetFilter.spec.ts","title":"Domains widget should show only selected domain when domain filter is active","durationMs":16217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d279ac61280d1069feb3-e750f41ca4fc19634b37","project":"chromium","file":"Features/LandingPageWidgets/DomainWidgetFilter.spec.ts","title":"Setup Domains widget on landing page","durationMs":22934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-3d5d145448d6f5cc90ae","project":"chromium","file":"Features/DataQuality/Profiler.spec.ts","title":"Update profiler setting modal","durationMs":14958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-54c0be66359a8c228744","project":"Ingestion","file":"Features/DataQuality/Profiler.spec.ts","title":"Data consumer role can access profiler and view test case graphs","durationMs":6623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-b7926c0bc21906aa28a2","project":"Ingestion","file":"Features/DataQuality/Profiler.spec.ts","title":"Data steward role can access profiler and view test case graphs","durationMs":6565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-e16c120deba5eb61a549","project":"Ingestion","file":"Features/DataQuality/Profiler.spec.ts","title":"Admin role can access profiler and view test case graphs","durationMs":6460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-2566c24a9ad53d85fb1e","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Export button opens scope modal with correct options","durationMs":6401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-2acfadf8c9ab00eada55","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Filtered search visible export downloads CSV with the filtered record count","durationMs":21028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-3b304a2ec3fc30ef4837","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Export queues a background job and downloads from the jobs tray","durationMs":17433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-414a8700c9cff70dc984","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Browse mode visible export downloads CSV with current page row count","durationMs":9405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-6a546d5a8d744f5ab628","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Search mode visible export downloads CSV with tab-specific row count","durationMs":13250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-9d106ae4569c23f8ea2d","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Search mode visible export count matches the first result tab count","durationMs":8570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-f159c7c0ad1b30a309b2","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Export is disabled when all matching assets exceed 200k","durationMs":4762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-209be753cb89befd2d8a","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"navigating to /table/TASK-XXXXX should show 404 (invalid URL pattern)","durationMs":7500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-3cc2fe9e766015abfde3","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task in home feed widget should navigate to entity page","durationMs":7023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-67253f2989896bce72d9","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"task link should contain correct entity FQN, not task ID","durationMs":8576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-743cfd99537261dac3ad","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"task count badge should match actual task count","durationMs":8986,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-77ce1295765dba2968f2","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"two sessions: admin on Columns tab creates task, assignee sees refresh on notification click","durationMs":22439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-7a2ad0726345cbc5accd","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task notification while on entity task tab refreshes the task list","durationMs":13820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-8744e779751df9e9d0f9","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"assignee should see task in notification box","durationMs":9080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-950d31f80797a93a58bf","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"task detail page with valid task ID should work","durationMs":8809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-a9ff5c396c0e2d45a234","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task notification should navigate correctly","durationMs":11276,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-ad4029189d87e59c6334","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"should display tasks in entity activity feed tab","durationMs":8901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-c12de98dc82239c7b83c","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task card should open task detail drawer","durationMs":9537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d517907dd258f94ebf35-2be67f3cc73b940823e9","project":"Basic","file":"Pages/DataMarketplaceAnnouncements.spec.ts","title":"Announcements widget renders with active announcements","durationMs":4202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d5279e73c9dec6bec83c-4b950d2a14ba444c8c16","project":"chromium","file":"Features/RTL.spec.ts","title":"Verify DataAssets widget functionality","durationMs":12917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d5279e73c9dec6bec83c-e61689c57f31e674f9b1","project":"chromium","file":"Features/RTL.spec.ts","title":"Verify Following widget functionality","durationMs":15964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d68b190d81ed6f17e858-5baf6073a2435d76d5d0","project":"chromium","file":"Features/OntologyStudioIsolatedToggle.spec.ts","title":"isolated term is visible by default (showIsolatedNodes = true)","durationMs":36037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d68b190d81ed6f17e858-9550a9c338775c5f3796","project":"chromium","file":"Features/OntologyStudioIsolatedToggle.spec.ts","title":"toggling isolated nodes back ON restores the isolated term","durationMs":34690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d68b190d81ed6f17e858-9971d291ad13253ddda2","project":"chromium","file":"Features/OntologyStudioIsolatedToggle.spec.ts","title":"toggling isolated nodes OFF hides the isolated term","durationMs":34470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d6fb355c03fdea638db7-305911a4b7881aaba0c1","project":"chromium","file":"Features/GlobalPageSize.spec.ts","title":"Page size should persist across different pages","durationMs":22751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77ba6914f7f6fb2fca4-98403d78db095df17303","project":"chromium","file":"Features/Workflows/NoOpWorkflowNodeConfig.spec.ts","title":"schema fields for runAppTask node are read-only","durationMs":8659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77ba6914f7f6fb2fca4-bceee39b29e98183822f","project":"chromium","file":"Features/Workflows/NoOpWorkflowNodeConfig.spec.ts","title":"schema fields for runAppTask node render with correct labels and values","durationMs":9692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-03c031e4678082b99897","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Metric Entity Action items after rules is Enabled","durationMs":21117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-066a9ef811dff65e4cb6","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the MlModel Service Entity Action items after rules is Enabled","durationMs":14491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-08a76fefd534a2c8a6a3","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Worksheet Entity Action items after rules is Enabled","durationMs":14470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-0aac07ed470b079b032f","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Dashboard Service Entity Action items after rules is Enabled","durationMs":8982,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-130fbc8e073e46ded214","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Chart Entity Action items after rules is Enabled","durationMs":15663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-279a27c38018c01b5a0f","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Database Entity Action items after rules is Enabled","durationMs":14505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-2985a21f038abaa38e2b","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Pipeline Entity Action items after rules is Enabled","durationMs":14741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-3d6a300eada29abc2ffd","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Table Entity Action items after rules is Enabled","durationMs":22445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-41f3fa56ebc98ef754ce","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Storage Service Entity Action items after rules is Enabled","durationMs":12004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-572437ea2ab3f7320552","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Api Service Entity Action items after rules is Enabled","durationMs":10217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-6473d71db2c0b882f00d","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"should enforce single domain selection for glossary term when entity rules are enabled","durationMs":10078,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-6d220edd7b3bfd3fe138","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the DashboardDataModel Entity Action items after rules is Enabled","durationMs":8207,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-759333f24dee762aea40","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the MlModel Entity Action items after rules is Enabled","durationMs":12841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-78e2dbbd9c1c1db98900","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the SearchIndex Entity Action items after rules is Enabled","durationMs":9864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-962838d6f4759abd09a2","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Database Service Entity Action items after rules is Enabled","durationMs":9062,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-aa332cfa334fdbc32d77","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Database Schema Entity Action items after rules is Enabled","durationMs":15216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b0cc34f925752dfb14e5","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Messaging Service Entity Action items after rules is Enabled","durationMs":17976,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b11b9a17326398be8da7","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Topic Entity Action items after rules is Enabled","durationMs":13835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b3308e67ec8457e0dee9","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Directory Entity Action items after rules is Enabled","durationMs":14869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b7df5538066c06db4364","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the SearchIndex Service Entity Action items after rules is Enabled","durationMs":12090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b9fb2556af6f3008e225","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Dashboard Entity Action items after rules is Enabled","durationMs":13607,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-ba8a638ac27ae4f109bd","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the File Entity Action items after rules is Enabled","durationMs":13953,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-bfeb0bcea2e0396acdd3","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Container Entity Action items after rules is Enabled","durationMs":11853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-ccf02cb9cfd7b194ec16","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Drive Service Entity Action items after rules is Enabled","durationMs":10669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-cec8b7118f5a613d3132","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Pipeline Service Entity Action items after rules is Enabled","durationMs":11906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-d444bfd28e07070c2777","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the ApiEndpoint Entity Action items after rules is Enabled","durationMs":21399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-dd030b4671b685a60fc8","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Spreadsheet Entity Action items after rules is Enabled","durationMs":13097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-e435bf4efd3242cc32d8","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Api Collection Entity Action items after rules is Enabled","durationMs":14307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-ff33cabf88b06ecbd0b9","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Store Procedure Entity Action items after rules is Enabled","durationMs":15314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d9f997795c80930b24d6-bf921a12f0124551e220","project":"Reindex","file":"Features/SearchSeparation/GlossaryRenameCascade.spec.ts","title":"glossary-term rename cascade keeps tags[] + glossaryTags + tier + cert consistent","durationMs":1552,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-06b8c08d4cabd6603635","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"DQ dashboard API carries tag filter","durationMs":6129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-2af86017b01f6bdc2b71","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"clicking Data Observability tab loads DQ dashboard widgets","durationMs":6209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-2f9a9790171a0d23ecbe","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"Data Observability tab absent in version history view","durationMs":3980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-3ed728877ac6a48879de","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"clicking Data Observability tab loads DQ dashboard widgets","durationMs":6620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-673ae7c8b7ec3c3affc3","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"clicking Data Observability tab loads DQ dashboard widgets","durationMs":4493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-73606198210a4d7ca076","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"glossaryTerms filter is hidden on GlossaryTerm Data Observability tab","durationMs":3879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-7645dbf4af3497d08343","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"Data Observability tab absent in version history view","durationMs":4214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-76ec8ab8ce8ce2b149c2","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"DQ dashboard API carries glossaryTerms filter","durationMs":4730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-805007763e0ee5d5ec82","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"standalone DQ dashboard still shows the filter bar","durationMs":7112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-83f5755364b2bb6d8713","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"DQ dashboard API carries domainFqn filter","durationMs":4093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-954f5e30a09edbd7462a","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"switching back to Overview tab hides the DQ dashboard","durationMs":6417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-b4092a35d4098fe815c1","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"filter bar is visible on Domain Data Observability tab","durationMs":3968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-bd8ebaa0e4d04266e712","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"tag filter is hidden on Tag Data Observability tab","durationMs":6187,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-f9c38769f3ba40a03d59","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"applying tag filter returns a successful DQ API response","durationMs":8130,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-879aff3f25587ae15c61","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"Data Steward is blocked from every bulk edit and import page","durationMs":18042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-cc9be6afc1f0a8405f38","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"Editor with EditAll can access every bulk edit and import page","durationMs":70949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-e2134863425ccaa50016","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"Data Consumer is blocked from every bulk edit and import page","durationMs":17441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-ee37951858f3d500023e","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"View-only user is blocked from every bulk edit and import page","durationMs":20137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db7911e8ad1498312207-6e5c70587b89b9de795f","project":"chromium","file":"Features/ActivityFeedTabBadge.spec.ts","title":"badge reflects openTaskCount in Open filter and closedTaskCount in Closed filter","durationMs":24478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db7911e8ad1498312207-bd810da56c5dbdd7767b","project":"chromium","file":"Features/ActivityFeedTabBadge.spec.ts","title":"entity tab count equals the sum of the All and Tasks badges","durationMs":14176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db7911e8ad1498312207-dccdb1943a15a38f4471","project":"chromium","file":"Features/ActivityFeedTabBadge.spec.ts","title":"placeholder shows the correct message per filter state","durationMs":14420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-0517bed5a24d15a2ba7f","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should handle multiple items being hidden at once","durationMs":15708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-2fe0ce861993b8034264","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should handle reset functionality and prevent navigation blocker after save","durationMs":14616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-311db8180f2642a6a095","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should save changes and navigate when \"Save changes\" is clicked in blocker","durationMs":19197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-37062c9a70d1d97f2f9e","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should support drag and drop reordering of navigation items","durationMs":12059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-3f83c3e394f2f9d87301","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should reflect a sub-item moved to another group in the sidebar after applying the persona","durationMs":19593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-7a54741073907c77c8ac","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should show navigation blocker when leaving with unsaved changes","durationMs":15104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-d7fe854a3fe31f16df34","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should update navigation sidebar","durationMs":19100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-df0e4058a5ba929c6f8d","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should persist a reordered sub-item after reload","durationMs":19673,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dd642ff9f3c87efa9c10-dba5285969e2c24eec98","project":"ImportExport","file":"Pages/CSVImportWithQuotesAndCommas.spec.ts","title":"Create glossary with CSV, export it, create new glossary and import exported data","durationMs":73534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-17f0abe122865c573a49","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"ViewBasic permission shows read-only access","durationMs":22756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-1f0be66ac1cb6ab2b83d","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Team-based permissions work correctly","durationMs":21100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-2b6740212b2249e5cc01","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Glossary deny operations","durationMs":22763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-3188a2dc2a31bdee3d75","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"EditOwners only permission","durationMs":24111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-33796de90ddf3f62b1f2","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Delete only permission","durationMs":23855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-450caad10c6db1648382","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Create only permission","durationMs":23687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-4d14e53f4d7b0b15aaed","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"EditTags only permission","durationMs":22547,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-e72e8a08ee837b49f474","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"EditDescription only permission","durationMs":22144,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-f6f497a28461c645595b","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Glossary allow operations","durationMs":13037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-3007293d39fd27b73cad","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Stored Procedure Table should have sorting on name column","durationMs":8634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-35e294a729e304ae5ecb","project":"chromium","file":"Features/TableSorting.spec.ts","title":"API Endpoint page should have sorting on name column","durationMs":7489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-417e1899c674ba056816","project":"chromium","file":"Features/TableSorting.spec.ts","title":"should have sorting on name column","durationMs":7269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-897fd6be8d196093945f","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Topics Table should have sorting on name column","durationMs":7446,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-8df3b2994395a9dcc5f5","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Drives Service Spreadsheets Table should have sorting on name column","durationMs":8453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-934f69ec265bfc985585","project":"Ingestion","file":"Features/TableSorting.spec.ts","title":"should have sorting on name column","durationMs":3998,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-a54e163ad0d6ada016a4","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Database Schema Tables tab should have sorting on name column","durationMs":8234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-b40a460170ea3e12c7e1","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Services page should have sorting on name column","durationMs":6574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-bdfb9efa450fc8d6224b","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Database Schema page should have sorting on name column","durationMs":7761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-ca3d2db60a7a4385e32b","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Data Models Table should have sorting on name column","durationMs":7778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-e2cc6fb3ceccaeb1a09c","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Drives Service Files Table should have sorting on name column","durationMs":7941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-2321814453e125b66353","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should move term with children to different glossary","durationMs":21794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-6b80fdb91ed3204a5d79","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should cancel drag and drop operation","durationMs":11184,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-b00abfec58cbc6f25ba5","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should cancel move operation","durationMs":19952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-bdba8a60b71c0b075dae","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should move term to root of different glossary","durationMs":20073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-e65e5779dd8c704d0ab2","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should move nested term to root level of same glossary","durationMs":20486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-e7b4a28ff6323e173bb5","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should navigate 5+ levels deep in hierarchy","durationMs":12186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-eb3d35861683904e3e32","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should drag nested term to root level of same glossary","durationMs":21412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e13cf584214701b07f57-1afee2626234d27ccae5","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":30878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e13cf584214701b07f57-4ab3e6f02d449cca814a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":27370,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e2d639d408792a06975c-7a6c81a675faa6254493","project":"Basic","file":"Flow/UsersPagination.spec.ts","title":"Testing user API calls and pagination","durationMs":5608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e35d7dd71e822f3001e7-3cfbb66ae88e3514c5b2","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":16220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e35d7dd71e822f3001e7-432b8cb5b927d6df6807","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":17823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-7154f830ca4d55756208","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"a browse-location deep link highlights the tree and clears on chip removal","durationMs":15463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-759bee3eb0181dc15eae","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"reloading the page preserves composed filters","durationMs":14887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-9da821fade89f083f3ed","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"an impossible filter combination shows the no-results placeholder and recovers on clear","durationMs":18586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-9ec4db1c07256b4bbde6","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"applying a filter from a deep page preserves pagination params","durationMs":17223,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-adbb03bd2ffa82ca5802","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"selecting an asset type grays out and collapses incompatible categories","durationMs":8961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-b871193e778bd381ca8d","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"a deep-linked filter URL restores chips and filtered results","durationMs":19594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-f2ce25709e1201e3797f","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"owner filter spans asset types and ANDs with an asset-type filter","durationMs":16784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-0942d72a0198995838ac","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Metric","durationMs":354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-147633f9a3cb97439f47","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for GlossaryTerm","durationMs":414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-20324ac8b868e83321ef","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Table","durationMs":377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-2b8226ae0f295584a097","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for MLModel","durationMs":404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-2c5fcdbed087327ee250","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Metric","durationMs":452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-3a95a887039194a669b6","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Table","durationMs":309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-431dd35d48f6c5bcdc40","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Table","durationMs":487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-43cfe0395336c7874d2d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Glossary","durationMs":404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-52e0dd99e1c1dcda9296","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Metric","durationMs":381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-590d64ea0d6d3432312d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Pipeline","durationMs":732,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-6076582e5142165747b7","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for File","durationMs":233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-60b6f2e8e65c4a1d9316","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Container","durationMs":1412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-62f33d5a7ba6afa42c5b","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Pipeline","durationMs":603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-65977a8e252c1884495f","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Topic","durationMs":687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-72ca55efac5e37216621","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for MLModel","durationMs":354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-7475dc44973d9389678c","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for DataProduct","durationMs":427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-76375b057ea4b8a3a914","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for MLModel","durationMs":400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-79a962dcb0d2df39591f","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Glossary","durationMs":317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-7ca8750db292c6811fab","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for SearchIndex","durationMs":358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-8462d9dafd86d4cb7a24","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Dashboard","durationMs":407,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-87349bc4da359d33210e","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Container","durationMs":877,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-8b624e5fee37ea1427cb","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for SearchIndex","durationMs":479,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-8ea1a343c7b62f387879","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Dashboard","durationMs":461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-9017945823aea8c31e65","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Topic","durationMs":492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-92f1ec834cf376a73ae6","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for File","durationMs":204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-9676563ef902c007c998","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Dashboard","durationMs":445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-9724e6857c64f0c5f6fb","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Directory","durationMs":614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-a19e745a80175cd48c5f","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Topic","durationMs":540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-a45bbfe31b09ade0e947","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Container","durationMs":680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-a9bd3aaaf359e0f5e01e","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for DataProduct","durationMs":674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-b05d36b597ce8e148023","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for SearchIndex","durationMs":517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-becea4046545cedb234c","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Pipeline","durationMs":398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-c5d58d76277e5a4a1fa8","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Dashboard","durationMs":427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-c9d917883dbfefee36a7","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Table","durationMs":338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-ce553d1c2da64d450d17","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Pipeline","durationMs":389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-cea3022de30e27291656","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for GlossaryTerm","durationMs":350,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-e17b4094c0f9dbdd345c","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for File","durationMs":260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-eba55dd6b22bb101f65d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for GlossaryTerm","durationMs":707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-ebffb46a0650e1e63b25","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Metric","durationMs":395,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-efdd01ba42a7838ececc","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Container","durationMs":1066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f1cdb4d14559b84e7e90","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Directory","durationMs":509,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f577090e7c0c2c6d1672","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Topic","durationMs":450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f7241889791483b397a1","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for MLModel","durationMs":252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f7f3a5872d0f5075a31d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Glossary","durationMs":478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-fbf598a3f758d45a8e87","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for SearchIndex","durationMs":1214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-ff39d1cbf073725e11f9","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Directory","durationMs":817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-27bf83ebb148b83122c8","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Database service","durationMs":52300,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-393e6fb3b55e026c5927","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Database","durationMs":50230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-80d244c353a9b5239063","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Table","durationMs":28761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-864b2325f77eb8ef0979","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Database Schema","durationMs":59959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-8b088f9fd4352335f186","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Glossary Term (Nested)","durationMs":50210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-afada82cd2191181328b","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Glossary","durationMs":57347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-991e22827d785d044de8","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing a child term: parent appears as a 1-hop neighbour via parentOf edge","durationMs":12556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-9a9e5f8ec1ab595d1664","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing a child term: parentOf edge is rendered between parent and child","durationMs":10847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-cb3f581754b8a14c9209","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing the parent term: parentOf edge is rendered between parent and child","durationMs":8770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-ea60b9272f2de2cae5c9","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing the parent term: child appears as a 1-hop neighbour via parentOf edge","durationMs":11378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-0872d0c75b5f4a1eea22","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Bulk edit existing entity with dot in service name","durationMs":31756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-11b6b2822f5d1e76a451","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Import at database level with dot in service name","durationMs":39858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-2b628617654ecf4bdd25","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Import at schema level with dot in service name","durationMs":28396,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-4ae957d1d4bc40c66b27","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Service name with multiple dots","durationMs":27777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-61e520c2d24c8cb303be","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"CSV with quoted FQN loads correctly in import grid","durationMs":27717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-8640e5baa9623705571d","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Column with dot in name under service with dot","durationMs":20311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-9831613d51f1f5074fcd","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Full import cycle with dot in service name","durationMs":32379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-adf1fb39ffb44f305718","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Database service with dot in name - export and reimport","durationMs":30967,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-451958641a79328fe77b","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Install application","durationMs":4935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-a3a1e60b3e20e393c2f1","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Edit application","durationMs":5821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-b0cd1177775297960d65","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Uninstall application","durationMs":5251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-d65f3bc388f55deee256","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Run application","durationMs":7070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-00727756ed54b11d9d66","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify fullscreen toggle","durationMs":6238,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-0de408c32267fb067d06","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify DQ layer toggle activation","durationMs":8519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-2fd3d671fe79e7aa79e6","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify DQ layer toggle off removes highlights","durationMs":10270,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-61f864881a368270e9b4","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify minimap toggle functionality","durationMs":8691,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-a50f5062bdbb068e2796","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify invalid entity search handling","durationMs":5532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-b82c3c1c96ccc2c41e8d","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify lineage tab with no lineage data","durationMs":10545,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-f67f93500d58072add25","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify zoom in and zoom out controls","durationMs":8542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-fa08f156b0ba6e20421a","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify fit view options menu","durationMs":8117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-3acaa880cb4773e73f12","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk cancel operation","durationMs":190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-3d3e2def8f2e96897376","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should handle partial failures in bulk operations","durationMs":496,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-4a32405d0d74df2c5db6","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk approve on multiple tasks","durationMs":744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-94ecf2bb50f9c561671f","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should reject non-suggestion task via apply endpoint","durationMs":136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-95ba2888711a203eb077","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk reject on multiple tasks","durationMs":799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-c46ffd4656a5fdf657cc","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk assign operation","durationMs":841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-febb592c17f5eea5e817","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should apply suggestion via PUT /api/v1/tasks/{id}/suggestion/apply","durationMs":533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f424f0b2de2b8353168d-3a71a044adebef3ad89e","project":"chromium","file":"Features/ContextCenterArchive.spec.ts","title":"full document lifecycle: folder expand icon, upload, delete, restore, and permanent delete","durationMs":31065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f424f0b2de2b8353168d-82b0e753e7d46cd9890c","project":"chromium","file":"Features/ContextCenterArchive.spec.ts","title":"archive page lazy-loads more rows on scroll within its own scroll container","durationMs":8955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f424f0b2de2b8353168d-99117e03aa3c5b328397","project":"chromium","file":"Features/ContextCenterArchive.spec.ts","title":"file in deleted folder is absent from search and not added to archive","durationMs":13114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-075d5e867770cf289c8d","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"data steward cannot edit team subscriptions","durationMs":12977,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-233b01cc9bf79b6f3f4b","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should disable endpoint input when webhook type is None","durationMs":10233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-388f9f7a9983f83d39d1","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should update existing subscription to different webhook type","durationMs":10784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-4089f84abb290168ef0c","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should validate endpoint URL format","durationMs":10473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-54a2d04779b87540a00d","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure Slack webhook subscription","durationMs":9016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-5c2b44855ea7aac27a3f","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should remove subscription by setting webhook to None","durationMs":10314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-67f33babda3fdf4febf5","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"team member without owner role cannot edit subscriptions","durationMs":15435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-842a1076b8d1906ba450","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"admin can edit subscriptions for any team","durationMs":11592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-8609b568b701057602c0","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"data consumer cannot edit team subscriptions","durationMs":13959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-86d32d813fc943a78e43","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should display subscription as None when no subscription configured","durationMs":9267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-8d2d31841b63ddf340ff","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure Google Chat webhook subscription","durationMs":9090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-a27b2e53b3221dbc8290","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should require endpoint when webhook type is selected","durationMs":9837,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-a9d0c9c4799698417f3d","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should open and close subscription edit modal","durationMs":10445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-b4f94192f34e07d52e1e","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure MS Teams webhook subscription","durationMs":10501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-bff65aca6ff47e244d26","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should persist subscription after page reload","durationMs":14192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-fca848d6346f22013a7f","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure Generic webhook subscription","durationMs":11346,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-ff289db727fd13098421","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"team owner can manage subscriptions","durationMs":21599,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-249f2e80e1ed07c92f7e","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should rename data product and verify assets are still associated","durationMs":18957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-600e291c7d231e7f82c1","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should show error when renaming to a name that already exists","durationMs":11324,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-6edae00094cd060fc0a5","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should handle multiple consecutive renames and preserve assets","durationMs":24936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-90803266ddfc79e89669","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should update only display name without changing the actual name","durationMs":13314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4cae74b06fda076f0a1-b770428f72ba5b0a9d85","project":"chromium","file":"Features/BlockEditorEmbedLink.spec.ts","title":"entering an invalid URL shows validation error and does not crash the editor","durationMs":9298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-0462ac71e8c91afbbf6c","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Stored Procedure - customization should work","durationMs":24460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-0702a83ca7d8b8bbd8c0","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"customize navigation should work","durationMs":31317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-25846c7a65b11a89cff2","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Container - customization should work","durationMs":30050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-37449f25e978be1788be","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Glossary - customization should work","durationMs":24375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-41d0a892fca6d9343808","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Data Product - customization should work","durationMs":29527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-455659b2d17f62c06d8e","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Domain - customize tab label should only render if it's customized by user","durationMs":22197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-59a82d5c1ea5278c7323","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Search Index - customization should work","durationMs":25579,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-59f9c9ce01e8f4c75fa9","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Validate Glossary Term details page after customization of tabs","durationMs":23219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-658ea4555cba25bb9b09","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Ml Model - customization should work","durationMs":26190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-729b695acd411ed7fcb8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Dashboard - customization should work","durationMs":25269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-75c1ec0b785dfbe2e9f8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Pipeline - customization should work","durationMs":24942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-81ab6a13446be00d2236","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Topic - customization should work","durationMs":22792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-a1007d349e35f17016eb","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Database Schema - customization should work","durationMs":27114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-b83e17354b58f3885232","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Database - customization should work","durationMs":24257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-b86710bce42df069ca07","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Dashboard Data Model - customization should work","durationMs":25625,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-bccd2187cd76d2275312","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Table - customization should work","durationMs":24717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-c23463689b6a02ae53e8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"customize tab label should only render if it's customize by user","durationMs":27575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-c77322af934d1f2cf284","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"should show all the customize options","durationMs":11432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-ca3857c050b462ada785","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"should show all the governance customize options","durationMs":11448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-cda13e1a745c6788e3ed","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"API Endpoint - customization should work","durationMs":24546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-dc93b1114afcda98e4d8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Navigation check default state","durationMs":11372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-df1705426fee23699c44","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Glossary Term - customization should work","durationMs":25540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-f36a44fc5a95e395227f","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Domain - customization should work","durationMs":22720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-f67ada2b0e7642366d4c","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"should show all the data assets customize options","durationMs":10844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-f6f733b3ac3589b9dfd1","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"API Collection - customization should work","durationMs":22552,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-0205ffdfc585cab01ddf","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Database Schema","durationMs":359636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-169d67f201cb81f89740","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Table","durationMs":158261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-642237d4a41dc49da1dd","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Database","durationMs":330408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-95b213492138666fe484","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Keyboard Delete selection","durationMs":137441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-bb8bb17e2fefc0c05203","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Range selection","durationMs":26965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-f582fd9991e819296458","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Database service","durationMs":455007,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4f25d988842201e6c20-ae24e2a0aae5144bba18","project":"chromium","file":"Flow/ExploreAggregationCountsMatching.spec.ts","title":"should verify left panel counts and tab search results for normal search","durationMs":5978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f63edb310b70898c32ef-404b1e6d790711af858c","project":"DomainIsolation","file":"Features/DomainIsolation/DomainLineageIsolation.spec.ts","title":"userA sees tableA but not the cross-tenant tableB node","durationMs":8648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f63edb310b70898c32ef-80db248d069981e2eab0","project":"DomainIsolation","file":"Features/DomainIsolation/DomainLineageIsolation.spec.ts","title":"admin sees both nodes in the lineage graph","durationMs":6971,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f63edb310b70898c32ef-9807ba0d848bcddb4727","project":"DomainIsolation","file":"Features/DomainIsolation/DomainLineageIsolation.spec.ts","title":"userB sees tableB but not the cross-tenant tableA node","durationMs":6582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-059206e1428a5297d108","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create TierUpdate task for Topic","durationMs":143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-408ca4feecc6e89950e5","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create OwnershipUpdate task for Topic","durationMs":610,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-448a9a33c07636db1183","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create and approve schema field description task for Topic","durationMs":211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-9833d1f4ad179adb98f1","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create DomainUpdate task for Topic","durationMs":246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-c54d52f5c5aeaa552192","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create and approve entity-level description task for Topic","durationMs":218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c386facc843a14ec19-6a408855f47e7887f923","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":28119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c386facc843a14ec19-ed35b4deecb9ca47009d","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":28113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-0a44a983974730b89f64","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-H01: ME glossary (top level) children render Radio with ME behavior","durationMs":10012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-3fcaec003ed89f7e3e4c","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-S02: Can select multiple children under non-ME parent","durationMs":11293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-5651fb4202fceb9735a1","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-R02: Children of non-ME parent should render Checkboxes","durationMs":9832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-5cb89ffa42856f160ca8","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-R01: Children of ME parent should render Radio buttons","durationMs":10476,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-9b44f296c9a6d33e51fb","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-T01: Apply single ME glossary term and save Data Product","durationMs":10796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-9c2585c3aa05ec0e24c0","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-S03: Can deselect currently selected ME term","durationMs":10370,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-efa1868c007a3e6cbd21","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-S01: Selecting ME child should auto-deselect siblings","durationMs":11641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-0dbac478b849946a6c3c","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"Tag - should handle multiple consecutive renames","durationMs":15386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-17c1918984f0172bbbe9","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"GlossaryTerm - should handle multiple consecutive renames","durationMs":22039,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-725c0e89e0d163df757d","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"Glossary - should handle multiple consecutive renames","durationMs":19787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-8c9a6934d3b95c2c1d12","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"Classification - should handle multiple consecutive renames","durationMs":19406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa42a344a1491728c88c-ca790fdf6e37164c48c6","project":"Basic","file":"Features/MutuallyExclusiveColumnTags.spec.ts","title":"Should show error toast when adding mutually exclusive tags to column","durationMs":10506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-1658d542d353f5e8537c","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"success state shows Done button and hides Edit Connection and Retry Test","durationMs":12069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-168f03efee35ec66edfb","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"failure state shows remediation card with error content","durationMs":12119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-2c7d4ad226db72ac9f82","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"changing a form field after a successful test resets the connection badge","durationMs":12522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-4b58db22ce037337317f","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"raw log toggle shows and hides connection log","durationMs":12792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-8cc727200eac97c77b66","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"Edit Connection click dismisses the modal","durationMs":12263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-8e06fc7c08d9ab043ed2","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"validation shows RJSF field errors on first click when only service name is filled","durationMs":8590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-b2346dfc921ce5e28a27","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"failure state shows Edit Connection button and Retry Test button","durationMs":12232,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-e8d2f77fc5c536d510c7","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"validation shows all required field errors on first click when all fields are empty","durationMs":8384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-f124d2edb8c14295a059","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"modal opens with gate card and capability checks sections","durationMs":10264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-35df4cdd13ee89a8d38d","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"Different user can view but cannot modify service owned by another user","durationMs":12672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-3c28749487fae15018ac","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User with service creation permission can create a new database service","durationMs":10206,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-7e5ca4567f5a88b8e298","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"Owner can update description of their service","durationMs":6965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-8e6d87b24ddeccf497e7","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User can view but cannot modify services they do not own","durationMs":6029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-955a42cfe4f501beb1ab","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"Owner can delete their own service","durationMs":7235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-a51b62db11ad9675f612","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User with EditAll but not Trigger cannot run a pipeline","durationMs":6838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-c733a081bb38e4e8f7e8","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User with Trigger permission can run an ingestion pipeline without EditAll","durationMs":6704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-f200b75084f8b2928afc","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User can update connection details of their own service","durationMs":6534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-00b4b832ff041854728c","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"renders a description-updated activity item in the feed","durationMs":18670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-264131b8e9c311797619","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"displays feed content in the Activity Feed widget","durationMs":7685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-38913b446c5ece4b7589","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"adds a reaction to a feed item","durationMs":17865,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-6dae248f6b6f0c87dc65","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows the activity detail layout, read-only","durationMs":14786,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-b23432aca7892b48a5e2","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"routes each Activity Feed widget filter to its own endpoint","durationMs":19891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-ce699d538b116cbec69b","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"removes an existing reaction from a feed item","durationMs":17714,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-d48cfc9fae2794bc1d35","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows Activity Feed widget filter options","durationMs":9628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-ffbf0a15623c2f20aed0","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows the followed entity activity under the Following filter","durationMs":8322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc426d31c2c6443c1be6-05800e3a4ea5b64d3da3","project":"DomainIsolation","file":"Features/DomainIsolation/DomainListingIsolation.spec.ts","title":"userA sees only tenantA on the domains listing page","durationMs":6412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc426d31c2c6443c1be6-4518202e8a9e1f36a215","project":"DomainIsolation","file":"Features/DomainIsolation/DomainListingIsolation.spec.ts","title":"userB sees only tenantB on the domains listing page","durationMs":6114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc426d31c2c6443c1be6-d5d4bf170dffa3f33a63","project":"DomainIsolation","file":"Features/DomainIsolation/DomainListingIsolation.spec.ts","title":"admin sees both tenants on the domains listing page","durationMs":7597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc6611f5f281a4e45f8c-75cb78dafb20bfb5e68f","project":"Reindex","file":"Features/DataQuality/TestSuiteListAfterReindex.spec.ts","title":"Basic test suite stays listed on the table-suites page after a full reindex","durationMs":1188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-29eff01a200d84238a47","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should create glossary with special characters in name","durationMs":9828,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-2fe6a9452e85458797d7","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should show history popover on status badge hover","durationMs":11445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-3f4b2313c27eb62355cd","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should show column settings with custom properties option","durationMs":10536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-439407dfe7f6467e411a","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should create term with Draft status when no reviewers","durationMs":13052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-fb8b4435543932423ab6","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should view workflow history on term","durationMs":12522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fdb594bf91641dcfe81f-97569a3fda3bc1af5014","project":"chromium","file":"Pages/AppRunsHistoryLogs.spec.ts","title":"External app run logs open in the LogViewerModal","durationMs":6403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-109f244e567c8e05b18a","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"switching to different domain triggers new feed API call","durationMs":6792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-1112ad59f3cbc8039e17","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"entity page activity feed refetches when domain is switched","durationMs":14517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-4957bdf2b1993328fb92","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"switching domain triggers feed API refetch on entity page","durationMs":6739,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-5fb1a3cba94644d690fe","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"selecting All Domains removes domain filter from feed API call","durationMs":6118,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-66bc79b3489af009bdb4","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"GET /tasks returns 200","durationMs":45,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-6ecf643f1978bd72b573","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"task count API returns counts for created tasks","durationMs":14,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-ccf80dfe3a0f263a9e03","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"entity page shows task cards for entity in selected domain","durationMs":4864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-db696b7c8e033f4adfa0","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"GET /tasks/count returns task counts","durationMs":15,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-46426b05e7ad5d6e5c55","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should perform case-insensitive search","durationMs":18212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-55947400922d9b46072b","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should check for nested glossary term search","durationMs":13696,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-5afd99790393d19e9894","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should check for glossary term search","durationMs":14474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-749f411c6ea7761e557a","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should filter by InReview status","durationMs":9411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-8995fbfedb67c22e25be","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should show empty state when search returns no results","durationMs":11177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-c161bb5dadfd704c3625","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should filter by multiple statuses","durationMs":9071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-0da857d629e3f435c6d4","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove reviewer from glossary","durationMs":15873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-40c7edf6cee7c9c38346","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove tags from glossary term","durationMs":17436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-4fb8c23497a80dd2fc28","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove tags from glossary","durationMs":13775,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-753d73bb076239505f28","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove reviewer from glossary term","durationMs":16902,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-9679675e187bc293844e","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove owner from glossary term","durationMs":18192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-ace8963a89d7b007752c","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove owner from glossary","durationMs":16267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ffa6959dc235a6a5b1d7-28b5728ddddb5976c831","project":"data-insight-application","file":"dataInsightApp.ts","title":"Run Data Insight application and wait until success","durationMs":51225,"attempts":2,"retries":0,"outcome":"expected"}]} +{"version":1,"mode":"full","sourceRunId":32744092683,"sourceSha":"36e00d5db788fb96857b34d11dbf2bae8cde24c7","retainedSourceRunId":29980474263,"retainedSourceSha":"9f78d5d741673d44dee0190488ba586cce4fecb1","retainedUnstableTestIds":["10c126ce21ddb47756a4-04d6154814646027d691","10c126ce21ddb47756a4-0741446b51bd1831b1fb","10c126ce21ddb47756a4-211bb353cbf91b58df5a","10c126ce21ddb47756a4-2a8d02fe65e159aa7997","10c126ce21ddb47756a4-326e5741aa3e465e11c0","10c126ce21ddb47756a4-439a804c72c1029b9604","10c126ce21ddb47756a4-485027c527c4c17d746c","10c126ce21ddb47756a4-49aa937a33fa5a8948c9","10c126ce21ddb47756a4-4bca0aa80c53d7c4a24c","10c126ce21ddb47756a4-4f16dd456ed5b31f8f8d","10c126ce21ddb47756a4-5adfe289cb3d8520b0ef","10c126ce21ddb47756a4-7f74b79cdc6913ea9d62","10c126ce21ddb47756a4-89f210443cbeae6bb2c0","10c126ce21ddb47756a4-9585120f51c086d40c8f","10c126ce21ddb47756a4-cda8340b8fcb3bc57b4e","10c126ce21ddb47756a4-d66611608cf890ccc13c","10c126ce21ddb47756a4-e88886cf009eb2d89a24","1c1beaa6e6bb68455687-02db839411b88f88324d","1c1beaa6e6bb68455687-19694be941e5fc5a50d6","1c1beaa6e6bb68455687-4fbd2cc9b2f8b51b955e","1c1beaa6e6bb68455687-620c0ccb2076231e1b46","1c1beaa6e6bb68455687-696baf01722eff41e180","1ce96103ecb38ee49d41-0a4191b4db0efcbae0f8","1ce96103ecb38ee49d41-a83ffa17458ba063ab54","260a9e5977a8ba3ec78b-dace76fe5d6fd2759124","2d5458d5effed0092e57-2c9621778a08fadbc834","2d5458d5effed0092e57-4156e62dca8bfb5afec0","2d5458d5effed0092e57-88e75e085e61e8618e6a","2d5458d5effed0092e57-9b4ef19a6cb0199bf241","2d5458d5effed0092e57-b0ff6e9dd7c295b37f2c","2d5458d5effed0092e57-b68f427de8c7c4e4c036","3f800034a832b756357b-2e3d05e6e1e746b6c156","426c3d5e1c2f1aa09ac8-f8d8b2894982189c8fdb","47563b3c243233393067-36286bd8f41799e49212","4b548bcc60ee243a112c-91f203d529a815190d96","5c28d935b3c657a6e5bc-b0a79157c365565b41e4","5c28d935b3c657a6e5bc-b7e3072f59f508bd7c81","5f37f0e1f4111ad5b126-a044c42b96a086d46495","6491031c3e271b473ed6-a1a41e105bc8e1f05019","6af163fea506aa4566f2-0d9793ea09690a80b966","6f9684bba76ed22e1a8c-76b8bbfc4abe6888a560","6f9684bba76ed22e1a8c-dcee5e388fad4727090e","7c975cd1ceb31d5d60dd-0dbdcff683eb513dc0f5","7c975cd1ceb31d5d60dd-20ec70d5fe0c22fab8a3","7c975cd1ceb31d5d60dd-44413c5a1543a1f5a65d","7c975cd1ceb31d5d60dd-f49b660fff35024b8100","848329c182e7112e80ae-9df4121368d3676326e8","8f00f316c6c46c156a1c-16b3484cc09d5255f8d6","92f4b5f6dbf60767921f-60d6762c4b0ae5b80aa3","9308de5e0d9b01cc3b0e-4cc494c7283e8466765d","9308de5e0d9b01cc3b0e-afbe709e30f6facd3dbd","9308de5e0d9b01cc3b0e-eb3f22266d782e009e06","9cc140ad818dd8f839cb-a80bbe7b29b7f5294127","b63caa6d5c82a89c01d9-930ae77b2adf34892aed","b76310c94a1ee56387bf-eee048f4f8692c102fb6","caebfb61a8a7d76a7401-1dbd614d29e180690a85","caebfb61a8a7d76a7401-7ac27f96d42f8e47da96","caebfb61a8a7d76a7401-dd9f678b3ba6fdaee2cc","d8f8caeb6165f1ef1fcd-2985a21f038abaa38e2b","db1daaef72d72e2312ab-71b65167efedb93432d2","df23f6ad1ee603a6ae65-e2cc6fb3ceccaeb1a09c","e6106fb403b25b398095-eba55dd6b22bb101f65d","e91c95e3d77f8c0bc288-27bf83ebb148b83122c8","e91c95e3d77f8c0bc288-393e6fb3b55e026c5927","e91c95e3d77f8c0bc288-80d244c353a9b5239063","e91c95e3d77f8c0bc288-864b2325f77eb8ef0979","e91c95e3d77f8c0bc288-8b088f9fd4352335f186","e91c95e3d77f8c0bc288-afada82cd2191181328b","fed0153cfc145e829673-749f411c6ea7761e557a"],"tests":[{"id":"004f08191fdf5a664c49-5934f2193bbcf4275249","project":"chromium","file":"Pages/Tasks.spec.ts","title":"List tasks by status","durationMs":73,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-6a8d58070f2721e22772","project":"chromium","file":"Pages/Tasks.spec.ts","title":"All built-in task categories can be created","durationMs":138,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-9a77320621e2e18ce3d6","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Create task with different built-in categories","durationMs":77,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-a034a19fedb3914dc554","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Resolve task with rejection","durationMs":75,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-a37baa03858ead321cb3","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Create task with assignees","durationMs":31,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-a6680360eb1c1db3276a","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Task priority levels","durationMs":113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-cf4a9c8c257c776dc018","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Resolve task with approval","durationMs":134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-dbd17b6aee48089a70bc","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Task ID sequence is unique","durationMs":106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"004f08191fdf5a664c49-e915ae4e13ecb3f579d1","project":"chromium","file":"Pages/Tasks.spec.ts","title":"Task CRUD operations","durationMs":60,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0052ab9e28cac302a481-57cf91322cdd33d989d4","project":"chromium","file":"Features/DataProductPersonaCustomization.spec.ts","title":"Data Product - customize tab label should only render if it's customized by user","durationMs":22259,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0052ab9e28cac302a481-f1eee6df796efc54fae7","project":"chromium","file":"Features/DataProductPersonaCustomization.spec.ts","title":"Data Product - customization should work","durationMs":24306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-061045104b0501529f9a","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate between tabs on glossary page","durationMs":9330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-254409f9a53adc8e7c67","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate to nested term via deep link","durationMs":7701,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-3b75351433e5696dd218","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate between tabs on glossary term page","durationMs":10142,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-6092fc9d785185e1febb","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should view activity feed on glossary","durationMs":9296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-9af09dcafe15890a4c22","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should post comment on glossary activity feed","durationMs":9084,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-a8188d2dbe1c913f81cb","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should post comment on glossary term activity feed","durationMs":9355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-dc08d608e28379784c90","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should show empty state when glossary has no terms","durationMs":8250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-ddd5214b0a60bd16b3ab","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should navigate via breadcrumbs","durationMs":9397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"005f0ebf0455d92ba940-f505640efd2508d042ed","project":"chromium","file":"Features/Glossary/GlossaryNavigation.spec.ts","title":"should view activity feed on glossary term","durationMs":9549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-417dfcf921ef3832d10e","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"TagPage: Certification detail page routes through certification.tagLabel.tagFQN","durationMs":3921,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-5b17e1cf7d08cd3cb595","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"Certification filter narrows both table- and testCase-index queries via the flat field path","durationMs":6970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-b5d9a677fd75a83d66e4","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"Certification filter is rendered between Tier and Tag in the filter row","durationMs":6632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"009d846d280e71301c7f-c2f2bff31097429e61d5","project":"chromium","file":"Features/DataQuality/CertificationFilter.spec.ts","title":"Certification tags are not listed in the generic Tag dropdown","durationMs":7084,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-22e2c0617d842764b11b","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"surfaces the index banner and stays usable when search returns an index error","durationMs":12481,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-23d8e6ff84c5ddbabe5a","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"does not white-screen when the search request fails at the network level","durationMs":6094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-9eae8c06bfeb61c22fd9","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"renders gracefully for a malformed quickFilter URL parameter","durationMs":9435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01ab199128dd4cbd1401-9f6105f6cdb93d1fd691","project":"chromium","file":"Pages/ExploreResilience.spec.ts","title":"renders gracefully for a malformed browsePath URL parameter","durationMs":9602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"01d9777d939990dabbd7-262dce1d2eeb8d343b4f","project":"chromium","file":"Flow/AppBasic.spec.ts","title":"should call installed app api and it should respond with 200","durationMs":3368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-22792cd610df6f5cade6","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create request description task for column","durationMs":11674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-2491067d6bcb5a54cb1f","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create request tags task for table","durationMs":10047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-25a394db38b512ef6f74","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create suggest tags task with suggested tags","durationMs":9727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-3046f4d31958bfd4dbf4","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should allow manual assignee selection when entity has no owner","durationMs":15347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-3557ecd547d5055ef28a","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create request description task for table","durationMs":14371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-64648a6c346cc46feb53","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should prevent task creation without assignee","durationMs":11668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"02d3ad5d2690225c29a3-c8d9ec46c49bded4357b","project":"chromium","file":"Features/Tasks/TaskCreation.spec.ts","title":"should create suggest description task with suggested value","durationMs":8806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-1d172c84ee80912f5e2b","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Delete Button Disabled - Fully inherited contracts cannot be deleted","durationMs":20771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-38ad37abf46eb45d83a2","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Edit Asset Contract - Add SLA when inheriting SLA from Data Product (PATCH should use /add not /replace)","durationMs":29056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-46fe2ceba304a71d5ec7","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Edit Inherited Contract - Creates new asset contract instead of modifying parent","durationMs":26332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-567dac3aaaf0ed82e32c","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Run Validation - Inherited contract validation uses entity-based validation","durationMs":17329,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-a3744a7bd7f9ba4362bf","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Partial Contract Inheritance - Asset contract merges with Data Product contract","durationMs":30916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-b132cbad6c8242839b58","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Remove Asset - Inherited contract no longer shown when asset is removed from Data Product","durationMs":21984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-be0fe0b025326af56b6c","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Delete Asset Contract - Falls back to showing inherited contract from Data Product","durationMs":22506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"042edd1236bb429d4881-f085389ed08a523aed7e","project":"chromium","file":"Pages/DataContractInheritance.spec.ts","title":"Full Contract Inheritance - Asset inherits full contract from Data Product","durationMs":26108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-0515ac5501ef2810b804","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12564,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-08ba9d2d9d9dd6d3b4a2","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-0d28e20e436777cb4128","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13544,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-0fafe939201d31585243","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":15310,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-12b31351571057d29cfd","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13092,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-2709b060aa5199ed7c46","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-3ae1dea8ac49be64dca4","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-3b46fb9bae34c93ab1e9","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12757,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-41007f7a6fab6e10596e","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13922,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-4a9e85c6f398e9f67275","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":8666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-4e3beed6243af81a754f","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":11057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-8cdf8f3a9f746fe00862","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-b73259974a470801efb0","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-bc4fcb436e3a2259227d","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":10517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-c2d03257ee6a2a9da060","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":7927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-cb0b667dbd687968d9a4","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":10163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-d0c505fe536cfd142768","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":13574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-db5d6a1f95b3e473d580","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":10032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"07da7e648d32184b2125-e5b3fd5755c76424ad67","project":"Basic","file":"Pages/EntityHeaderBreadcrumb.spec.ts","title":"should render every breadcrumb crumb exactly once","durationMs":12388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-1cee2b35ca54d4c31c16","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should prevent all users from modifying system test definition entity type via API","durationMs":7065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-360040f1744491234d09","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should allow viewing and editing but not creating or deleting test definitions","durationMs":13434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-5d4e43fff79360c3f26b","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should allow viewing test definitions but not create, edit, or delete","durationMs":10549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-6e5f9aa62a0c1a6a0b18","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should allow viewing test definitions but not create, edit, or delete","durationMs":10447,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-7092674b02cee0ed0c42","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should prevent unauthorized users from creating test definitions via API","durationMs":9664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-b2982050987bb5e8b4ee","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should not be able to edit system test definitions","durationMs":13335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08438e4c31be1f112e33-e6aff96f2117419d34a3","project":"chromium","file":"Features/DataQuality/TestDefinitionPermissions.spec.ts","title":"should prevent unauthorized users from deleting test definitions via API","durationMs":13540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-38d034de72fa8cbb70cb","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should not show online status for inactive users","durationMs":6749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-3e05f86121d3c978d4a2","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should show online status badge on user profile for active users","durationMs":6838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-43e97a2523a7811c8bb0","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should show online status below email in user profile card","durationMs":7129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-b7bc8e5ed7bc4471ba0a","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should update online status in real-time when user becomes active","durationMs":13208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"08acdf02a4232934bfcc-e0bd28c84529a51c89aa","project":"chromium","file":"Features/UserProfileOnlineStatus.spec.ts","title":"Should show \"Active recently\" for users active within last hour","durationMs":6438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0a56168a40b882fe6894-170e1f3eff5aa971e713","project":"chromium","file":"Flow/FrequentlyJoined.spec.ts","title":"should display frequently joined table","durationMs":9898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0a56168a40b882fe6894-84ac3055d73ecf89a21d","project":"chromium","file":"Flow/FrequentlyJoined.spec.ts","title":"should display frequently joined columns","durationMs":11540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-011fed074239d8794a66","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Admin can remove the default persona for a team","durationMs":9409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-027f80afc1576bc6be86","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Persona rename flow should work properly","durationMs":8472,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-1030722b78088d2ec6ec","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"User without permissions cannot edit team persona","durationMs":8632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-135241804761fb629b85","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Delete persona should work properly","durationMs":7771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-187a985529b191d190fb","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Persona update description flow should work properly","durationMs":6526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-25b967abba28bb47f099","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Description Contains filter – table with matching description appears in widget","durationMs":19069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-2c59da2e1af01cfdfb95","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Remove users in persona should work properly","durationMs":7326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-47c2545428c8641b1aba","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Non-group team types do not have a default persona setting","durationMs":9359,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-828969cb1530df18a4e9","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Set default persona for team should work properly","durationMs":11418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-c91b116cdca0ef43878d","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Set and remove default persona should work properly","durationMs":42419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b596e420ec414391b24-e8766d04fa25cb1329b6","project":"chromium","file":"Flow/PersonaFlow.spec.ts","title":"Persona creation should work properly with breadcrumb navigation","durationMs":11581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b721dc6d1e4c283a3d7-254b18deceb1b36bf441","project":"Basic","file":"Pages/Policies.spec.ts","title":"Add new policy with invalid condition","durationMs":14817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b721dc6d1e4c283a3d7-9938e72067584c0c12ab","project":"Basic","file":"Pages/Policies.spec.ts","title":"Delete policy action from manage button options","durationMs":8661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0b721dc6d1e4c283a3d7-de3a6ddc322ed853fa63","project":"Basic","file":"Pages/Policies.spec.ts","title":"Policy should have associated rules and teams","durationMs":6026,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-05378723d5e66cf91611","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display isolated nodes toggle","durationMs":3467,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-0564c09d0e6aecd65d7b","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should open settings panel when settings button is clicked","durationMs":4965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-06a230ae8ba96f7d7719","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"renders a distinct edge for each relation type between the same pair","durationMs":37162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-0c79ca6b0a89a6b129ce","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should show hierarchy empty state when no hierarchical relations","durationMs":36709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-0d2f6313709f9c0b7b13","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should show empty graph state when the search matches nothing","durationMs":8515,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-13f8c7c9a32833deaf3b","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display all graph control buttons","durationMs":3515,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-16a3534319a4235fc681","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should not show empty state when glossary terms exist","durationMs":6610,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-17604bd54318eff53a8c","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should trigger SVG download when SVG option is clicked","durationMs":9322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-18f283d072779a45043e","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should show only the matching node and its neighbours when a search query is entered","durationMs":37013,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-20dd3b48d5b1083e2f0d","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"entity panel Relations tab should show the related term by name","durationMs":38421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-2d0c7cedfd906ef8ff0a","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should execute fit-view without errors","durationMs":5065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-2f1566eaaf2741e2fb54","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should clear the search query by emptying the input","durationMs":5273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-37e6076736f2a7c71442","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should close settings panel via close button","durationMs":5964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-39434b1a956b479f10cd","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"entity panel should display outgoing or incoming relations section for a connected term","durationMs":36990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-39d59f1f0e981e9cf097","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should trigger PNG download when PNG option is clicked","durationMs":7121,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-481b25c04c66c88c2966","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display layout options in settings panel","durationMs":5067,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-4aac26790e52a1ef217a","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should fire a glossaryTerms API request when refresh is clicked","durationMs":6855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-4e2508a7151a022d182d","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"clicking a term node opens the entity summary panel without a permission error","durationMs":37628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-5c80f23a59428f24a670","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should restore all nodes when the search query is cleared","durationMs":38069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-7b6922d69c604f4073ab","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display settings button","durationMs":3453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-7cc1cdaa65fe3ec7375d","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display the header section with title","durationMs":4360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-82119a03ae25fc08a61d","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should show empty state when active filter yields no visible nodes","durationMs":36646,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-8308b167077a7c1b46ea","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display stats in header after graph loads","durationMs":6491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-949ddc539f2f4eecdcde","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should show empty state when relation type filter removes all edges and no isolated nodes remain","durationMs":37074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-9a300e46ba23738f9ed3","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should recover from a no-match state when the search is cleared","durationMs":7870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-9da738766af57c0fc0ce","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should toggle edge labels off and back on","durationMs":6050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-a98d8d4109ef712056fc","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should execute zoom-in without errors","durationMs":6534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-a9915f41028dc1735a58","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display view mode select with Overview, Hierarchy and Cross Glossary options","durationMs":4186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-b1f39034ce0f4865a1f6","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display canvas element as graph container","durationMs":4044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-b92e6532e70903eac909","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should close settings panel when clicking outside","durationMs":6245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-b9f727df599b62838593","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should change layout to Circular and back to Hierarchical","durationMs":7394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-bac51c9dbbc8550ddb6d","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should repopulate data-node-positions after fit-view","durationMs":34738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-c379ce8ed6816d3dee2b","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should disable refresh button while graph is loading","durationMs":5825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-c96de381446bbbc2d0bb","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should close entity summary panel when close button is clicked","durationMs":38535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-cd1db73e680f01ad13ba","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should accept a search query in the graph search input","durationMs":5531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-ceb628e919ff42903397","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display edge labels toggle in settings panel","durationMs":6196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-d05255b43441133a4a51","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display exploration mode tabs (Model and Data)","durationMs":3560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-d71ba25e03a1a247ac94","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should hide loading state after data is loaded","durationMs":7047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-ddb8df3897f251c37c4e","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should show loading state while graph data is being fetched","durationMs":4681,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-dfccf61c48ca7e06c1bb","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display search input in graph toolbar","durationMs":3551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-dfd32c508a5b7dd0b3ef","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should execute zoom-out without errors","durationMs":6474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-e1d83cee56a34a75be6d","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should fire glossaryTerms/assets/counts API when refresh is clicked in Data mode","durationMs":8000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-e6b29d0a0951ce8e21b0","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should display filter toolbar with View Mode label","durationMs":3454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-ed1cb368cfa96d436ab7","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should navigate to ontology explorer via sidebar and load page","durationMs":6202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0c7f4cd09abde33f6363-f2f952f6609b0842d4b0","project":"chromium","file":"Features/OntologyExplorer.spec.ts","title":"should clear the search query","durationMs":5214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-047be35b194c9d866468","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide tokenValidationAlgorithm for OIDC providers","durationMs":5221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-0833169ee6407ec5c50d","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide publicKeyUrls field for confidential OIDC providers","durationMs":4720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-0989b149fa1918db6a13","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Azure AD provider","durationMs":4990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-0bcb263825f9b25094cd","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide clientAuthenticationMethod for Auth0 provider","durationMs":5991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-19081ba3791a2c4eba3f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should enable Configure button when provider is selected","durationMs":5294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-1e149432136c7a6db559","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show SAML SP Entity ID and ACS URL as readonly","durationMs":4970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-22abb186177c16862afa","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should stay on /settings/sso when pressing back if SSO is not configured","durationMs":4328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-2474fda7d7d183e84f6f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide publicKeyUrls for LDAP provider","durationMs":5434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-2a2ad991e5c06901f99e","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Okta provider","durationMs":5228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-2e18cb79c436daab7829","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show advanced fields when advanced config is expanded","durationMs":5643,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-34fba19c758dadd4b5cb","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide jwtPrincipalClaims for SAML provider","durationMs":5125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-38ca5d4d684728fccecb","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Google provider","durationMs":5437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-3a87615ac059ba986272","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should navigate to /settings when pressing back if SSO is already configured","durationMs":9537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-3e41514daf189541ef7a","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide SAML SP callback URL field","durationMs":5510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-47ac2af718829befd92f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show tenant field for Azure provider","durationMs":5237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-4daf0d02c9591a8510d5","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should expand and collapse advanced config when clicked","durationMs":5212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-4df25211bef2dfa32e40","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should render authReassignRoles as a searchable dropdown and support role selection, removal, and search filtering","durationMs":6756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-51d4acdbee95dd109eb6","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide preferredJwsAlgorithm and responseType for OIDC providers","durationMs":5506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-546b90ad1991b04d4494","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide serverUrl field for OIDC providers","durationMs":5148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-55b88df9f30715574758","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should collapse advanced config by default","durationMs":5508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-5a6348a858f0bbba6ae2","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting Google provider","durationMs":5887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-61a7fabbf89bc2f26c7f","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields for Okta provider with confidential client","durationMs":5369,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-61d0e3405cdc819cc222","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting Okta provider","durationMs":5809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-67b572e98086ce7eac3b","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show upload drop zone for SAML provider","durationMs":3596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-6a1992cd6f70ad36be17","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should parse valid SAML metadata XML and populate form fields, then clear fields on invalid XML","durationMs":3384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-726836846c61acacf72e","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide jwtPrincipalClaims for LDAP provider","durationMs":5195,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-79775feb638787094aa2","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should display advanced config collapse for OIDC provider","durationMs":4955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-7a25922674aa447ae188","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should support full LDAP role mapping flow: add, fill, open roles dropdown, detect and resolve duplicates, and remove","durationMs":7056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-7a4121fbd7ff73813e83","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show clientAuthenticationMethod for Okta provider","durationMs":5798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-88267c4e251dfab9d1c7","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide publicKeyUrls for SAML provider","durationMs":5280,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-9571bd75cfb56b064f18","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should not display role mapping widget for non-LDAP providers","durationMs":4833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-977c5309463a2194ae58","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields for Auth0 provider with confidential client","durationMs":5405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-98f71413d99725507f60","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields for Google provider with confidential client","durationMs":5964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-9b94064cfad5336dc576","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting SAML provider","durationMs":5405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-a2653b3971e7a3dfe31c","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should hide tenant field for Auth0 provider","durationMs":5725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-b415cb2dc167ddb53dda","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting Auth0 provider","durationMs":5738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-c3a47af5c898e89c1d82","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should validate the configuration without saving and show a success banner","durationMs":7146,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-d785f2f4f674973f449b","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show OIDC Callback URL as readonly for Auth0 provider","durationMs":5342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-debfc2945a6f9ce23750","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show correct fields when selecting LDAP provider","durationMs":5437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-ea466a94c0478617e9d8","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should show the Test Configuration button and lockout warning for a new configuration","durationMs":7224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-f6cf49ad9159c898f8ff","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should surface validation errors when the test fails","durationMs":7384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0da65f5fab90fc1549e2-f74d7edc9c9978851109","project":"chromium","file":"Features/SSOConfiguration.spec.ts","title":"should display all available SSO providers","durationMs":4931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-4e375083d590a9a5acea","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Version diff shows synonym changes","durationMs":7758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-73f6fddc80038a5eae47","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"GlossaryTerm","durationMs":21201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-7cf3cccd2fd4e86bbcd0","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Version diff shows reference changes","durationMs":9592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-926156befd108528b026","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Return to current version from history","durationMs":9991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-abb395dc56eb33d395fb","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Navigate between versions","durationMs":12279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-c125342150e1c90238d5","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Glossary","durationMs":29590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0ee65b8963c2937ca439-c9fa2cbac6df0316a4ae","project":"chromium","file":"VersionPages/GlossaryVersionPage.spec.ts","title":"Version diff shows related term changes","durationMs":11321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0fc3c96fe730fa7ec869-cf1d8bf1cc1db0d05bbf","project":"chromium","file":"Features/IngestionListNameSorting.spec.ts","title":"should keep a sorted page addressable across a reload","durationMs":9502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"0fc3c96fe730fa7ec869-e123a56fe8bf877f9303","project":"chromium","file":"Features/IngestionListNameSorting.spec.ts","title":"should sort the Name column by the name shown in the cell","durationMs":5593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-04d6154814646027d691","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"dataProduct supports removed property value variants","durationMs":5832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-0741446b51bd1831b1fb","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"dashboardDataModel supports removed property value variants","durationMs":5360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-211bb353cbf91b58df5a","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"apiEndpoint supports removed property value variants","durationMs":5548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-2a8d02fe65e159aa7997","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"mlmodel supports removed property value variants","durationMs":5508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-326e5741aa3e465e11c0","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"searchIndex supports removed property value variants","durationMs":5871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-439a804c72c1029b9604","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"domain supports removed property value variants","durationMs":4448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-485027c527c4c17d746c","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"pipeline supports removed property value variants","durationMs":6377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-49aa937a33fa5a8948c9","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"metric supports removed property value variants","durationMs":5784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-4bca0aa80c53d7c4a24c","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"databaseSchema supports removed property value variants","durationMs":5606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-4f16dd456ed5b31f8f8d","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"container supports removed property value variants","durationMs":6827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-5adfe289cb3d8520b0ef","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"tableColumn supports removed property value variants","durationMs":5871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-7f74b79cdc6913ea9d62","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"glossaryTerm supports removed property value variants","durationMs":6340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-89f210443cbeae6bb2c0","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"database supports removed property value variants","durationMs":5065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-8fec358bf4604e70210f","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"custom property value contract covers the exact removed browser matrix","durationMs":18,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-9585120f51c086d40c8f","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"storedProcedure supports removed property value variants","durationMs":6941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-cda8340b8fcb3bc57b4e","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"apiCollection supports removed property value variants","durationMs":5201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-d66611608cf890ccc13c","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"topic supports removed property value variants","durationMs":5318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10c126ce21ddb47756a4-e88886cf009eb2d89a24","project":"chromium","file":"Pages/CustomPropertiesApiContract.spec.ts","title":"dashboard supports removed property value variants","durationMs":4402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"10d375d35d7071018386-deeb63637a49a6e9339d","project":"chromium","file":"Features/Permission.spec.ts","title":"Permissions","durationMs":62113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-1764dc17d058c43ed0e6","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should keep the run history reachable when the status call fails","durationMs":3870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-373310b628ca43526007","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should list the agents with disabled actions when the status call fails","durationMs":3353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-9438db641e0109169435","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should list the agents while the status call is still in flight","durationMs":3668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"119d3ed577f67a8f9d7a-9f029e8b570eb3564250","project":"chromium","file":"Features/ServiceAgentsStatusDegradation.spec.ts","title":"should still explain itself when the status call answers with no reason","durationMs":3801,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-15dfb2af7e1db8aec21c","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":14873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-2de09c93fa26511e5882","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":20482,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-3b84db11da31ab9d60f8","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":19906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-412088496e870362a6bb","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":14439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-5185f8d1e5c3bfb6de74","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":20172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-6c3ef71e9c671b248b36","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":15134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-747d62ad76876a268122","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":15014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-7a96261fbe77abc31f4a","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":20356,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-cdd1bc8be764f4d1dc7f","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":16205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-d007ef1cc9caf0532ddc","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":14876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1257a08d694033b99e03-ffab3b8233da881cb344","project":"chromium","file":"Features/LandingPageWidgets/FollowingWidget.spec.ts","title":"Check followed entity present in following widget","durationMs":17556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-0396a683a217404bc705","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"term from another glossary is hydrated in as a node","durationMs":35937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-3396e18d2b057b036c37","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"cross-glossary edge is present in graph data","durationMs":35767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-343af4d62aaba2630406","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"relation filter with no matching edges shows no-relations state","durationMs":35543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-50ed7c1fbcf33c138817","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"clicking a neighbour node opens the entity panel","durationMs":7087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-51484391b4e911f246e9","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"stats include the cross-glossary relation","durationMs":33462,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-6bb1183fced6fb9f8f96","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"only the term and its direct neighbours appear — unrelated term is absent","durationMs":6655,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-7564b4e242fb53c6b77e","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"zoom and fit-view controls are visible","durationMs":6910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-819430d5e839658621ad","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"removing the relation filter restores connected nodes","durationMs":34875,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-9d0332e87b84fec9721d","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"isolated nodes OFF + unmatched relation filter shows no-relations, not empty state","durationMs":34710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-b12144b2967a7a2731c9","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"edge between the term and its neighbour is present","durationMs":6216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-b471627ee638b7bfebca","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"global filter toolbar is hidden in term scope","durationMs":6028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-c3b40279304ec46428af","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"ontology explorer is visible in the Relations Graph tab","durationMs":5762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1285c81ffe6568e0e5be-d5ce5f84b1effb571047","project":"chromium","file":"Features/OntologyStudioInteractions.spec.ts","title":"re-enabling isolated nodes while relation filter is active keeps no-relations state","durationMs":34563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"138116cad0db6db3e31c-0db6bba1bba36a56c98e","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":25368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"138116cad0db6db3e31c-8ab63046fdfd9ef943c1","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":24932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"13ef108ee6fd737d094f-086a50c8e31b6ccf6ff3","project":"chromium","file":"Pages/DataProductCertificationFilter.spec.ts","title":"lists only certifications assigned to data products","durationMs":7948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"13ef108ee6fd737d094f-a19672220bf86f8386a8","project":"chromium","file":"Pages/DataProductCertificationFilter.spec.ts","title":"filtering by a certification narrows the listing","durationMs":11396,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"14bd5adb6df9a88c340f-29600d766f20a5eaaea8","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should edit reference URL","durationMs":10594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-296c68d33da16a9dd7d8","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should cancel term creation without saving","durationMs":8815,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-2b2204bb8ab1e8834014","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove related term","durationMs":10542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-3b7344c642f950c9343a","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should show error when glossary name exceeds limit","durationMs":8090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-60710dd072ecbdae486b","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove tags from term","durationMs":10484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-67cb7301397b8e2167cb","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove domain from glossary","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"14bd5adb6df9a88c340f-6aef0428615488839b7e","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create glossary with multiple owners (users + teams)","durationMs":14551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-6c8759c68ef5992a7234","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should handle term with very long description","durationMs":9630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-7c48d938e18034fdb3ab","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should replace reviewer on glossary","durationMs":11794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-7c861f5b15fc8efe5687","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should edit reference name","durationMs":10678,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-7e20f808cda196f4b965","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove owner from term","durationMs":12883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-80d0b311299387783e9c","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should replace owner on glossary","durationMs":11263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-8223e5ca58ae964dbb30","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should clear all synonyms from term","durationMs":10798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-87accf1b092c476fa522","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should change domain on glossary","durationMs":11048,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-a1d727fbf53816e3e867","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create term with custom style color","durationMs":9498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-a5945883ff9686302ca6","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create term with custom style icon URL","durationMs":10134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-ab969a7d4761c13683d1","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create glossary with mutually exclusive toggle OFF","durationMs":8721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-bced7f631eafead67a79","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should update term style to set color","durationMs":9758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-bfd5ef7659767ee9c04c","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove individual reference from term","durationMs":10254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-c0a2104006b98732511e","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should show error when term name exceeds limit","durationMs":9502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-d09abb82cd12494db539","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should update term display name via manage menu","durationMs":10948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-d6b1141fd8a29c352619","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should show bidirectional related term link","durationMs":9528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-d81fab109e3f20196586","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should remove reviewer from term","durationMs":11625,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-dcac77ccd1673ede0375","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should cancel glossary creation without saving","durationMs":7238,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-e6d2869b45eb07973d63","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should update term style to set icon URL","durationMs":10246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-f15ee3dbeb3557870e2a","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should handle term with very long name","durationMs":9689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"14bd5adb6df9a88c340f-f9256cb87400d1374dfe","project":"chromium","file":"Features/Glossary/GlossaryAdvancedOperations.spec.ts","title":"should create term with related terms","durationMs":11817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-004c2b1604f9a7169e12","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should return to Overview from Hierarchy","durationMs":5192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-0caa1296673e86baed49","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should retain glossary filter when switching between Model and Data modes","durationMs":35003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-1b4e33aec268b5401dc7","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should open relation type dropdown and show options","durationMs":3814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-1ffd24e09a39b7ea8cbe","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show only one glossary terms when one is deselected","durationMs":64690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-25bcd5e159f57f556d5e","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should display Relationship Type filter label","durationMs":3590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-28a16c00105b85799e4a","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should have Overview selected by default","durationMs":5030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-290e545bea30e4dd2f44","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should switch back to Model exploration mode","durationMs":5169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-3117fec6cce377fd7d96","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should filter to only matching relation type when Synonym is selected","durationMs":35658,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-3ac4537ae03869da14fe","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should open glossary dropdown and show glossary options","durationMs":3225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-3e904d4c4d9a10183ddb","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should update selected option when view mode changes from Overview","durationMs":3378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-431ba0a038457e20b043","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show 2 terms and 0 relations for glossary2","durationMs":34078,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-4b122a6d981da8e2a62c","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show relatedTo edge when Related To filter is selected","durationMs":34699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-5e53d146bb7e1e90290f","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should switch to Hierarchy view mode","durationMs":5248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-5e6059e5873940cb2ccc","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should switch to Cross Glossary view mode","durationMs":5452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-6539ab8a97947694575c","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should display Glossary filter label","durationMs":3091,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-6f1ef5800b4bfd5a38fc","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show clear all when both glossary and relation type filters are active","durationMs":36399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-775d3104d066425745b4","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should have Model mode selected by default","durationMs":4030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-77cc5057190fc0a8054d","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show no results when search does not match any glossary","durationMs":4955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-7d49ff7638e154126118","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should filter glossary options by name in the dropdown search","durationMs":4404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-8777c86141901d618a3c","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show and clear all filters","durationMs":33645,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-b2e6a0302209c14bd967","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should disable the view mode select when Data tab is active","durationMs":5264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-bf02299445d8e91c92b2","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should filter the graph to the selected glossary (stats match canvas data)","durationMs":36165,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-c28f58cdcb31e538046c","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should retain relation type filter after glossary filter is cleared and re-applied","durationMs":65913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-c86c2b68ca26cced22a6","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should filter graph edges by relation type (stats match canvas data)","durationMs":34028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-cd4812a02a7e55807127","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should switch to Data exploration mode","durationMs":5677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-d944afe2825fecccf775","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should toggle isolated nodes off and back on","durationMs":3328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-d9e4ba0583db7be54416","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show terms from both glossaries when both are selected","durationMs":34425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-db7b0cff936497f70d5a","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show 2 terms and 1 relation for the test glossary","durationMs":33804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-ea51d527dc05896f8ce7","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should re-enable view mode select when switching back to Model tab","durationMs":6653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-f781ff8c5e975021279e","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should show graph stats after switching to Data mode","durationMs":33626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1508675d1043294832bd-f81bcef282b79046d9df","project":"chromium","file":"Features/OntologyExplorerFilters.spec.ts","title":"should remove isolated nodes from stats when toggled off","durationMs":33436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-042c40f6b1a54e6c53ae","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when glossary name is empty","durationMs":5261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-48fa78f24f68871eb1a6","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when creating glossary with duplicate name","durationMs":5234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-7932aa55fdb2a147ece7","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when term description is empty","durationMs":6253,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-7fa3c393df4fd3e48395","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when term name is empty","durationMs":5860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"159747fbb5cbe51a0d39-fb157931edfad50a16d6","project":"chromium","file":"Pages/GlossaryFormValidation.spec.ts","title":"should show error when glossary description is empty","durationMs":4528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-108588a17dc7c1e9e7ab","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"filtering by synonym should show only terms connected by synonym and hide others","durationMs":36584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-455d392a14de1202ee13","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"switching back from Data to Model mode restores stats","durationMs":37741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-45db8d08e9700d762767","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"clearing relation type filter should restore all connected nodes","durationMs":36474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-4d34613e9fd9b0bda54f","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"should reflect relation add and remove in the graph","durationMs":105498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-542208ececb3910f878c","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"should display terms with narrower relation in Hierarchy view","durationMs":40372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-77906f4cbeabbb0481ab","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"Data mode stats do not show Data Assets when no assets are tagged","durationMs":38904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-78cdd2ed39025ffeff45","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"filtering by relatedTo should show only terms connected by that relation and hide others","durationMs":37540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-8b23927bba2fc7066544","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"Cross Glossary view hides terms that only have same-glossary edges","durationMs":38148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-a349c74e7f92a667705f","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"isolated nodes toggle is disabled when Cross Glossary view is active","durationMs":5743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-d1299047f5e68bc2788d","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"Cross Glossary view should show edges between terms from different glossaries","durationMs":39770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"16ce324b85d7fb722bdb-d40d2b4f41f456fda733","project":"chromium","file":"Features/OntologyStudioIntegration.spec.ts","title":"clicking asset count badge in data mode triggers asset search query","durationMs":38183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"179dbf18e2af7f4cbec2-3e866d93ac6b4b246fc4","project":"chromium","file":"Features/Permissions/DomainPermissions.spec.ts","title":"Domain allow operations","durationMs":28360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"179dbf18e2af7f4cbec2-f81418f6b9c6495bc826","project":"chromium","file":"Features/Permissions/DomainPermissions.spec.ts","title":"Domain deny operations","durationMs":29046,"attempts":1,"retries":0,"outcome":"expected"},{"id":"18494d13c3e927572e0e-8d190554ecc9cdce0e8b","project":"Basic","file":"Pages/CustomThemeConfig.spec.ts","title":"Update and reset custom theme config","durationMs":8422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"18494d13c3e927572e0e-98fda58f97982dc8e671","project":"Basic","file":"Pages/CustomThemeConfig.spec.ts","title":"Should call customMonogramUrlPath only once after save if the monogram is not valid","durationMs":9455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"18494d13c3e927572e0e-c6dc3de533286e6d221d","project":"Basic","file":"Pages/CustomThemeConfig.spec.ts","title":"Update Hover and selected Color ","durationMs":8723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-1087a144c5cc50d535ee","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should open right panel when clicking data product card in domain","durationMs":9079,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-13aa03b757371c9adb72","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should display overview tab for data product","durationMs":8308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-237ee97a03dc27da8efa","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should display overview tab content for data product in domain context","durationMs":7050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-2cdd99c8ce2bb06b59ed","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should not display glossary terms section in domain data products context","durationMs":7555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-a76035f76a4eea346b55","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should display data product name link in panel in domain context","durationMs":8455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-c15c8f4e2f276a832be4","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should edit tags for data product from domain context","durationMs":9357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-cffeac6eeaa76dd6886b","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should edit owners for data product from domain context","durationMs":10426,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-de5961ae0dcc1dc1eb7c","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should edit description for data product from domain context","durationMs":9531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1868f38c02e67c5911d3-f4986293245e7e080a70","project":"chromium","file":"Pages/DomainDataProductsRightPanel.spec.ts","title":"Should assign tier for data product from domain context","durationMs":9912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-537cb9c232ceabecba8e","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"service lineage has pipeline service connected to both services","durationMs":3637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-612653f6947301a02b49","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"database service has pipeline service as downstream in service lineage","durationMs":3217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-80746b789ad7769474c0","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"entity lineage does not include service nodes","durationMs":3776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"191a039569461c2eb042-a52558b2d5f6468bb5ea","project":"chromium","file":"Features/LineagePipelineAnnotator.spec.ts","title":"entity lineage edge preserves pipeline annotation","durationMs":4438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-02b5ace1b2248b785a49","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with EditAll can export ODCS contract","durationMs":10633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-2125ddb8382292c5fdda","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with EditAll can import ODCS contract","durationMs":12155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-2ff6b56ee053f07bce20","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Admin should see all import and export options for existing contract","durationMs":7514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-4bc8465740aa8464ebd6","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Admin should successfully import ODCS contract","durationMs":7636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-5cc7d37ab19d320a7f43","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Consumer can export ODCS contract","durationMs":7543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-5fd734b0bc28d6e08535","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Consumer should see export but not import options","durationMs":6677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-75e594ea4b3040db9f2b","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with ViewOnly should see export but not import options","durationMs":10532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-82f6c0dde199e09a485e","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Admin should successfully export ODCS contract","durationMs":6956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-83e7b1c072c2dde4d9ea","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Steward should see export but not import options","durationMs":7889,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-b39b794f3ed9fde9e63c","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"API should allow export for users with view permission","durationMs":4776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-c6dae5c5f1756c1d0e66","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with EditAll should see all import and export options","durationMs":10410,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-d72f4e2dbeb3c195ab46","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"Data Steward can export ODCS contract","durationMs":7258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19af7aac2231565e0ab5-ed0768c8b67f4feea53f","project":"ImportExport","file":"Pages/ODCSImportExportPermissions.spec.ts","title":"User with ViewOnly can export ODCS contract","durationMs":8374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19b2b14ce084d7e3579a-201004f6be67ac9d9065","project":"chromium","file":"Features/CustomMetric.spec.ts","title":"Column custom metric","durationMs":19915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19b2b14ce084d7e3579a-c4d4be4d5d794d22c090","project":"chromium","file":"Features/CustomMetric.spec.ts","title":"Table custom metric","durationMs":10495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-3b16f2702fc12cd8074e","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create term with tags","durationMs":9783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-45bb6a8bde203b85b1cf","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create glossary with tags, owners, and description","durationMs":8108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-51e4f8807e00f57e0192","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create term with synonyms","durationMs":9186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-612c0266b544101fdc87","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create child term via row action button","durationMs":8702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-ad5dd701c1d496e2781d","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should navigate between tabs on term page","durationMs":7470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-b3aae0fef2551ec89460","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove owner from glossary","durationMs":7980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-c2ba3a55bcfac2bf76cb","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create glossary with mutually exclusive enabled","durationMs":8603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-e9fd39fecbc9feeff1f8","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should delete parent term and cascade delete children","durationMs":7819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-ec658667dc5b068c0a42","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove reviewer from glossary","durationMs":7456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-ee3ddfd6112d2b10da41","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove tag from glossary","durationMs":7807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-f3901eb61f81592f1a02","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should display parent term with children for drag operation","durationMs":7428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-f658c35c19332d4004f1","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should remove synonym from term","durationMs":7666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"19e537c12a95217f1b60-f8e45548f1769c59d321","project":"chromium","file":"Features/Glossary/GlossaryCRUDOperations.spec.ts","title":"should create term with references","durationMs":9145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a6f1da61460ebe7ad36-7a6c1a3faf2cfc2648d7","project":"chromium","file":"Features/QueryEntity.spec.ts","title":"Query Entity","durationMs":29411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a6f1da61460ebe7ad36-a06d40e1bc9c3f5e1457","project":"chromium","file":"Features/QueryEntity.spec.ts","title":"Verify query duration","durationMs":10433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a6f1da61460ebe7ad36-cf42d000893656b64dbd","project":"chromium","file":"Features/QueryEntity.spec.ts","title":"Verify Query Pagination","durationMs":10827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-0088ed46eab587c90371","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should restore filters from URL on page load","durationMs":11518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-014321099028e71df84c","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should load the page with stats cards and grid data","durationMs":7779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-170dbfd48cfc4dd5c106","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show Service filter chip from URL","durationMs":9657,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-185597b794db3ab6912c","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should update display name and propagate to all occurrences","durationMs":26004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-239c0f77e33ddb02ed00","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should search columns with server-side API call","durationMs":8124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-23c5e0255a245d7bd4a2","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should clear individual filter and update URL","durationMs":22068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-2e96f151f46e62aaae33","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should select and edit nested STRUCT field","durationMs":24638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-32b4d960f036903b8b97","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should open edit drawer when clicking on aggregate row","durationMs":5822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-39e4bd843402570f4339","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show success notification after bulk update","durationMs":27399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-3ef93584d85256069ad4","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show no results when searching for nonexistent column","durationMs":7852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-3ff3cebfc11e44e7369b","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show disabled edit button when no columns are selected","durationMs":5539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-4a4df818cbe72b56fd42","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should not reset stats to zero while search request is loading","durationMs":7845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-59c5f8a31c7199210394","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should not count aggregate parent row in drawer selected count","durationMs":6834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-5dac5fccf031408603db","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should expand STRUCT column to show nested fields","durationMs":25371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-6c8908c3cd1359e50b2b","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show pending progress spinner after submitting bulk update","durationMs":22861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-7267cda84897fc91f6dd","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should update pending changes counter when editing selected columns","durationMs":23547,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-797101ebe2b800c4b2a4","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should select column, open drawer, and verify form fields","durationMs":23850,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-8491c672cd59d38141d9","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should show column count for multiple column selection","durationMs":3453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-8b7eb228bf6a6d35884e","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should filter by metadata status and verify API param","durationMs":26462,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-94fbdadd8c9d95ead874","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should filter by entity type (Table)","durationMs":7054,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-c6b5c6fa386a261c9945","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should cancel selection and disable edit button","durationMs":21941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-c9cf4dffe0aa3ea711bb","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should accept text with spaces in the description field","durationMs":21050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-cef1122673da72e852b8","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should navigate through pages","durationMs":9419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1a7cffc95ce4e87fc41d-d2e9a4b29a88686387ab","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should keep latest search results when responses arrive out of order","durationMs":48745,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"1a7cffc95ce4e87fc41d-da1a0b3fd0cc0e01ed6d","project":"chromium","file":"Features/ColumnBulkOperations.spec.ts","title":"should discard changes when closing drawer without saving","durationMs":25322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-7ff955e7b470d12f6b1f","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve mlFeature description task for MlModel","durationMs":653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-968585514b3da1da4c2e","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve requestSchema field description task","durationMs":599,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-9ab19e4c245ad906a5d7","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve responseSchema field description task","durationMs":291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-b59abc2f87ac29cd2972","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve nested field description task for SearchIndex","durationMs":190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-b8d86ff533deaebb79b9","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve field description task for SearchIndex","durationMs":218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1bce88623bfa04916f7a-ceff75e902b4028fe53b","project":"chromium","file":"Features/Tasks/TaskNestedFields.spec.ts","title":"should create and approve column description task for DashboardDataModel","durationMs":386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-088888d65c2c12c7041b","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with EditAll on TEST_CASE resource should not be blocked from bulk edit page","durationMs":11904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-10fd0dc506e83a7ecd02","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer should see export but not import & edit options","durationMs":9166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-12f1201233201134e21a","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should redirect to Table Data Quality tab when canceling table-level bulk edit","durationMs":9799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-219eece6de17e298670b","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to import page from Data Quality tab","durationMs":5513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-2f5d1810bf9a82344168","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should export test cases from Logical Test Suite page","durationMs":9290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-3514378a10d1a2777e69","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should upload and validate CSV file","durationMs":14353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-4469b1ebd6879db66e32","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with EditAll & ViewAll on TEST_CASE resource should see import, export & edit options","durationMs":12807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-47d1b7b068edeb4ac63a","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward should be blocked from import page","durationMs":5917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-570ebf80af90e61924f8","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer can successfully export test cases","durationMs":9964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-62a7e656fc98846ddce6","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer should be blocked from bulk edit page","durationMs":3802,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-6647b28c5e6d51f38b7b","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with ViewAll on TEST_CASE resource can successfully export test cases","durationMs":16117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-66538490a691fb2cadbe","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should redirect to Test Suite page when canceling bulk edit","durationMs":10340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-6f744fd1e24888ade4df","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Consumer should be blocked from import page","durationMs":4093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-76c7b490768e9355c0d9","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward should see export but not import & edit options","durationMs":8679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-7ebd62f24bf13648f5fe","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward should be blocked from bulk edit page","durationMs":5038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-8b8f266e0c798fecdbf0","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"Data Steward can successfully export test cases","durationMs":12886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-9aac88cc9731e6741e41","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should show validation errors for invalid CSV","durationMs":9584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-c3b94742e06f23717451","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should redirect to Data Quality page when canceling global bulk edit","durationMs":10149,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-c555aec9e622f36a508c","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"User with EditAll on TEST_CASE resource should not be blocked from import page","durationMs":8167,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-d3e2ea3896d13e010edd","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should export all test cases from global data quality page","durationMs":15001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-e074e2a35b2354778e27","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should export test cases from Data Quality tab","durationMs":10960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-e41293a41d782cbfb0c7","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to import page from global data quality page","durationMs":4672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-f20e9de461c4e6cfadc6","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to bulk edit page from Logical Test Suite page","durationMs":15526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1c1beaa6e6bb68455687-f7761c9107599ffa5435","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportBasic.spec.ts","title":"should navigate to import page from Logical Test Suite page","durationMs":4782,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-081025371a2814b4fb5f","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":11835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-0a4191b4db0efcbae0f8","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":9794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-11ad6728a046d81592e9","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-16216a857e97288f66c5","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-1d2ca67614bbdde8e805","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-1ea9821cb6097c0ec98f","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":10856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-20781c678687a66fa68b","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-20f85fdc0656235f5cf7","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-2abec9f21a8ea3b2cc4f","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":15010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-2e08b3569bf413a4b41d","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-2eee0c93c970f8d07682","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":14807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-38553a39450ce7270e88","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-4f11e50f706352784b6e","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":11945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-5bf28053c2a051ccdfa3","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-693a5a472bbdcd5d7c39","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-6f03ad71cb5cf3694aeb","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":8760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-70f4e24aa49e1afddd61","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":10868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-75aab610bb32463cf2dd","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":8862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-7930c4d3ae24ea30f63c","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":7715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-7bbb32de38f97fcb06e3","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":10568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-7d221bdeacd5afefd2ab","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":10882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-88e41b978ee0ef287d92","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":13044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-8db06fd539e01dd3bbaf","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10480,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a1a032a22693be0119e4","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column displayName immediately without refresh","durationMs":10708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a5652ed373875bbfa978","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a83ffa17458ba063ab54","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":11870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-a89c14c356526919c60e","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":8406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-b9b78692b1500d345e57","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":9704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-c458a06a93bfddc93263","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":8926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-cf44adf2e574fb2cbc19","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":12110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-cfdcfe160d3952303e12","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-d1725f195b4f94165c61","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":14338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-d3a1704a85d2cfaf31cd","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":9196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-d636fe1feb6796f668e6","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should update nested column description immediately without page refresh","durationMs":10847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-f2418d8c375a80d46f69","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":13058,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ce96103ecb38ee49d41-fd849b08a1243d3a9494","project":"chromium","file":"Flow/NestedChildrenUpdates.spec.ts","title":"should add and remove tags to nested column immediately without refresh","durationMs":14909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ceb1bff96abee8abc39-80f3f55b370556d0a638","project":"DomainIsolation","file":"Features/DomainIsolation/DomainDropdownIsolation.spec.ts","title":"Admin sees every domain and the All Domains option","durationMs":7436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ceb1bff96abee8abc39-cfe97d75645c1db901ff","project":"DomainIsolation","file":"Features/DomainIsolation/DomainDropdownIsolation.spec.ts","title":"Restricted user sees only their own domains in the navbar dropdown","durationMs":5901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-1965ba5132d65f76b54f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should assign tier from tag assets page context","durationMs":13335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-1f93c23ec60eeb578f8f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit owners from tag assets page context","durationMs":14763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-6551d3f84e4ae3617f7f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit description from tag assets page context","durationMs":9167,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-6d105f08c01f5f945b88","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should open right panel when clicking asset in tag assets page","durationMs":12335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-74d2940c2fb33c358ae0","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should display correct tabs for table entity in tag assets page context","durationMs":7568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-8a7973d64b54fd04b10f","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should display overview tab content in tag assets page context","durationMs":8746,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-9193d8183ffaf8094b63","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit tags from tag assets page context","durationMs":12420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-9613819e7989c4a50ea5","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit domain from tag assets page context","durationMs":13190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-c822ef782390b573e856","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should edit glossary terms from tag assets page context","durationMs":8794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-cf6d8d95a859ea58c1be","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Should display entity name link in panel header in tag assets page context","durationMs":7551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1dfc98d9ffa275f39c23-fc44c04a118fcf119b28","project":"chromium","file":"Pages/TagPageRightPanel.spec.ts","title":"Panel should not be visible before any asset is selected","durationMs":2705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1e7ae5f087867b855c68-48cd403ded8704aa6847","project":"chromium","file":"Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts","title":"navigates to the entity detail page when the link is clicked","durationMs":9045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1e7ae5f087867b855c68-4dc58e52f2b3ef4ddc40","project":"chromium","file":"Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts","title":"renders a clickable entity link for instances with a related entity","durationMs":8888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1e7ae5f087867b855c68-50e09093829a8af6a7a5","project":"chromium","file":"Features/Workflows/WorkflowExecutionHistoryEntity.spec.ts","title":"shows the no-data placeholder for instances without a related entity","durationMs":8517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-0b7d1730a6386f5560c5","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"a non-leaf node count reflects the active Data Assets filter","durationMs":9838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-2cbd0173a43e19a49632","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"selecting a schema keeps the drilled path expanded and highlights it","durationMs":9199,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-4062943a54eac71c08c2","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"browsing the tree stacks removable QUERY chips and filters results","durationMs":9733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-50dc1266c26cb8e4ef67","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"the entity-type leaf respects the Data Assets filter (Table hides Columns)","durationMs":12205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-622bb480069d7b96ff7f","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"Glossary leaf under Governance filters the results","durationMs":8519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-86705f5803eae96f692b","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"drills the database hierarchy down to the Tables and Columns leaves with counts","durationMs":7947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-94b4249e6fb96c12d2b3","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"service type drill-down disables unrelated roots and query-panel Clear resets it","durationMs":10158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-9e4da591f01ee8f4968d","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"result-card breadcrumb collapses a deep path and expands on click","durationMs":6251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-a705079e6c267810beba","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"selecting the Tables leaf highlights the leaf, not its parent schema","durationMs":8900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-a84cc2d736afdc4a7016","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"Tags leaf under Governance filters the results","durationMs":9000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-f1cb8868b95fbc0f7ce2","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"every result-card breadcrumb links to its hierarchy destination","durationMs":8627,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1ecb1fcf553f8b440284-fac7d8785eac504ff222","project":"chromium","file":"Pages/ExploreBrowse.spec.ts","title":"drills a non-database hierarchy (Dashboards) down to the entity-type leaf","durationMs":8964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1f761de977875b0ac365-5f3ed1d5eca7edaa77b7","project":"Basic","file":"Features/TeamsHierarchy.spec.ts","title":"Add teams in hierarchy","durationMs":18273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1f761de977875b0ac365-9f33170dce0c34953135","project":"Basic","file":"Features/TeamsHierarchy.spec.ts","title":"Check hierarchy in Add User page","durationMs":11672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"1f761de977875b0ac365-c663c28071eca27c2f9f","project":"Basic","file":"Features/TeamsHierarchy.spec.ts","title":"Delete Parent Team","durationMs":11434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2001c1c02e517ab398de-49967e402c6c0fbe2572","project":"Basic","file":"Flow/LineageSettings.spec.ts","title":"Verify lineage settings for PipelineViewMode as Edge","durationMs":15531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2001c1c02e517ab398de-79465f7bd5a7cf3d01cc","project":"Basic","file":"Flow/LineageSettings.spec.ts","title":"Verify lineage time filter and tab switch reuse loaded graph","durationMs":10330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2001c1c02e517ab398de-c9abd4818a163664575b","project":"Basic","file":"Flow/LineageSettings.spec.ts","title":"Verify global lineage config","durationMs":27238,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-48420345617d1a8ef174","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Resolving incident & re-run pipeline","durationMs":17751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-6defbf65f0f7b32af71a","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Verify filters in Incident Manager's page","durationMs":10569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-77c6d8b0db807c48f0f5","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Rerunning pipeline for an open incident","durationMs":18516,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-af5d262d6380615148dc","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Validate Incident Tab in Entity details page","durationMs":6100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"20371b414745b84fa481-d2d654438df91f046bde","project":"Ingestion","file":"Features/IncidentManager.spec.ts","title":"Complete Incident lifecycle with table owner","durationMs":32190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-137a99fe0f15c4a98a02","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Drives Service Spreadsheets Table should have search functionality","durationMs":9635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-25125140ebe405ad916b","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Drives Service Directories Table should have search functionality","durationMs":10403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-4448687b3721cbb49b49","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Stored Procedure Table should have search functionality","durationMs":10648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-5cf93c1909876091f46c","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Database Schema Tables tab should have search functionality","durationMs":10977,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-60cfa1796b7b024699b6","project":"chromium","file":"Features/TableSearch.spec.ts","title":"API Collection page should have search functionality","durationMs":11001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-76b22267beb30e6ce153","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Services page should have search functionality","durationMs":11317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-79db68618d5b1154ffa1","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Data Models Table should find data models by displayName","durationMs":10795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-8f0b48ff70e49c23a10c","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Drives Service Files Table should have search functionality","durationMs":10160,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-cc7c974eeb90a2ace251","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Data Models Table should have search functionality","durationMs":10849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-d705aa5a323d4919dc01","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Data Models Table should find data models by mixed-case name","durationMs":11931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"219bf5247ddf993e2ac8-fede3d39c728e9fc5d3b","project":"chromium","file":"Features/TableSearch.spec.ts","title":"Topics Table should have search functionality","durationMs":10784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-7a5065f335aef4798767","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Multiple rename + update cycles - assets should be preserved","durationMs":27777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-8268f8edccd6575fc094","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Rename then change owner - assets should be preserved","durationMs":19161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-e6575adf21443f9e4abc","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Rename then update description - assets should be preserved","durationMs":19807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"22036fdb926ee3722bad-f2d0ea7623838b225b12","project":"chromium","file":"Features/DataProductRenameConsolidation.spec.ts","title":"Rename then add tags - assets should be preserved","durationMs":18428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"222fe1e5206cdd75a358-7d5f8774b1fce82284d3","project":"Basic","file":"Features/CronValidations.spec.ts","title":"Validate different cron expressions","durationMs":9469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-3c63e984b9371e4d91c8","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All with Draft filter shows all terms including children of non-matching parents","durationMs":9040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-689fbbe40540b5d50eff","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All with default filter shows all terms","durationMs":7470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-b0971994404c76b9db78","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All shows all children regardless of status filter","durationMs":12145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"228158f5b924c0adbd50-b5a7414e2cf53479e246","project":"chromium","file":"Features/Glossary/GlossaryExpandAllWithStatusFilter.spec.ts","title":"Expand All with Approved filter shows all terms","durationMs":8923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2385db9fde781bb59544-ac35955bbae6a48adf8c","project":"chromium","file":"Features/IncidentManagerPagination.spec.ts","title":"Page size dropdown updates list limit and resets to page 1","durationMs":6618,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2385db9fde781bb59544-fd49dbad03ff26fc50b3","project":"chromium","file":"Features/IncidentManagerPagination.spec.ts","title":"Next, Previous and page indicator","durationMs":6251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-064c76de14054d025202","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> apiEndpoint","durationMs":32104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-0d9bbd826523da4a8f43","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> apiEndpoint","durationMs":36882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-0f02f3b748ae134173df","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> table","durationMs":33613,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-13cc491cb5ca92a3ab0c","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - File","durationMs":187485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-14b2454310f82a3c0843","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> searchIndex","durationMs":30009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-16eca21baf156dbcf4a0","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> apiEndpoint","durationMs":28460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-18358f8facc6b4296831","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Spreadsheet","durationMs":174081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-1e0430cd28c2c8054cfa","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"should render temp lineage table nodes on canvas","durationMs":9368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-21ce9dbac82c26a63b8f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify validation for invalid depth","durationMs":7378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-27638ce37ef6999a284b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> dashboard","durationMs":41793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-2b7f46364906eadbe405","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> mlModel","durationMs":31265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-2d3070c5aa20d0e6b1a8","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Mlmodel","durationMs":192299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-2e4b6ec4efa6124ddd72","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Dashboard","durationMs":159490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3002f790005cb7ba6c34","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> dashboard","durationMs":46011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3278ea25b8daecaafd8c","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> dashboardDataModel","durationMs":39279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3352b05fd95f5a0fb235","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> container","durationMs":39215,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-33ae36b1fd82757cf284","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> mlModel","durationMs":32386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-34679292daa52dbac8ea","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> container","durationMs":42886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3608f98e2232fd6df0d8","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> mlModel","durationMs":46612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-376d116700017793d718","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> table","durationMs":40980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3f62ca7c8be0ab85c351","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> container","durationMs":29651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-3fe7b58036a4a2125b1d","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Topic","durationMs":182358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-40413374e8b581e88eac","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> dashboard","durationMs":35801,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-48e22825f7eae0f3f29e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> container","durationMs":41307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-49a209210dc5932f5be4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify opening config modal","durationMs":6266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-4bbf4f6c6dd680998645","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> table","durationMs":29037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-4c982c2809b69bbd1a2e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> searchIndex","durationMs":29660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-4fe8582f7af9544ed9ec","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> dashboardDataModel","durationMs":36023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5295edf4c7e15940f709","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> topic","durationMs":30704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5a8d6ed8c112615ed27e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> dashboardDataModel","durationMs":36474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5ae6ed5a7ee2578ac818","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> apiEndpoint","durationMs":29507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-5e542cc97152d8d0705f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> dashboardDataModel","durationMs":34947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6241640d58a39cee5537","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> searchIndex","durationMs":38851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6455912558e4fffeac0e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> container","durationMs":34071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-69c142e64207aaa0a94f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> table","durationMs":32332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-69c9ae55c31c1431989e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify column layer is applied on entering edit mode","durationMs":11847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6de016ff06d3e247fd60","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Table","durationMs":194803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-6f9687cfb5ff37d4c970","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> topic","durationMs":29748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-71053c4836b2f2c2bab7","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> topic","durationMs":37590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-74f9f044f9d408f8b511","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Data Model","durationMs":160912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-75b8c3ece17cc1e26d1b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> topic","durationMs":29720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-77f07e78b114d7e380a6","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> topic","durationMs":42465,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-7818a3c39c2e3d1ab93e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Worksheet","durationMs":135734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-7d446a8e5d1ae09b69ec","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Container","durationMs":186097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-822e290d4cae6826f11b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> dashboardDataModel","durationMs":37038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-84a4f88be0b0883d0548","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> searchIndex","durationMs":30395,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-86837102759c8b88c7ee","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> mlModel","durationMs":32404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-8a4216c454f70b116882","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> apiEndpoint","durationMs":39368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-8fc92b51471bd08b5ee2","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> apiEndpoint","durationMs":39530,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-902d02b5e1addc6fbcc4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> searchIndex","durationMs":31810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-904f3f185881ee29c575","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Pipeline","durationMs":157466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-924a8f8064c2cb3d0f90","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> container","durationMs":41693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-95a4a55f764426dfa3a9","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> table","durationMs":24579,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-9607caba24e30eadfc51","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> topic","durationMs":41878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-9751a8c99a2653f2aa30","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Search Index","durationMs":188794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-9b4c4e7691752df4be4a","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> dashboard","durationMs":40563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-a026fb430f338403d586","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> table","durationMs":42413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-a81da11d3e68f71662af","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> table","durationMs":43102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-a93a5af92da1405c4d6b","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> dashboardDataModel","durationMs":35732,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-b1bf9ca4eb8f2934bcf2","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify there is no traced nodes and columns on exiting edit mode","durationMs":9939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-b236ad548d05490edec9","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> dashboardDataModel","durationMs":41170,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-b8b8c397dd2d10aef2ed","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> dashboard","durationMs":31942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-bf398b163b9ef3139ff4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> container","durationMs":38576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-bf4451a64295a0504826","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Directory","durationMs":133745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c0636255e8b026bb90ee","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> mlModel","durationMs":40852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c3a968d05e03db815c90","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> container","durationMs":38308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c711e248c5afd84bbb51","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> dashboardDataModel","durationMs":38970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c7287b311547d884a060","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> dashboard","durationMs":39421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c7e215f258b4cd2440ff","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> mlModel","durationMs":39678,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-c7e39beb095c4acf268f","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> apiEndpoint","durationMs":39386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ccd10903aa517591cbeb","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for mlModel -> dashboard","durationMs":38233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-cd31152efe795b3feee3","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for apiEndpoint -> mlModel","durationMs":49476,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-d161a00652e6b794a397","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for searchIndex -> apiEndpoint","durationMs":30775,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-d4f051fa41ede4629590","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> topic","durationMs":36736,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-d6dd53d462492cf5c9fd","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboard -> table","durationMs":33620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-dace76fe5d6fd2759124","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> dashboard","durationMs":36947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-e64fffa15e978be71af6","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for container -> mlModel","durationMs":34123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ea05741da3a8f6c58340","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> topic","durationMs":69158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-efddc2fb2b825c20769e","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for topic -> searchIndex","durationMs":40448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-f170cfec3b7f57bec7f5","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for table -> searchIndex","durationMs":29728,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-f98474a8fa60fbf4ca6a","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Stored Procedure","durationMs":182974,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-f996fdec580d71b0adef","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Column lineage for dashboardDataModel -> searchIndex","durationMs":33017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-fecafeaa4ce3edd1b3c4","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"Verify updating depth configuration","durationMs":6608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ff9ebdfc07b8ba7d3850","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Metric","durationMs":181289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"260a9e5977a8ba3ec78b-ffb10f915aca070503ee","project":"chromium","file":"Pages/Lineage/DataAssetLineage.spec.ts","title":"verify create lineage for entity - Api Endpoint","durationMs":128956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"265968562dab11101b36-37daa773ced9fd7bf0ec","project":"Reindex","file":"Features/DataQuality/TestCaseStatusAfterReindex.spec.ts","title":"Test case status survives a full entity reindex","durationMs":2212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"26611e95fed0ca4ab3e1-78c7a95661587119e576","project":"chromium","file":"Features/ExploreQueryBar.spec.ts","title":"query bar is persistent and shows the browse placeholder when empty","durationMs":5895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"26611e95fed0ca4ab3e1-b1aa54afdc73b54d2452","project":"chromium","file":"Features/ExploreQueryBar.spec.ts","title":"selecting an asset type grays out incompatible tree categories","durationMs":9011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"26611e95fed0ca4ab3e1-e2061d62ce11ee960ccb","project":"chromium","file":"Features/ExploreQueryBar.spec.ts","title":"filter survives a tree click and both stack as removable chips","durationMs":17148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"27048049e118f657f450-24951d56e8cd5d4b8308","project":"DomainIsolation","file":"Features/DomainIsolation/DomainSearchIsolation.spec.ts","title":"userA finds tenantA and domainless tables but not tenantB","durationMs":4029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"27048049e118f657f450-ad87b762a7e4e02c372b","project":"DomainIsolation","file":"Features/DomainIsolation/DomainSearchIsolation.spec.ts","title":"admin finds tables from both tenants","durationMs":3909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"27048049e118f657f450-c663e9f8f53d1aa53eba","project":"DomainIsolation","file":"Features/DomainIsolation/DomainSearchIsolation.spec.ts","title":"userB finds tenantB and domainless tables but not tenantA","durationMs":4002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"281c15345384604a0b9f-5e289bddf5fb4d98b73c","project":"chromium","file":"Pages/TaskFormSettings.spec.ts","title":"creates and updates a task form schema from settings","durationMs":18097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"281c15345384604a0b9f-b6e254ef505635b44b37","project":"chromium","file":"Pages/TaskFormSettings.spec.ts","title":"loads built-in tag suggestion schema in the visual designer","durationMs":11488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2824251716383e5d36e7-2060084764dd7ff53518","project":"chromium","file":"Pages/EditClassification.spec.ts","title":"Edit a user classification from the manage button","durationMs":12725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2824251716383e5d36e7-a00456cc1a9c0dc1352f","project":"chromium","file":"Pages/EditClassification.spec.ts","title":"System classification name is disabled in the edit drawer","durationMs":11585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28a5e8d47dd39a15b905-2e9b470072e7b23085df","project":"Basic","file":"Pages/DataMarketplacePermissions.spec.ts","title":"Data consumer can search and view results","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"28a5e8d47dd39a15b905-bff1a99ffc922deb45bc","project":"Basic","file":"Pages/DataMarketplacePermissions.spec.ts","title":"Admin sees add buttons and customize button","durationMs":6197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28a5e8d47dd39a15b905-c1e99a61cbaee27a3291","project":"Basic","file":"Pages/DataMarketplacePermissions.spec.ts","title":"Data consumer does NOT see add buttons","durationMs":8534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28dfe7a0de9ed4705a0e-05876c29593dba931db0","project":"chromium","file":"Features/Glossary/GlossaryVoting.spec.ts","title":"should upvote, downvote, and remove vote on glossary","durationMs":10949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28dfe7a0de9ed4705a0e-99e8ed1d5f5e1d0f3445","project":"chromium","file":"Features/Glossary/GlossaryVoting.spec.ts","title":"should persist vote after page reload","durationMs":48935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"28dfe7a0de9ed4705a0e-c3e1cb2ae49780d2d5af","project":"chromium","file":"Features/Glossary/GlossaryVoting.spec.ts","title":"should upvote, downvote, and remove vote on glossary term","durationMs":12578,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-01fa65289fdf7772d19a","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Warning shown when removing asset that is also an output port","durationMs":8264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-069bf1431194facaaaf2","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add single output port","durationMs":10077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-09afee46c87e2c0c5306","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage displays input and output ports","durationMs":8202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-11bbd39747f89aaae32c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Remove last port shows empty state","durationMs":11371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-14e8ceea3982385db337","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Tab displays correct port counts","durationMs":8126,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-174d16335a712ce9a332","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage controls work","durationMs":7532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-1c9f8da89ee745c9cdca","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output port drawer quick filter - behaviour matrix","durationMs":12734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-21e7b442b2a6c36c89bd","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Tab renders with empty state when no ports exist","durationMs":6859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-3a74fad72d2d54a8e468","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"No warning when data product has no output ports","durationMs":7800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-3d3e7086548e88c3849a","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port drawer quick filter - behaviour matrix","durationMs":14589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-479038eb5f8430331d00","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output ports list displays entity cards","durationMs":7600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-568c9f18724fb22d5c00","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage with only output ports","durationMs":7388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-5872d10a29e1a2d4b052","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output port drawer shows info banner about data product assets","durationMs":7743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-599f62d906523734a071","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input ports list pagination","durationMs":8752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-623807bc4cef3c742778","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Remove single output port","durationMs":11251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-63e50a82f75c0228edce","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add different entity types as ports","durationMs":16709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-68ed4c25507e6cadedf7","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Cancel adding port","durationMs":8991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-6b0f41ca117d5b0956bb","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add multiple input ports at once","durationMs":12548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-72f0804125828c6f149c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output port drawer only shows data product assets","durationMs":8858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-733ae742a4ce02354d12","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage displays data product center node","durationMs":7632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-79a2f83588f41a76de4c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage loads on expand","durationMs":7404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-819607994bef4b006508","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage section collapse/expand","durationMs":8080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-8aeba85897967d48c777","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Exit fullscreen with button","durationMs":7649,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-94ae8a7689822d8918e3","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage with only input ports","durationMs":8589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-9b8cedfbb43e6bd23630","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input ports section collapse/expand","durationMs":8134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-a73ed6ab8a060722d7d5","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port drawer shows assets from outside data product","durationMs":9309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b1527c09bef737ec3c9e","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Port action dropdown visible with EditAll permission","durationMs":7299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b3dd87c04273c0020ea9","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Multiple sections can be collapsed independently","durationMs":8401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b4817323e9d164afc510","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add single input port","durationMs":10767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-b5c149038668b3f7479f","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port drawer does not show info banner","durationMs":6156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-c7afe91593115b6d8e4c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Toggle fullscreen mode","durationMs":8241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-d220e4be7b73acd6cf5c","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"No warning when removing asset that is NOT an output port","durationMs":8454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-d54c0a93937f198e079e","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Lineage section is collapsed by default","durationMs":7957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-d9854a7ec2e3f18edc97","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Bulk delete shows warning listing only assets in output ports","durationMs":7500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-ddaf39a4e6d62adc4e31","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Exit fullscreen with Escape key","durationMs":8377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-ddb0e52df0f2bb65f38b","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Output ports section collapse/expand","durationMs":34354,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"29d4e0f3d05ee7ab11db-e631fe73e88dac5cda61","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Cancel port removal","durationMs":8417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-e70c9d333f1aebdbede6","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input port button visible, output port button hidden when no assets","durationMs":6834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-e8229144fe684928d7de","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Add input port from asset not in data product","durationMs":11276,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-ee7e0ca8a849e28a74bf","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Input ports list displays entity cards","durationMs":7113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-f04ff612f7841b2c6dcf","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Fullscreen lineage is interactive","durationMs":7644,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-f0887c631c4e55ebf462","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Removing asset from data product also removes it from output ports","durationMs":9258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"29d4e0f3d05ee7ab11db-f1ce0182791a75fb7ddd","project":"chromium","file":"Pages/InputOutputPorts.spec.ts","title":"Remove single input port","durationMs":8707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-3c1aaf6e29997cd9b74d","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create and approve entity-level description task for Container","durationMs":793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-c3d9df18c364056c0ec0","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create and approve dataModel column description task for Container","durationMs":502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-cf8c6964fbe2bb99e5b4","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create DomainUpdate task for Container","durationMs":910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-e777ffbc4ddc1cfbc9ac","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create TierUpdate task for Container","durationMs":294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad3d86ca94d03ac7cb5-ed5bd6cb911fba4657f4","project":"chromium","file":"Features/Tasks/TaskContainerEntity.spec.ts","title":"should create OwnershipUpdate task for Container","durationMs":1188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-3536acf272fc1235a483","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"KPI Widget","durationMs":42209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-39b17deca4f99ff79e80","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Data Products Widget","durationMs":53211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-595be3cd2493a7346dea","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Domains Widget","durationMs":54347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-7e3c2324ccd07d25501a","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Total Data Assets Widget","durationMs":34716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-833499f6d2acc671ad5b","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Activity Feed Widget","durationMs":23654,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-8b144a6bf607ae7fadd9","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Following Assets Widget","durationMs":50317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-a3157898561d06d43bc0","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"Data Assets Widget","durationMs":27554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-c0a4574b273caeb431b5","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"My Tasks Widget","durationMs":49462,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2ad9a40f0bef94e8eb21-e084e4a872d20a615bbf","project":"chromium","file":"Flow/CustomizeWidgets.spec.ts","title":"My Data Widget","durationMs":40753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2c508ade7638f8bcccac-e7c9382107a42d661bbc","project":"chromium","file":"Flow/MetricSearch.spec.ts","title":"searching for a metric with a long multi-word name should not cause clause explosion","durationMs":5453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-2c9621778a08fadbc834","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit Revert Changes restores all rows to NO_CHANGE","durationMs":23115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-4156e62dca8bfb5afec0","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit shows NO_CHANGE badge and OperationSummary on unmodified rows","durationMs":22800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-88e75e085e61e8618e6a","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit shows UPDATE badge and increments summary after editing a cell","durationMs":20237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-9b4ef19a6cb0199bf241","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Glossary bulk edit search filters rows and clear restores them","durationMs":19394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-b0ff6e9dd7c295b37f2c","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Database service bulk edit search filters rows and clear restores them","durationMs":10099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2d5458d5effed0092e57-b68f427de8c7c4e4c036","project":"chromium","file":"Features/BulkEditOperationBadges.spec.ts","title":"Database service bulk edit shows NO_CHANGE badge and OperationSummary for all rows","durationMs":18529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2e6c9afba330c97d50b5-1e20636ea4cdf2691c93","project":"chromium","file":"Features/Permissions/DataProductPermissions.spec.ts","title":"Data Product deny operations","durationMs":15683,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2e6c9afba330c97d50b5-286bfa812828f22999ee","project":"chromium","file":"Features/Permissions/DataProductPermissions.spec.ts","title":"Data Product expert can edit data product details","durationMs":15388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2e6c9afba330c97d50b5-f81d384daa402484ac75","project":"chromium","file":"Features/Permissions/DataProductPermissions.spec.ts","title":"Data Product allow operations","durationMs":15844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"2f3ad51ddbdcab4a2a2b-0084dea86addabfd83fa","project":"chromium","file":"Features/StoredProcedureServiceBulkFetch.spec.ts","title":"Stored procedure carries service via the bulk field path even when service is not requested","durationMs":225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30237b3a00cd0fa9b72a-acd0640f861e051504ef","project":"chromium","file":"Features/ColumnBulkOperationsTagsGlossary.spec.ts","title":"should select a glossary term from the tree dropdown inside the drawer","durationMs":24718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30237b3a00cd0fa9b72a-acde5114dfcdd1395bed","project":"chromium","file":"Features/ColumnBulkOperationsTagsGlossary.spec.ts","title":"should select a classification tag from the dropdown inside the drawer","durationMs":26755,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30263b4dc5f93c4f7d25-1d50e07d9894b470896a","project":"chromium","file":"Features/SampleDataDomainDataProduct.spec.ts","title":"Verify TestDataProduct shows correct details and domain association","durationMs":6311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30263b4dc5f93c4f7d25-5c8b64d664628e73b5fb","project":"chromium","file":"Features/SampleDataDomainDataProduct.spec.ts","title":"Verify TestDataProduct exists under TestDomain","durationMs":6832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30263b4dc5f93c4f7d25-d7f88ea8c2c406af471f","project":"chromium","file":"Features/SampleDataDomainDataProduct.spec.ts","title":"Verify TestDomain exists from sample data ingestion","durationMs":8012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"30fe03f56c8634b423b8-01bd25935cd715188169","project":"chromium","file":"Features/ServiceAgentsPauseResume.spec.ts","title":"should offer pause for an enabled agent and resume in disabled state","durationMs":4634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"310213acbd422d208ae5-167f8d8a1b921415200c","project":"SystemCertificationTags","file":"Features/SystemCertificationTags.spec.ts","title":"should NOT show disabled system certification tag in dropdown","durationMs":7009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"310213acbd422d208ae5-41471524fd79dda135f9","project":"SystemCertificationTags","file":"Features/SystemCertificationTags.spec.ts","title":"should show certifications after re-enabling classification","durationMs":10201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"310213acbd422d208ae5-4a0f943642b77501695f","project":"SystemCertificationTags","file":"Features/SystemCertificationTags.spec.ts","title":"should NOT show any system certification tags when classification is disabled","durationMs":6221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-22b545a43b2d863af043","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"shows how tier and usage signals moved an exact table match","durationMs":5795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-2e816677f2966a225842","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"returns ranking stage matched queries without explain","durationMs":2674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-4f1c38196e1dd547eb09","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"shows configurable ranking stages in table search settings","durationMs":5071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-5a015d2e8f981f75b56f","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks customer and customers identity matches before high-signal description matches","durationMs":3159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-998bd319d41b5fa9c78a","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks customer profile name and column matches before high-signal description matches","durationMs":2676,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-a8021c129685daf99088","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"finds customer profiles fixtures across searchable asset indexes","durationMs":3291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-b3d869d6c65350419260","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"finds provider address texas fixtures across searchable asset indexes","durationMs":3464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-c4074fe750ef0ac6936d","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks clear provider address intent above weak high-signal description matches with stopwords","durationMs":3016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-e859181cb88056deb9a4","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"toggles ranking details in search settings preview","durationMs":5263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-f250e708b05339783d84","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"shows readable ranking details for exact table matches","durationMs":6792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3117e9587f58f0653c4e-f74d3a290f5428946864","project":"search-nightly","file":"Search/SearchRelevance.spec.ts","title":"ranks name and structural table matches before tier and usage description matches","durationMs":3326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3181935147491aeb55f0-6a8fd0caa84eae7db16f","project":"Ingestion","file":"Features/FailedTestCaseSampleData.spec.ts","title":"FailedTestCaseSampleData","durationMs":6626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3181935147491aeb55f0-96858048143c07e8fbee","project":"Ingestion","file":"Features/FailedTestCaseSampleData.spec.ts","title":"gates the sample fetch on failed status","durationMs":4979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"31a87c9b2485f1aec7b5-6e697bb7c08c009f3229","project":"Reindex","file":"Features/SearchSeparation/GlossaryRenamePrefixCascade.spec.ts","title":"glossary-term prefix rename keeps linked asset glossary tag consistent","durationMs":1517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-3cef86380e36f0a03159","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Dimension card click should redirect to test cases with applied filters","durationMs":76055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-3e3ac21dbb78b79b542a","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Tier filter sends tier.tagFQN field in ES query (not tags.tagFQN)","durationMs":7423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-448cbb52313be9ec70b3","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Dashboard batches all report aggregations into one request (no N+1)","durationMs":6483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-4497b8a31a310cc90f24","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Tag filter sends tags.tagFQN field in ES query","durationMs":8122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-52bdc43c7c7c66f92d3e","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Entity Health pie chart segment click redirects to Test Cases with correct status","durationMs":9520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-67e3603da89d1d13dddf","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"DataQualityDashboardTab","durationMs":29168,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-7b1536150d3100c7a16b","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Test Cases list filter — Data Product","durationMs":9833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-8b76300bfab3a0c4b5ab","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Data Assets Coverage pie chart segment click redirects to Test Suites and Explore","durationMs":13561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-9b9e4b3fa500f737bb52","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Tier and Tag filters produce independent ES filter clauses","durationMs":10123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-d086e0bed7cc7831c38b","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Test Case Result pie chart segment click redirects to Test Cases with correct status","durationMs":17744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"320716241c332b3d939a-d7eb33e1ed4ca47318bd","project":"chromium","file":"Features/DataQuality/DataQualityDashboard.spec.ts","title":"Reopen resolved incident in place from the Test Case page","durationMs":10649,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-15ab7c92e6cc4e9e698e","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"Persona AI Context — Rule CRUD: empty state → create → edit → delete","durationMs":12449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-1600d0c7e7e9f50cddc7","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"knowledge entity type forces Fully rendered on and disables it","durationMs":9615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-9c3f02d123ada83d2aeb","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"changing entity type clears an incomplete filter and unblocks save","durationMs":10912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-e0fd56c870d3159d545e","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"incomplete condition (no field selected) blocks save with an error message","durationMs":10876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-e183791f48da280d4ed6","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"max assets input clamps values above 1000 to 1000 on blur","durationMs":10663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-ee9d29fa394f102ef3d7","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"fully-completed Description Contains condition allows save — regression #31564","durationMs":11812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-f48f2b0c4ab37b0281ce","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"duplicate rule name is rejected with a validation error","durationMs":11508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"325992278c5916a61142-fc51d001d91cc85c0f14","project":"chromium","file":"Features/PersonaAIContextRules.spec.ts","title":"Always in context and Fully rendered toggles are visible and interactable","durationMs":10011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-11614026b8dde22a8254","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Search Data Products","durationMs":6185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-1458cccf2156100ad999","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Create data product with tags using TagSuggestion","durationMs":10106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-6fa7bf28459032ee3dc8","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Pagination","durationMs":8942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-b46995b607c673d5399f","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Empty State - No Data Products","durationMs":6088,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-b61a7bbd7a47b1fd89c2","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Data Product — Data Observability tab","durationMs":9102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-bed8c16cc4258729a678","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Create Data Product and Manage Assets","durationMs":17059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-ca3fcd97cc2fd4b90fce","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Data Product List Page - Initial Load","durationMs":6372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-d475230b6e62375a3ff9","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"Data Product - Follow/Unfollow","durationMs":7854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"333d3a17ff58588f3f24-e497da6ffe895e87458b","project":"chromium","file":"Pages/DataProducts.spec.ts","title":"View Toggle - Table and Card Views","durationMs":6269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"386c5e2a979bf842b774-be875acf813e1ecae98e","project":"chromium","file":"Features/SearchIndexNestedColumns.spec.ts","title":"oversized deeply nested column indexes and an in-limit column name is searchable","durationMs":5463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-1e3f50160ad418e033c4","project":"chromium","file":"Pages/Users.spec.ts","title":"Token generation & revocation for Data Steward","durationMs":10090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-25c1589afdcf05b3f9cc","project":"chromium","file":"Pages/Users.spec.ts","title":"Should switch personas correctly","durationMs":5853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-28a4af5feb386d2eb3bf","project":"chromium","file":"Pages/Users.spec.ts","title":"Update own admin details","durationMs":10484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-40bc5d16474bd567fec7","project":"chromium","file":"Pages/Users.spec.ts","title":"Should add, remove, and navigate to persona pages for Default Persona section","durationMs":20943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-4e844addc2d7deb18855","project":"chromium","file":"Pages/Users.spec.ts","title":"Should display persona dropdown with pagination","durationMs":4760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-55e153f9ef4db1972ec7","project":"chromium","file":"Pages/Users.spec.ts","title":"Permissions for table details page for Data Consumer","durationMs":13599,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-8831dc2085f1fc122b29","project":"chromium","file":"Pages/Users.spec.ts","title":"Should add, remove, and navigate to persona pages for Personas section","durationMs":18631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-90526ec56b570b377292","project":"chromium","file":"Pages/Users.spec.ts","title":"Create and Delete user","durationMs":19237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-9290e51e5e0501556ac1","project":"chromium","file":"Pages/Users.spec.ts","title":"Close the profile dropdown after redirecting to user profile page","durationMs":11344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-92ef91e72262b1cb927e","project":"chromium","file":"Pages/Users.spec.ts","title":"Should navigate to user profile from feed card avatar click","durationMs":11602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-998cbbc9b801f03b3159","project":"chromium","file":"Pages/Users.spec.ts","title":"Reset Password for Data Steward","durationMs":13796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-a075ce3908b993c98ad0","project":"chromium","file":"Pages/Users.spec.ts","title":"Should handle default persona change and removal correctly","durationMs":14049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-a67e6de8eaa1bac9ba4c","project":"chromium","file":"Pages/Users.spec.ts","title":"Check permissions for Data Steward","durationMs":16994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-b006556d31479323998d","project":"chromium","file":"Pages/Users.spec.ts","title":"Should display default persona tag correctly","durationMs":4233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-ba6d0e4506a5b495f489","project":"chromium","file":"Pages/Users.spec.ts","title":"User Performance across different entities pages","durationMs":99779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-bb7e1f324e137b23fc91","project":"chromium","file":"Pages/Users.spec.ts","title":"Should handle persona sorting correctly","durationMs":4704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-c477ab434b58b5c1462a","project":"chromium","file":"Pages/Users.spec.ts","title":"User should have only view permission for glossary and tags for Data Consumer","durationMs":11807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-cb98769927a83a764470","project":"chromium","file":"Pages/Users.spec.ts","title":"Admin soft & hard delete and restore user","durationMs":17176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-d3b9e560fd6791c5dbf1","project":"chromium","file":"Pages/Users.spec.ts","title":"Update user details for Data Consumer","durationMs":12154,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-d753e04c92cfcfde4334","project":"chromium","file":"Pages/Users.spec.ts","title":"Admin is searchable by email","durationMs":12304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-dcb103b18bbe8e8861ab","project":"chromium","file":"Pages/Users.spec.ts","title":"Token generation & revocation for Data Consumer","durationMs":11494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-e004aa852f1f5c14efb7","project":"chromium","file":"Pages/Users.spec.ts","title":"Reset Password for Data Consumer","durationMs":20503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-e28e9e6eefdde1da98c0","project":"chromium","file":"Pages/Users.spec.ts","title":"Update user details for Data Steward","durationMs":8806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-e61829517b764558d9be","project":"chromium","file":"Pages/Users.spec.ts","title":"Update token expiration for Data Steward","durationMs":14784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-edc0496c9c81d3ed5e9b","project":"chromium","file":"Pages/Users.spec.ts","title":"Should revert to default persona after page refresh when non-default is selected","durationMs":8061,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-f34104f9785f64f73e81","project":"chromium","file":"Pages/Users.spec.ts","title":"Operations for settings page for Data Steward","durationMs":14485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-f3a2c3c86e3d09c3dd16","project":"chromium","file":"Pages/Users.spec.ts","title":"Operations for settings page for Data Consumer","durationMs":18394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-f64b8f345910b62363a5","project":"chromium","file":"Pages/Users.spec.ts","title":"Update token expiration for Data Consumer","durationMs":18876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"391bbea418bb3322b4c3-faece1be3db817778a7a","project":"chromium","file":"Pages/Users.spec.ts","title":"Admin soft & hard delete and restore user from profile page","durationMs":16537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-4739ff2084f3c8e98727","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should not allow dragging term to itself","durationMs":11041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-6737551753852bc1cbf3","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should delete term and remove tag from assets","durationMs":29177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-771c51350f220ab003ef","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should delete glossary and remove tags from assets","durationMs":28119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-e9b4d20d3effa0991571","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should update child FQN when parent is renamed","durationMs":18372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39a15eaa26884810efef-f046ff3d00fbffbac1c2","project":"chromium","file":"Features/Glossary/GlossaryMiscOperations.spec.ts","title":"should delete parent term and remove both parent and child tags from assets","durationMs":40829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39f85eca53b00497835e-5795cfec5f514c0dff0a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":26805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"39f85eca53b00497835e-b9d0e082fb7768ae4703","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":26757,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-05d0755a10ff7ca86a72","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Search suggestions should be filtered by selected domain","durationMs":18141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-106885a3b01e4c2164f2","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain assets tab should NOT show assets from other domains","durationMs":15389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-107b97cfdd17a1b2e998","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain Data Products tab should NOT show data products from other domains","durationMs":13104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-2df699eabe74a18aae7b","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain filter should use exact match and prefix with dot to prevent false positives","durationMs":23795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-457e576ead0d5e94d5f8","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Subdomain assets should be visible when parent domain is selected","durationMs":21609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-4cecbd70fae32cde1afd","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Quick filters should persist when domain filter is applied and cleared","durationMs":58016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-4f11dba00d75a16f9ce4","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain page assets tab should show only domain assets","durationMs":14099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-57e135a57c2400ac872d","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain filter should persist across page navigation","durationMs":25228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-85fa806fabef9e541f8b","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Assets from selected domain should be visible in explore page","durationMs":19716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-a56e2714819093d7a60f","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Domain filter should work with different asset types","durationMs":26086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-b501db7d91aa446ad715","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"Multi-nested domain hierarchy: filters should scope correctly at every level","durationMs":45488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3bb3cddb781451bf98b7-cfe1941aeddc2a8aedf3","project":"chromium","file":"Features/DomainFilterQueryFilter.spec.ts","title":"3-level domain hierarchy: SubSubDomain assets visible when SubDomain selected","durationMs":26191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3d714cb874dd7d8d1332-864a1c3f662a3a46b0a2","project":"Ingestion","file":"Pages/HealthCheck.spec.ts","title":"All 5 checks should be successful","durationMs":2519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-1d51ace7c2b9cb0cfb30","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Related Metrics Update","durationMs":19585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-4debf93e2d3cfddfb567","project":"Basic","file":"Flow/Metric.spec.ts","title":"verify metric expression update","durationMs":16817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-50df1fa23ff9349409a6","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Metric Type Update","durationMs":15283,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-7fda60583e5879af3268","project":"Basic","file":"Flow/Metric.spec.ts","title":"Dimensions and measures render and description is editable","durationMs":16676,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-9acc6f2fc61d63d42017","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Granularity Update","durationMs":16162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-ceb78708ef9d141055da","project":"Basic","file":"Flow/Metric.spec.ts","title":"Metric creation flow should work","durationMs":20081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3ed6e761ea817113c444-d1d3605e00316bbde469","project":"Basic","file":"Flow/Metric.spec.ts","title":"Verify Unit of Measurement Update","durationMs":14708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-0bd2eb1e92ac9425b8dd","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Configure column search field settings","durationMs":11601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-19fb7ea74d0da3fa8c0a","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Preview config reflects reverted n-gram weight after save","durationMs":9235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-1f6c82edb0d025fa4d35","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Restore default search settings","durationMs":7459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-2e3d05e6e1e746b6c156","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Latest preview config wins when a superseded request resolves late","durationMs":10202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-3ed9d0f3e867e19c934c","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Preview config updates when restore defaults returns empty search fields","durationMs":9870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-3f1486bc755826887709","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Update entity search settings","durationMs":11799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-56543540342adb9b3b9e","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Search preview for searchable table","durationMs":8232,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-c8de79795df8ae9d2141","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Update global search settings","durationMs":10394,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-cf112303dbb369632c4e","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Reset global search settings to default via confirmation modal","durationMs":7647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"3f800034a832b756357b-dc51be90f6049672dc25","project":"GlobalSettings","file":"Pages/SearchSettings.spec.ts","title":"Search preview displays column results correctly","durationMs":9906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"40e9622bfe15bcff9ad8-e351a58660693f8ee3e3","project":"chromium","file":"VersionPages/ClassificationVersionPage.spec.ts","title":"Classification version page","durationMs":9945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4101399d238fe61337fd-26aaa7b16fc4e9c43441","project":"chromium","file":"Features/Announcements/AnnouncementEntity.spec.ts","title":"creates an announcement on a domain","durationMs":19934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4101399d238fe61337fd-3ca48bb1ea1b722e1c1b","project":"chromium","file":"Features/Announcements/AnnouncementEntity.spec.ts","title":"edits an existing announcement on a domain","durationMs":11778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4101399d238fe61337fd-e35c5e2370a108a1519a","project":"chromium","file":"Features/Announcements/AnnouncementEntity.spec.ts","title":"deletes an existing announcement on a domain","durationMs":14228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-293d2abba1bbe1172a4d","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Data Model with display name filter","durationMs":24916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-2a3509194f4730d8cba7","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Dashboards with display name filter","durationMs":22486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-2b2c7b49221082fedabe","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Data Products with display name filter","durationMs":26412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-341c54345e6b70793b52","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Stored Procedures with display name filter","durationMs":20781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-35ecd7a4557f829ec686","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Containers with display name filter","durationMs":25406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-369032808baca9262db1","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Search Indexes with display name filter","durationMs":23790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-399c803a6b55bfebb25d","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Placeholder validation - widget not visible without configuration","durationMs":13524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-433345184533998b95ef","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Database Schemas with display name filter","durationMs":27108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-443dbf0db976c77a9310","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Charts with display name filter","durationMs":24789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-445bc96e17011a12c613","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Pipelines with display name filter","durationMs":25988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-49430d25ae8bdad31291","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Topics with display name filter","durationMs":25362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-4a8e2d73b07a9622bd37","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Tables with display name filter","durationMs":21159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-522b865a043f08183f74","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test API Endpoints with display name filter","durationMs":25564,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-56d6106d21f5cbe8f52e","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Complex nested groups","durationMs":28980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-5dd48016c14d23fccc18","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Multiple entity types with OR conditions","durationMs":26575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-70222d8e09ba6b43fbde","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Metrics with display name filter","durationMs":25180,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-8f9c1279b9e0ba86b5ad","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Knowledge Pages with display name filter","durationMs":5345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-9bcab5a6deac24218c64","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test API Collections with display name filter","durationMs":24066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-a06a0a8ac5a0165a48c8","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Multiple entity types with AND conditions","durationMs":26815,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-b1e897419449d04dadc7","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Databases with display name filter","durationMs":23848,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-b61c4dd6c6c72671c332","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test ML Model with display name filter","durationMs":24912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-b6bdaacf16de33bb5986","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Test Glossary Terms with display name filter","durationMs":25150,"attempts":1,"retries":0,"outcome":"expected"},{"id":"41c98876e1766b5cfd3d-ed2ab173d7a73750195c","project":"chromium","file":"Features/CuratedAssets.spec.ts","title":"Entity type \"ALL\" with basic filter","durationMs":15897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-0a6a0c0a89079822be9b","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: chart","durationMs":6145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-1826851f56f2f64a88af","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: table","durationMs":12338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-197e96b23c8dfd4534d8","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: dashboard","durationMs":10970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-1a3701d0ef11c45d2d86","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for pipelineService in platform lineage","durationMs":8720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-1f9fed7ccd1a32e46faa","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for mlmodelService in platform lineage","durationMs":8741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-2d3e40c9d820f5709c19","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: apiEndpoint","durationMs":6397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-2dfc818f81d83de6fdaa","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for messagingService in platform lineage","durationMs":8115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-34bdec5cd3987c0b1474","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for storageService in platform lineage","durationMs":8874,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-5812ef9c06312f638121","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: searchIndex","durationMs":8137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-68545723ed07a1581857","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: topic","durationMs":10809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-76cc687e194d0300f524","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: container","durationMs":8188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-770dfa5de4648db0785f","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: mlmodel","durationMs":8601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-77f956cbb3cdbb432c07","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: metric","durationMs":6242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-da57ff8ea302cc48d77a","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for dashboardService in platform lineage","durationMs":8319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-ea0b3841423e11276a4c","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for databaseService in platform lineage","durationMs":8656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-ecfd33b33b08fec09293","project":"Basic","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab IS visible for supported type: pipeline","durationMs":11818,"attempts":1,"retries":0,"outcome":"expected"},{"id":"426c3d5e1c2f1aa09ac8-f8d8b2894982189c8fdb","project":"chromium","file":"Pages/Lineage/LineageRightPanel.spec.ts","title":"Verify custom properties tab is NOT visible for apiService in platform lineage","durationMs":8245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-039b9d9949c4ae9f9ca1","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Add Table Test Case","durationMs":10692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-727c14a4b085f6d7d08e","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Non-owner user should not able to add test case","durationMs":10742,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-970712d494efa076b03d","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Add multiple test case from table details page and validate pipeline","durationMs":12444,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43a4e7a0652e3c4a937d-9b9fb01ad7fade5e355b","project":"Ingestion","file":"Features/DataQuality/AddTestCaseNewFlow.spec.ts","title":"Add Column Test Case","durationMs":12583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-1d6fa09a9a2596f90ef9","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify No owner and description redirection to explore page","durationMs":6058,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-254524b7d3aaa13e3040","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify metrics in chart API response","durationMs":3189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-3761ae2928ffed19f52d","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Update KPI","durationMs":4093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-56301182f27c3a7cc07c","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verifying Data assets tab","durationMs":4802,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-5d09da8479693162a3cf","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify KPI widget in Landing page","durationMs":4669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-5f88ed46d6737a9bc324","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Create description and owner KPI","durationMs":6741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-82610a9ae35a0e1b158d","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verifying App analytics tab","durationMs":4420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-869f610ab3df9908aa44","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verify metrics appear in description chart","durationMs":3256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-944e8c55fd3b896053aa","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Verifying KPI tab","durationMs":4442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"43d97496a69d8a7a7493-9b38808389a222082626","project":"Data Insight","file":"Pages/DataInsight.spec.ts","title":"Delete Kpi","durationMs":4450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-9f5733c4dfa61fe13e8f","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"switches between Graph and Tree view surfaces","durationMs":2047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-ac147fa6311f758e140a","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"searches the Model graph and clears the query","durationMs":2034,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-bfa7a1e932c6531f0d8f","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"opens with the View, Graph, and Model surfaces selected","durationMs":2402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-d3781b6e6f0194b71607","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"scopes the Studio graph and stats to a glossary","durationMs":2240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-dc8b76bc66b6e8259ad7","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"covers Edit Graph authoring and the Model workbench","durationMs":2672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-e2a05d4ab84737443ccb","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"switches between Model and Data layers","durationMs":2631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"455af77f3678efcfb575-f9d00c1ff5fd124e8d68","project":"chromium","file":"Features/OntologyStudio.spec.ts","title":"renders every relation type between the same concepts","durationMs":2296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45a520c451ca353b2bea-4f5b3eea701877cc38c8","project":"chromium","file":"Features/DataQuality/IncidentManagerAfterSoftDelete.spec.ts","title":"Incident Manager renders without Jackson error after a test case is soft-deleted","durationMs":10406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45c88a6f0c34dbb0e7c7-1d2e961d2b1aba19000b","project":"chromium","file":"Features/DataQuality/BundleSuiteBulkOperations.spec.ts","title":"Create new Bundle Suite with bulk selected test cases","durationMs":11231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45c88a6f0c34dbb0e7c7-9f20c56231a934527813","project":"chromium","file":"Features/DataQuality/BundleSuiteBulkOperations.spec.ts","title":"Add test case to existing Bundle Suite","durationMs":10520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45c88a6f0c34dbb0e7c7-afb2d8d44d708f76b025","project":"chromium","file":"Features/DataQuality/BundleSuiteBulkOperations.spec.ts","title":"Bulk selection operations","durationMs":9009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"45e1ab4b06aa23f33aff-f2407ea680c31e534c87","project":"chromium","file":"Pages/PipelineExecution.spec.ts","title":"Execution tab should display start time, end time, and duration columns","durationMs":6536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-68ed63a7d77a329ff399","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should show enabled certification tag in dropdown","durationMs":11738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-a0fa29193e91484a6ef1","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should show certification after re-enabling disabled tag","durationMs":17328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-b024f565212d80a3e351","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should NOT show disabled certification tag in dropdown","durationMs":12461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"46c5b33a1d364708c732-de28387173f13d94b5ab","project":"chromium","file":"Features/CertificationDropdown.spec.ts","title":"should handle multiple disabled tags correctly","durationMs":12290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-0570db7f4661ea4e68b4","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display domain and owner of deleted asset in suggestions when showDeleted is off","durationMs":8561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-325ce92dfd704c84764a","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display deleted assets when showDeleted is checked but deleted is false in queryFilter","durationMs":8353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-36286bd8f41799e49212","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display domain and owner of deleted asset in suggestions when showDeleted is on","durationMs":11208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-6605f6bf34495eb64f57","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display soft deleted assets in search suggestions","durationMs":17892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-66fc48bbab5da83e551a","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display deleted assets when showDeleted is not checked but deleted is false in queryFilter","durationMs":8487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-960a4db0dbad3161c418","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should not display deleted assets when showDeleted is not checked and deleted is not present in queryFilter","durationMs":8158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-a17f0c9007400530095f","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display deleted assets when showDeleted is not checked but deleted is true in queryFilter","durationMs":8893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-d9a2f9139db34ab1f5c7","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display deleted assets when showDeleted is checked and deleted is not present in queryFilter","durationMs":9374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"47563b3c243233393067-f24680ac9fa5499518e4","project":"chromium","file":"Flow/ExploreDiscovery.spec.ts","title":"Should display deleted assets when showDeleted is checked and deleted is true in queryFilter","durationMs":9113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-0ae3eee235ec5b54090e","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should display correct tabs for table entity in team assets context","durationMs":7656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-1887262312ad0f4235d2","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should display overview tab content in team assets context","durationMs":7776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-3e9e117558b4023ad650","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should display entity name link in panel header in team assets context","durationMs":7886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-4839ec1ef558a4b2c1e1","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit domain from team assets context","durationMs":7814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-5994beef742f7e20b2e6","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should open right panel when clicking asset in team assets tab","durationMs":8274,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-9f9ccb162be898d5c7ce","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit description from team assets context","durationMs":7891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-b2b79442ca34f8eb583c","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit owners from team assets context","durationMs":10001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-e637e0262a842d70ad43","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit tags from team assets context","durationMs":9437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-eaaf971263597a587c9c","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should edit glossary terms from team assets context","durationMs":8192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"485ad34d6101bfb8625c-fe9c6f16ecf7bfb38e71","project":"chromium","file":"Pages/TeamAssetsRightPanel.spec.ts","title":"Should assign tier from team assets context","durationMs":8846,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4962513e4ede9efbc6bc-fe90046fdeee5e13ecdf","project":"Ingestion","file":"Features/TestSuitePipelineRedeploy.spec.ts","title":"Re-deploy all test-suite ingestion pipelines","durationMs":3393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-06daeb511ef00f84fd29","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service deny common operations permissions","durationMs":10716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-0c4645d7bb089c1e321f","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service allow entity-specific permission operations","durationMs":11813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-14321144181f9ce47f79","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Api Service allow common operations permissions","durationMs":10987,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-17cd90767af0966bd36c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Pipeline Service deny common operations permissions","durationMs":10448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-18ede5fe24ff674006aa","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":9597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-2e5ac8793860549aeacb","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":7872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-343573554ec0d8268d70","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":11203,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-3484dd5baeedfabcdc0d","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":11276,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-35a725698998eb2a47f8","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-38f5f03eb5cf5ae7f033","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":7338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-395e69814743ba2cb187","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":8944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-3a1ec3677e129e362fbc","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":4864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-3ae259c0d22b1e1ce4d8","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Messaging Service allow common operations permissions","durationMs":8401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-432352edf3dca06c2ef7","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":7710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-436873586de451fe96d5","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service allow common operations permissions","durationMs":14605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-4c6ea164e911bb693213","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":8740,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-5f11cfb879248cf34e4c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":5429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-622ca29cccba013730a4","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-7b3743d684cf6e117d91","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":8214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-835d301c730efbe11b34","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":7893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-8ddcec058984ec203d3f","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":7961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-8f1bafe670518bc9e83c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":7391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-91a5d646919b4d9597e3","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":9668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-93d0ad051bf724091eae","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":4873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-a475e3ade77b9e387765","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-ae6752ff147b57846fac","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service allow entity-specific permission operations","durationMs":14301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-afc719e0143260d4e040","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Storage Service allow common operations permissions","durationMs":10063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-b77edf9e143ef601fbf9","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with denied trigger permission","durationMs":8788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-bcc6de800ae0018c8e35","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":9941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-c3aca2c5c8c2d82180af","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":7675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-c552350b1e2fa95be986","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service allow common operations permissions","durationMs":10218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-c7c8619b266099fc4f70","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is hidden with view-only permission","durationMs":9123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-cdae34958cb93081829a","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"SearchIndex Service allow common operations permissions","durationMs":12341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-d59b19f223a8f2cc1bbb","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"AutoPilot trigger button is visible with Trigger permission","durationMs":7981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-dd662649178d493876e0","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Storage Service deny common operations permissions","durationMs":9870,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-ef980385b808a5c01753","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Api Service deny common operations permissions","durationMs":11864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-f03031217bd696b25733","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Mlmodel Service allow common operations permissions","durationMs":13297,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-f14d138df6e533dcf29d","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Mlmodel Service deny common operations permissions","durationMs":13689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-f4ee16bcc2057c7cbe8f","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"SearchIndex Service deny common operations permissions","durationMs":9936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fb8dab4d2fd36f28599c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service deny common operations permissions","durationMs":14707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fc44283d14ba6c42806c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Database Service deny entity-specific permission operations","durationMs":10244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fc52cf1b230c7de377b5","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Pipeline Service allow common operations permissions","durationMs":11841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-fee0d4a9f268927eb49b","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Dashboard Service deny entity-specific permission operations","durationMs":13542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b386b55f31c66fcf0a6-ff25baa5e6705fd87e3c","project":"chromium","file":"Features/Permissions/ServiceEntityPermissions.spec.ts","title":"Messaging Service deny common operations permissions","durationMs":6784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-1bb1a00f45a51a478c52","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should navigate to new page when \"Leave\" is clicked","durationMs":22037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-61dac66ba80ac816590f","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should show navigation blocker modal when trying to navigate away with unsaved changes","durationMs":18431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-91f203d529a815190d96","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should not show navigation blocker after saving changes","durationMs":21220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-9d1b73de8b80246d8cf7","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should confirm navigation when \"Save changes\" is clicked","durationMs":21056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b548bcc60ee243a112c-e22c3867f6fc02b097af","project":"Basic","file":"Features/NavigationBlocker.spec.ts","title":"should stay on current page and keep changes when X button is clicked","durationMs":21653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-02496396ede353f7fb35","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"Add tests CTA navigates to the Profiler tab","durationMs":8017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-0fb42a3e78e29d28e22d","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"replaces the setup CTAs with status badges once tests are configured","durationMs":9888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-983cb693886d03b0dbc8","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"Enable observability CTA navigates to the Profiler tab","durationMs":9926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-990261b030bde9be3d4c","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"renders the widget with all four category rows","durationMs":9680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-d9f11a53361475875ec7","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"shows setup CTAs for unconfigured categories","durationMs":8619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4b6e4ca7fb13c0fd30cc-da9aa25e75339891381d","project":"chromium","file":"Pages/AssetHealthWidget.spec.ts","title":"Create contract CTA navigates to the Contract tab","durationMs":10474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-0810169ebfef6450dab7","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"STATIC config sends all three static-only fields when set","durationMs":5350,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-3dd9676e86c529445185","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"STATIC config sends profileSample and no DYNAMIC-only keys","durationMs":4999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-5b5f30c9f86f701498c6","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"switching STATIC → DYNAMIC does not leak static-only fields","durationMs":5835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-c227bb3d66ab294ce3b3","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"DYNAMIC threshold remove drops only the selected row","durationMs":5521,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-ce6cb46c9ee7e6dd2479","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"DYNAMIC with smart sampling ON sends only DYNAMIC keys","durationMs":5514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-cf4cca44f019913b314a","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"switching DYNAMIC → STATIC does not leak smartSampling or thresholds","durationMs":5376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c104d4f128d8996df97-f02c36f33396d9719410","project":"Ingestion","file":"Features/DataQuality/ProfilerIngestionForm.spec.ts","title":"DYNAMIC with smart sampling OFF and thresholds sends thresholds array","durationMs":5459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-0acd98f891080c27eb0d","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Custom SQL Query","durationMs":23001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-19b221f23b1996aea714","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column Count To Be Between","durationMs":14840,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-45298dd3dedeb1025238","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Row Count To Equal","durationMs":16710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-6dffe1d54d6631269ef3","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Row Inserted Count To Be Between","durationMs":20513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-9ab6d3fa51599960986f","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column To Match Set","durationMs":16417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-a38fbe8dce53bede33cf","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column Count To Equal","durationMs":16510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-a586dabea686a2746e3a","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Row Count To Be Between","durationMs":18186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-b6168c587d55ad692c3f","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Difference","durationMs":25342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4c305ec854f9593f5dca-efb7d23b30cf3ec7410c","project":"chromium","file":"Features/DataQuality/TableLevelTests.spec.ts","title":"Table Column Name To Exist","durationMs":16490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-1f7188b7b883e25772b4","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Data Product","durationMs":7384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-27cf91afa49b80c2fff9","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Tag","durationMs":7380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-29cc7b194e31b3fdc811","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Dashboard","durationMs":5651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-2b584b4d9a77cdb55d27","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Data Model","durationMs":5854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-382d14fc9018ce22dc30","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Database Schema","durationMs":7402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-4cc3834b03e310e5e602","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Metric","durationMs":6653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-4dae8060a54ac47cc0a8","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - API Collection","durationMs":5074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-54a64bccafdf003b3b5c","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - All","durationMs":5891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-54ad89a5b97bf479cc59","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - ML Model","durationMs":6612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-6316c64b4f391ed5dd7c","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Database","durationMs":6605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-6559c024bdc4ef8d6595","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Search Index","durationMs":7402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-69a557a324f049438f36","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Directory","durationMs":5933,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-89015f87c94adc34de54","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Table","durationMs":7583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-92dfb0fb33159b9982bf","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Container","durationMs":7122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-960f1bace1eb38b1a42a","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Worksheet","durationMs":8459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-9c37b3959482f071ddae","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - API Endpoint","durationMs":6213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-a8750715d64a09e3c8fc","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Spreadsheet","durationMs":6105,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-cae189412fe5f16c69a7","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - File","durationMs":8243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-cd0c011f0719a41d2d68","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Pipeline","durationMs":6051,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-cf14b19b99f210391fc6","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Stored Procedure","durationMs":6332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-db96c73de1e2ebd5a423","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Topic","durationMs":6264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e43d09217c30828fd6f-dcfea58dc473f62141b7","project":"Basic","file":"Flow/Navbar.spec.ts","title":"Search Term - Glossary","durationMs":7621,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e89530d9c0b985f2d2e-8764696c70efbfce6d8f","project":"Basic","file":"Pages/Roles.spec.ts","title":"Roles page should work properly","durationMs":19700,"attempts":1,"retries":0,"outcome":"expected"},{"id":"4e89530d9c0b985f2d2e-fbf09b1def578f24be64","project":"Basic","file":"Pages/Roles.spec.ts","title":"Delete role action from manage button options","durationMs":8886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-3e47bd48fd77712e1f85","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify columns and edges when a column is hovered","durationMs":9683,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-ad6d8832112259fd0251","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify edges for column level lineage between 2 nodes when filter is toggled","durationMs":8934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-b732968444170866a917","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify column visibility across pagination pages","durationMs":12264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-dfc52176b46c289f580c","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify edges when no column is hovered or selected","durationMs":11031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"52cbec20b84b33e4e196-fa1589a1509ed48faec5","project":"Basic","file":"Pages/Lineage/LineageNodePagination.spec.ts","title":"Verify columns and edges when a column is clicked","durationMs":11246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-2fe9c1b4e193b0e8a3c1","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Pipeline via UI","durationMs":10915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-437893114501837400b1","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Dashboard via UI","durationMs":16673,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-69a7106de7c0a6a9eced","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Verify task lifecycle in activity feed","durationMs":13781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-6c54054c4b110926b888","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create tag task for table column via UI","durationMs":10301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-79d67e1c613b05839814","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Table via UI","durationMs":18387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-8605df75810c859fa5df","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create description task for table column via UI","durationMs":10513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-9c3e14eda96c37015d6c","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Pipeline via UI","durationMs":12944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-a6b2c6fca32681720e0d","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Dashboard via UI","durationMs":85578,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"53b3e913ac628cc64131-b14bef78aecc75cf1e4b","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Topic via UI","durationMs":15529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-b3aafe3db491bbb76c3f","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and resolve description task for Table via UI","durationMs":12134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-ca8b24a71c63ee90c746","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Create and reject tag task for Topic via UI","durationMs":16135,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53b3e913ac628cc64131-dc5fdbbc55f4323bd01d","project":"chromium","file":"Pages/TasksUIFlow.spec.ts","title":"Verify task shows correct metadata","durationMs":12962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"53f5e48dc6dd5303275d-f73ee758f1c03b02e338","project":"Basic","file":"Features/MetricCustomUnitFlow.spec.ts","title":"Should create metric and test unit of measurement updates","durationMs":8515,"attempts":1,"retries":0,"outcome":"expected"},{"id":"542738137544ccb7a5b6-ec4052ad168f3715c61c","project":"Basic","file":"Pages/SubDomainPagination.spec.ts","title":"Verify subdomain count and pagination functionality","durationMs":16458,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-20526ba66c2db23ec1b7","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Edit own comment - author can edit","durationMs":208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-3adb3ddf9b6b67100b88","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Admin can delete any comment","durationMs":226,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-494755f4b3475416e2de","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Delete own comment - author can delete","durationMs":246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-5282e3382c460cc2d9f9","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Add comment to a task","durationMs":186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-577db3e820f130af6ca7","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Non-author non-admin cannot delete comment - returns 403","durationMs":7054,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-6f7978153f6acdcda0dc","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"View comments on task in activity feed","durationMs":14342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-80af15ec5a63db7ec1c7","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Add multiple comments to a task","durationMs":240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-861e0f72c5138e44c9dd","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Comment supports markdown formatting","durationMs":130,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-adf9f8b9a52a48f27809","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Comment with @mention syntax","durationMs":194,"attempts":1,"retries":0,"outcome":"expected"},{"id":"54aa5f49255417e56514-eba5683c6497d7b43096","project":"chromium","file":"Pages/TaskComments.spec.ts","title":"Non-author cannot edit comment - returns 403","durationMs":6910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-07bce10ca7c87f76ebc3","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Insights page should trigger collect API","durationMs":5403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-3868472ff94748e79924","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Incident Manager page should trigger collect API","durationMs":5202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-57526628bff2481e11dd","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Explore page should trigger collect API","durationMs":6153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-64c32274d7af4914dbb0","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Tags page should trigger collect API","durationMs":5729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-73b9c5edde2a3debaf93","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Quality page should trigger collect API","durationMs":5114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-a48dd7c323ac0a8ce57a","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Settings page should trigger collect API","durationMs":5817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5527d5d87b7ebfcf0ae8-ee0a5aeb47d5510b99b5","project":"Basic","file":"Flow/Collect.spec.ts","title":"Visit Glossary page should trigger collect API","durationMs":5589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-077585f6e4f0a08cffc6","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should create a new learning resource","durationMs":7354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-24ae7d73ea2582e79ad8","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct pageId param when filtering by context","durationMs":4385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-34c89825a071c90c66cd","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct resourceType param when filtering by type","durationMs":3693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-408a941563d59c4b52db","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should validate required fields when creating a resource","durationMs":5404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-4daf0f2ef98790dfdd5d","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should open resource player when clicking on resource card in drawer","durationMs":8366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-6440dc2b2c05f5ff8244","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should clear all filters and reload without filter params","durationMs":4366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-7057ea634ebbed2312bb","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should toggle between table and card views","durationMs":4131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-a5ef027b5906819fe95a","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct status param when filtering by status","durationMs":4265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-b9bfc3ce1ba2ab5785a5","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct category param when filtering by category","durationMs":3691,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-d8c73713be3825c12ab8","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should show correct learning resource in drawer on lineage page","durationMs":7330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-db3917dc961a6c6490d9","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should create resource via UI and verify learning icon appears on target page","durationMs":12299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-f5d75cc00a51851d5306","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should preview a learning resource by clicking on row","durationMs":4977,"attempts":1,"retries":0,"outcome":"expected"},{"id":"552de93d12db93b47527-f761108bc52917eb0642","project":"chromium","file":"Pages/LearningResources.spec.ts","title":"should send correct search param to API when searching","durationMs":3613,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5609f6479eac3cd9b7a7-683a4b4827384efb9055","project":"chromium","file":"Features/AgentLogStreamHandover.spec.ts","title":"A finished run clears the live state and refetches the log exactly once","durationMs":4710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5609f6479eac3cd9b7a7-8b23b53f970ad335810a","project":"chromium","file":"Features/AgentLogStreamHandover.spec.ts","title":"A run that keeps streaming is never polled, and reconnects from its cursor","durationMs":7428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5609f6479eac3cd9b7a7-d27d4198437bb484a92f","project":"chromium","file":"Features/AgentLogStreamHandover.spec.ts","title":"Scrolling a live log pauses auto-follow and the toolbar toggle resumes it","durationMs":12095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-1d7fa6c7705f360dd57c","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"AI badge should appear on entity description with Suggested source","durationMs":9343,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-4d509e367d791e680fce","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"AI badge should NOT appear for manually-edited descriptions","durationMs":9284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-ad865f0b3a35d329cfae","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"Automated badge should appear on entity description with Automated source","durationMs":6863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-c879ec9ef9cceb2c1db5","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"AI badge should appear on column description with Suggested source","durationMs":12964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"568c8eba961df9f30237-d7e62feac5044c0d61fa","project":"chromium","file":"Features/ChangeSummaryBadge.spec.ts","title":"Propagated badge should appear on entity description with Propagated source","durationMs":6957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-00d10c1204dcb1503daf","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"uploaded document card shows name, size, updatedBy, updatedAt, and folder","durationMs":8557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-1333813a8cf577276069","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"expanding a folder shows 10 files, view more loads the rest, and show less collapses back","durationMs":8891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-24e040b4f0daf57f8c2b","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"document appears nested in the folder tree after being moved to a folder","durationMs":10201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-269c7beb9556949e695f","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"moving document to folder shows folder on card; re-opening menu shows current folder selected; clicking it again removes document from folder","durationMs":10471,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-2e28f17914a39684acc0","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"retry on a failed file updates the row to complete and keeps the modal open","durationMs":10627,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-2f7b38c26e82cbe867ce","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling the bulk \"Move\" dropdown loads the next page and reveals the page-2 folder","durationMs":13708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-38c6c355899b59d8b7a4","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"documents view container is rendered","durationMs":7618,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-41757222b5c8359eed12","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"copy link button on document list row copies URL with correct document id and opening the link shows the preview panel","durationMs":15271,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-4745dae95484add0ade5","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"create folder appears in sidebar tree and delete folder removes it","durationMs":11041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-485a24ecc4ba1cdad79f","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"delete single document from card menu removes it from the list","durationMs":9900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-4b077df390afe8767316","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"clicking folder in sidebar shows only that folder documents and move menu show the current folder","durationMs":11625,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-62c0897bad0eda516e8d","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"attaching a new file does not close the modal when a pre-existing error file is present","durationMs":10559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-639d91951f33be98d7a6","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling the per-file \"Move to Folder\" submenu loads the next page and reveals the page-2 folder","durationMs":10212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-74c465ee083236782524","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"partial batch failure keeps modal open with failed rows showing try again","durationMs":9940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-77de7e00171675e4d461","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"file upload attaches file and closes modal, then appears in list","durationMs":10280,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8150a4d5518b4bb29ac0","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"clearing document search restores the full list","durationMs":9224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8688b851d9e1c94056d6","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"bulk move moves selected documents to a folder with a single API call and folder name appears on both cards","durationMs":16879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8737cb9413dd7cb2e802","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"searching documents with no match shows empty state","durationMs":8997,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-88817c4218092444a545","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"clicking document row opens preview panel with name, status, size, folder, updatedBy, updatedAt and copy button copies correct link","durationMs":9935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-8d88e17dba6bf2ee365f","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"bulk delete 2 documents removes them from the list and both appear in the archive","durationMs":15906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-a00b3e03f359967e5d5d","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"Upload File button opens upload modal with correct title and hint","durationMs":9706,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-a9f5bd79d23a70cae703","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"oversized file appears in list with failed state and Attach button stays disabled","durationMs":12459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-d5758dd9e35122c24e51","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling the sidebar folder tree loads the next page and reveals the page-2 folder","durationMs":9075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-d6fa28cd9dd0a23fe766","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"searching with folder selected scopes results to that folder only","durationMs":9220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-d716db49c6608dbe0e11","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"shows header with Upload File button","durationMs":7043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-e2345c9897597a5db162","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"scrolling to the bottom of the list loads the next page of documents","durationMs":11018,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-edb3ac72c05e7f318a35","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"move document to folder via card menu shows folder name on the card","durationMs":9811,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-ef0af5d349390d9be21a","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"searching documents filters the list to matching results","durationMs":8177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-f42e131cca4e98999103","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"duplicate filename in same folder shows retry error; uploading same name to different folder succeeds; delete file and folder from UI","durationMs":16163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"56ea56135a0dd653746e-feebbefe7b5c42ddb24e","project":"chromium","file":"Features/ContextCenterDocument.spec.ts","title":"duplicate filename upload fails case-insensitively in the same folder","durationMs":10208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-1a30082a0e8c0134b699","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values Sum To Be Between","durationMs":17747,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-220c8abdae85161f7ef1","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Not Match Regex","durationMs":18181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-2bc0479414d1cfb7e52a","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value StdDev To Be Between","durationMs":16996,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-527690061879323e9f56","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Mean To Be Between","durationMs":16719,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-52a4ac74b376c6248a8b","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values Missing Count To Be Equal","durationMs":16291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-585c361e018618ac3c85","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Min To Be Between","durationMs":17648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-5cf5641d7794e01ed134","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Match Regex","durationMs":17379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-8d0cc261c61869a2e942","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Median To Be Between","durationMs":18468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-941e7252830d062fca15","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be In Set","durationMs":18544,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-a728a614c03861fbe05c","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values Length To Be Between","durationMs":16641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-b8c2ba1a531cf17537f6","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value Max To Be Between","durationMs":16358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-b9c4fc654f6df8a64278","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Value To Be At Expected Location","durationMs":15728,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-be68a0dcbf4404b7c60d","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Not In Set","durationMs":15852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-d2b4cbf07a2eb74cafaf","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Unique","durationMs":15979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-d44e518bd09b8d8cca9d","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Not Null","durationMs":21275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"57f6f59b8a2fbb0240c4-f0ad21757191a49ab561","project":"chromium","file":"Features/DataQuality/ColumnLevelTests.spec.ts","title":"Column Values To Be Between","durationMs":16569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"58209e668526b4118920-9962bcde1da3ae180f23","project":"chromium","file":"Features/TableConstraint.spec.ts","title":"Table Constraint","durationMs":25911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-150f00a8522948ca82c7","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"removing team member should create activity","durationMs":11070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-281ff782d6a9895b5d37","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should be able to resolve team-assigned task","durationMs":11993,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-4218944b90688690d3c8","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should see team-owned entity changes","durationMs":10478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-6a1509d7c1e716eb9550","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should receive notification for team-assigned task","durationMs":11738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-8caa0444f8b3d9f04f71","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"non-team member should NOT see team-assigned task in their tasks","durationMs":12170,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-ae919be6e81338fd2a2a","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team page should show activity feed for team","durationMs":4077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-c97f6ef399e1f3cb9b58","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should see tasks assigned to their team","durationMs":10998,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-d9e43035c5a38c2b7517","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"team member should see team membership changes in activity feed","durationMs":10228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-e2bc93dfdbdc70314acc","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"non-team member should not see team-only activity","durationMs":11419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5840c29779fa06dc8fc9-ee6cda8cf796aaead244","project":"chromium","file":"Features/Tasks/TeamActivity.spec.ts","title":"different team member should also see team-assigned task","durationMs":11687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-12d140d9d851ee24f0e1","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Add teams in hierarchy","durationMs":14198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-651d615e2b611721b171","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop on Division team type","durationMs":8505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-821ac29f15154291c014","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should fail when draggable team type is BusinessUnit and droppable team type is Division","durationMs":8160,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-84b55c520eac6337ee73","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop on Department team type","durationMs":9924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-9eebb114627308bfceda","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should fail when drop team type is Group","durationMs":7287,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-c5c76c34a2e5cbd00ce6","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop team on table level","durationMs":8457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-cf4bd8f779f87bb20516","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should fail when droppable team type is Department","durationMs":7707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5937f45c8a0b55964dfb-e02d0adfda4658ae691c","project":"Basic","file":"Features/TeamsDragAndDrop.spec.ts","title":"Should drag and drop on BusinessUnit team type","durationMs":10015,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-17226c8e4fb8758d4c16","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with only VIEW cannot PATCH incidents","durationMs":10887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-40d5b508af0f1557c186","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TABLE.EDIT_TESTS can see edit icon on incidents (alternative)","durationMs":10506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-5b14a963076563878b00","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"Consumer-like user cannot see edit icon and cannot create/edit incidents","durationMs":11220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-6952ddbbfc1aded68ffe","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view incident CONTENT in UI","durationMs":10915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-86854d0ef42ab99072e7","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TABLE.VIEW_TESTS can view incidents in UI (alternative)","durationMs":10561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-906fb153657cd8c10018","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TEST_CASE.EDIT_ALL can see edit icon on incidents","durationMs":11415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-bdbf4bb4dd50592dc6ab","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with only VIEW cannot see edit icon and cannot POST incidents","durationMs":10373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5985cb00d8cd09145705-e24504ddfad39ded9cfe","project":"chromium","file":"Features/DataQuality/TestCaseIncidentPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view incidents in UI","durationMs":11393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-8fb80db9e9e824864860","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should show loader then render classification content on initial page load","durationMs":5900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-902997d142078395f0b2","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should render correct content when switching between classifications","durationMs":11606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-bc6bf4188428df4e1363","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should render classification correctly after page reload","durationMs":11856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"59effc6c36037d92b112-d3427f89e0e3492163f4","project":"chromium","file":"Pages/ClassificationConditionalRendering.spec.ts","title":"Should render all classification detail sections after loading","durationMs":10268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a571ecbb30c2877255e-000cc1bf493e11634f32","project":"Ingestion","file":"Pages/LogsViewer.spec.ts","title":"Logs page shows breadcrumb, summary, and log viewer or empty state after opening from bundle suite pipeline tab","durationMs":9062,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-00a1cdb503e15dbb492e","project":"chromium","file":"Pages/Domains.spec.ts","title":"Comprehensive domain rename with ALL relationships preserved","durationMs":37563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-058d4f127752c8b36927","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify duplicate domain creation","durationMs":13638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-08165284efa6f293a92a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Should clear assets from data products after deletion of data product in Domain","durationMs":78533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-13c6520c826c7eca4b68","project":"chromium","file":"Pages/Domains.spec.ts","title":"first-time add (no current domain) commits without showing the warning modal","durationMs":19388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-1810cc2b4c4a408af07f","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify redirect path on data product delete","durationMs":16531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-1edacb9d8c077caa7901","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain","durationMs":26584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-211da11cb816223351be","project":"chromium","file":"Pages/Domains.spec.ts","title":"Domain owner should able to edit description of domain","durationMs":19500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-28fdb3fda9203a613a93","project":"chromium","file":"Pages/Domains.spec.ts","title":"Data Product announcement create, edit & delete","durationMs":34611,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-2bd269f19362ee149752","project":"chromium","file":"Pages/Domains.spec.ts","title":"Should inherit owners and experts from parent domain","durationMs":15321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-2c7f60df9b21b10d852c","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with tags and glossary terms preserves associations","durationMs":17784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-316848d9a8aa099bafae","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain tags and glossary terms","durationMs":38822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-39708973ea128903f12a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain and subdomain asset count accuracy","durationMs":61721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-3a657a5b353f23a52971","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with data products attached at domain and subdomain levels","durationMs":14192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-41ad0369adac81ff6b18","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with assets (tables, topics, dashboards) preserves associations","durationMs":36405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-42fe30db5b099636336b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Subdomain rename does not affect parent domain and updates nested children","durationMs":18697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-468822f47c1bfe7e56ea","project":"chromium","file":"Pages/Domains.spec.ts","title":"Assets tab lists the assigned glossary and its inherited term","durationMs":8468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-4943e305ac2f77dab3e8","project":"chromium","file":"Pages/Domains.spec.ts","title":"AddDomainForm description preserves typed whitespace","durationMs":11435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-4e3971359320b075cbb3","project":"chromium","file":"Pages/Domains.spec.ts","title":"Add-Assets drawer quick filter - behaviour matrix","durationMs":24243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-4ec6b7d25e96a0a0c363","project":"chromium","file":"Pages/Domains.spec.ts","title":"Domain announcement create, edit & delete","durationMs":27637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-54632a239b314fb2b087","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain data products count includes subdomain data products","durationMs":37273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-5ea87aba82de9e69f803","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with deeply nested subdomains (3+ levels) verifies FQN propagation","durationMs":14212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-60ec59c847ceb9594d4a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with subdomains attached verifies subdomain accessibility","durationMs":13851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-78907b1bc71d2fbf4f0a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify data product tags and glossary terms","durationMs":20601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-7aca6831130839a0cec8","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify domain custom property value persistence","durationMs":20143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-832afab7b2e6da27dcd6","project":"chromium","file":"Pages/Domains.spec.ts","title":"slash, mention, and hashtag popups are usable inside the Add Domain drawer","durationMs":18407,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-867db2298f498ed22771","project":"chromium","file":"Pages/Domains.spec.ts","title":"Follow & Un-follow domain","durationMs":18598,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-877f57fd0b9d6c00c328","project":"chromium","file":"Pages/Domains.spec.ts","title":"User with noDomain() rule cannot access tables without domain","durationMs":15686,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-8a19c401185f31534530","project":"chromium","file":"Pages/Domains.spec.ts","title":"Multiple consecutive domain renames preserve all associations","durationMs":49361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-90441b02005e9e698942","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create domain with tags using TagSuggestion","durationMs":13331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-90d3b0f4f38255032906","project":"chromium","file":"Pages/Domains.spec.ts","title":"cancel on preview modal aborts the move","durationMs":20349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-941ba943b9b6909b181b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create domains and add assets","durationMs":32146,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-a64ddf86b530d1b08c7e","project":"chromium","file":"Pages/Domains.spec.ts","title":"Data consumer can manage domain as owner","durationMs":11038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-a91a7b57d2c8980e04ea","project":"chromium","file":"Pages/Domains.spec.ts","title":"shows preview modal on cross-domain move and commits on Move Anyway","durationMs":21024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-b5b9e238dec299377ac0","project":"chromium","file":"Pages/Domains.spec.ts","title":"Domain Rbac","durationMs":59073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-b9e70b1c81b9ba79fe2b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify Domain entity API calls do not include invalid domains field in glossary term assets","durationMs":15126,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-bde707fc5aac0401750a","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create subdomain with tags using TagSuggestion","durationMs":19325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-c38fbe441d42c9627329","project":"chromium","file":"Pages/Domains.spec.ts","title":"preview names affected data products when moving across domains","durationMs":15975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-c9d5f9bbc47b87764df6","project":"chromium","file":"Pages/Domains.spec.ts","title":"Follow/unfollow subdomain and create nested sub domain","durationMs":27330,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-d88964156dbad267a3fa","project":"chromium","file":"Pages/Domains.spec.ts","title":"should handle domain after description is deleted","durationMs":8319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-dc27f2d87881ab505c0b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify Domain entity API calls do not include invalid domains field in tag assets","durationMs":14876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-dfc370e7cca8f37456f2","project":"chromium","file":"Pages/Domains.spec.ts","title":"should render the domain tree view with correct details","durationMs":5093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-e39301d5c52576b7bc0c","project":"chromium","file":"Pages/Domains.spec.ts","title":"User with hasDomain() rule can access domain and subdomain assets","durationMs":10373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-e915b74c6eba6a3cb81d","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename to existing domain name shows appropriate error","durationMs":10738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-eba5d9a4be11a73fb40b","project":"chromium","file":"Pages/Domains.spec.ts","title":"Rename domain with owners and experts preserves assignments","durationMs":13805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-ec0297c4e178bfb838e2","project":"chromium","file":"Pages/Domains.spec.ts","title":"Verify clicking All Domains sets active domain to default value","durationMs":21498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-edbb83c1aef23ac5fe9e","project":"chromium","file":"Pages/Domains.spec.ts","title":"should handle data product after description is deleted","durationMs":10339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5a5bc63dc66e3147e5e8-f2a49bf85e545308f9cf","project":"chromium","file":"Pages/Domains.spec.ts","title":"Create DataProducts and add remove assets","durationMs":82980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5b560f2a008735eeb753-59998383f71d95e33941","project":"chromium","file":"Features/DataQuality/IncidentManagerAfterOwnerChange.spec.ts","title":"Incident Manager renders after a test case owner change","durationMs":11155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5c28d935b3c657a6e5bc-73a4cae56b3a100775bc","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts","title":"Admin: Complete export-import-validate flow","durationMs":250031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5c28d935b3c657a6e5bc-a936c2f91f4ad9769ad0","project":"ImportExport","file":"Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts","title":"EditAll User: Complete export-import-validate flow","durationMs":258400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-10b3bf8dd0d55f85d77d","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Tags","durationMs":10690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-18610c86119ed13f58a1","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Search Index","durationMs":10592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-3aa370ad5eaa21e64275","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"API Collection","durationMs":9560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-4f41b2190e1d1f9d68e2","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Glossary Term","durationMs":9465,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-5675237446380d7955da","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Database","durationMs":10267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-7b5d40e65305dc11c3b4","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Stored Procedure","durationMs":10190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-7da97f8239b2930647ac","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Table","durationMs":11086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-993a003b732f85ca70f1","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Dashboard Data Model","durationMs":11155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-a3aaf964369df56c9bdf","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"API Endpoint","durationMs":11050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-aa4c7687b25f08368410","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Column","durationMs":10968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-aca5963b052c2fbcc208","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"ML Model","durationMs":9402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-adf3ee9562a932f7cfb4","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Topic","durationMs":10684,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-c0d85d22753538870e95","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Database Schema","durationMs":10647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-ca00f14c4cb64a35f244","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Dashboard","durationMs":10155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-cd028f49219fc3decf23","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Pipeline","durationMs":11153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-d9b951c102d713db155e","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Container","durationMs":9881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5d2c333690b61eef10ec-dc8ba8fe61a148caacd4","project":"Basic","file":"Features/ExploreSortOrderFilter.spec.ts","title":"Metrics","durationMs":9536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-247a852a8f9d96911088","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Sort state should be preserved when searching columns","durationMs":6421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-2d5d89cfca8730ffb2c3","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Clicking Original Order option should sort columns by ordinal position","durationMs":5831,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-3c6d240db259312d28e5","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Clicking Name column header should toggle sort order","durationMs":5592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-70bcb1d6a1cd9df68f81","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Clicking Alphabetical option should sort columns by name","durationMs":6653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-a5dfbdd951385e32b97a","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Sort dropdown should show Alphabetical and Original Order options","durationMs":5298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-c01e49e259252126d74c","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Sort dropdown should be visible on table schema tab","durationMs":4900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e32522fea48c4685990-c86bd28c40019f7bf7ee","project":"Ingestion","file":"Features/ColumnSorting.spec.ts","title":"Switching sort field should reset sort order to ascending","durationMs":5974,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-0466efa203f90064b580","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary truncates long description and end of text is not visible before expand","durationMs":7000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-197cf17e5b07ddff57de","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Customized Table detail page Description widget shows long description","durationMs":25999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-1d5bdad4fce05f36540c","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Domain long description is scrollable and end of text is visible after scroll","durationMs":9895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-60fae3d5fe2e9ea4edc1","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary long description is visible after expanding","durationMs":7243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-76ee66e52bce790fb914","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Data Product long description is scrollable and end of text is visible after expanding","durationMs":9121,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-9380f0005af196f8f8cc","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Domain description comment-thread button opens the activity feed drawer","durationMs":9132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-bf35b4fa3269cd34eb66","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary Term long description is visible after expanding","durationMs":7449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-c84de7d4c776aa2235ca","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Glossary Term truncates long description and end of text is not visible before expand","durationMs":7159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5e3a40cd5a33dbdfc6db-c993b188be16c921d381","project":"Basic","file":"Pages/DescriptionVisibility.spec.ts","title":"Data Product truncates long description and end of text is not visible before expand","durationMs":8488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-2fc13bd486ba204a9b0e","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":68669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-30b6dae7d0a961254f56","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":64619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-4f3a6fb1fb3de6d8217d","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":128413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-92cd730c005813f91465","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":100633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-94c100d67d396805d1b5","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":9679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-9ecb9ce96078b339d264","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":7368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-a044c42b96a086d46495","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":162501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-a3b61ed679be08981a84","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":7010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-acddffdad8f69d48d4ce","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":10268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-b3d6519c76369e63a867","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":7380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-c745b5314f6b89d8d8dc","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Create Service and check the AutoPilot status","durationMs":100482,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f37f0e1f4111ad5b126-f5cf031d5d3d53ec8d50","project":"Ingestion","file":"Features/AutoPilot.spec.ts","title":"Agents created by AutoPilot should be deleted","durationMs":8583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-35843ba93005559bc5b7","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"edit form renders and manifest edits are saved","durationMs":8405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-70976550640ebe56c182","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"manifest editor is full width, clears cleanly and keeps caret stable","durationMs":4413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-8525dc7ae87c5a745a7d","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"confidence field rejects values outside 0-100 and blocks next step","durationMs":4717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-d301fbab1271274948c4","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"sampleDataCount rejects non-positive values and blocks next step","durationMs":4721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5f9b7046cb92d05086b1-e1ac46b0fa3419663979","project":"Ingestion","file":"Features/StorageMetadataAgentForm.spec.ts","title":"auto-close keeps the caret between the inserted pair","durationMs":4254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-08f0afc5bbbcfddf5fe8","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should display correct status badge color and icon","durationMs":20481,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-0c5bb45f7891c174950a","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should inherit reviewers from glossary when term is created","durationMs":18623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-26b4e489ecf3c2ec93b8","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should start term as Approved when glossary has no reviewers","durationMs":15643,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-27f2d6ee3aefa050281a","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should view workflow history on term details page","durationMs":11779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-7faac0bc93febd2581b9","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should delete parent term and cascade delete children","durationMs":15132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-bf53bdbb0a31361d92aa","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should change status when non-reviewer edits approved term","durationMs":17111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-c2809e67875b4136fbc3","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should not auto-approve term when glossary has reviewers","durationMs":16794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-c623fe2508894ad9aa77","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"non-reviewer should not see approve/reject buttons","durationMs":28321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-ea2302b8bcba34efbbcb","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"owner should not see approve/reject buttons if not a reviewer","durationMs":26940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"5fdbea9f250338b68a5a-febeba98e63565adc403","project":"chromium","file":"Features/Glossary/GlossaryWorkflow.spec.ts","title":"should show workflow history popover on status badge hover","durationMs":12176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-17bb560f186a52556b6e","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently created article appears in the Articles pillar card recent list","durationMs":7494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-35ffe7964f4ff382e358","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"clicking each top summary card redirects to its corresponding list page","durationMs":10373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-591d8e2b0ba501dd7afe","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"Create > Quick Link creates a quick link that appears in the Articles pillar card recent list","durationMs":10484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-7e65fcaf721dd4c7fc90","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently created memory appears in the Memories pillar card recent list","durationMs":7126,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-82c968bc20dd40640260","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"memory with highest usageCount appears at the top of the Most Cited Memories widget","durationMs":7148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-9c9d3267a4439857e600","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"folders widget shows folder with file count and expanding reveals child file","durationMs":7303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-a485be19ead771b720d0","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently viewed article appears in the Recently Viewed widget after visiting it","durationMs":10994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-a7a4ddbacb21212a4925","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"recently uploaded document appears in the Documents pillar card recent list","durationMs":6873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"625aedead59fb3070a5e-b39405d678aebfb3c9d0","project":"chromium","file":"Features/ContextCenterDashboard.spec.ts","title":"Upload File button opens the upload modal and uploaded file appears in the recent documents list","durationMs":7842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"629436f87b212b8ba678-b5eccd0197361c9c4f78","project":"Ingestion","file":"Pages/TestSuiteDetailsPage.spec.ts","title":"Add test case modal on Test Suite details page - filters and select","durationMs":14197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6371c6e2d907c92358e4-a6573e241600590ee3d5","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":27447,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6371c6e2d907c92358e4-c116df633ffcf099a993","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":28825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-4067d73d89ad7e8a9d7b","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":36008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-4c0a127433aa7dd6e72b","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":15853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-6cc746feeae7fcde0753","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":16541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-8ed5ae9e4457d894e9a1","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":23568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-c171fd09b78290a7ee3d","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":28352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-c48e9e0adb431a610c55","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":28760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-d459106bf07dc4b72448","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":28718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-ddd05ab1ec93995dc321","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":26526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-f1417577e5c493c9ed9d","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":27492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-fc8cffe6fccb985e0363","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":17942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64585c575e6fcefb6853-fe8f25b8cb74ea0c9c11","project":"chromium","file":"Features/RestoreEntityInheritedFields.spec.ts","title":"Validate restore with Inherited domain and data products assigned","durationMs":27569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-01215054e737e2c593fb","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Create team with domain and verify visibility of inherited domain in user profile after team removal","durationMs":13716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-16b7d856c97d302db432","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Non admin user should be able to edit display name and description on own profile","durationMs":8950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-2d41661b7fb29796cb11","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Admin user can edit teams from the user profile","durationMs":9843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-761b0901e1a38838b81d","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"User can search for a domain","durationMs":12002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-82f49cf6ec1e1428430f","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"My Data Tab - AssetsTabs search functionality","durationMs":22032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-8d5d1460501ed67f3bfb","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Admin user can assign and remove domain from a user","durationMs":15418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-a1a41e105bc8e1f05019","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Admin user can get all the roles hierarchy and edit roles","durationMs":14411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-dd0919f68d1d3f97ba68","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Subdomain is visible when expanding parent domain in tree","durationMs":12868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6491031c3e271b473ed6-e327d2178a45b46d6a94","project":"chromium","file":"Pages/UserDetails.spec.ts","title":"Non admin user should not be able to edit the persona or roles","durationMs":10305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-270895da7594f80804d0","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"Tier1 OR Tier2 union shows assets with either tier across asset types","durationMs":14439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-2f5e7621dfc5950e7dbe","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"removing one tier chip narrows the union to the remaining tier","durationMs":19402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-77d802807f3b1de7d1e5","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"domain filter spans asset types and ANDs with an asset-type filter","durationMs":22128,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-a5ea7273e17fe2c0b22c","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"certification union shows assets certified with either level","durationMs":34658,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-d88a3c506999e00ab9af","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"glossary term filter spans asset types and ANDs with tier","durationMs":28418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-f4233e4ff83a89dfc78b","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"tier and tag filters AND across fields","durationMs":15946,"attempts":1,"retries":0,"outcome":"expected"},{"id":"64ebf94c09564950d872-f629a0aa9880099c7b25","project":"chromium","file":"Features/ExploreFilterComposition.spec.ts","title":"asset-type union composes with tier union (AND across, OR within)","durationMs":26908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-00c1b828793ac9ccad42","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":15858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-010a74dfd5f225fdd9ac","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16424,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-02cdcc35da1446d26426","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":28879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-0513f79e653d347c7603","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":15440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-05568392368ae2bd8841","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":12615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-076047cd3a3cd9186780","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":18972,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-0b18fe048332aed087f0","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-0e4eed2d6ca3374d26a7","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-106e894b7b0f76f0a360","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":14441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-13d9772ce8471d90d2fb","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16525,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-19e7e34913aaccebcebd","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-1a342db08b7329cc2010","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":16511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-1a8e244a95c0d725bc93","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-1c6d2e1ac16152f480f0","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":15416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-2172832393bae4110f5a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":12614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-21e015047436a930e5a7","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":15798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-241282b34358796f6850","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15395,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-265c0bedcb12d4ef691f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19270,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-27dfe3b37ded28891ed3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-27e953a961e46ba2243b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":17302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-2881886f24b7cb9bedb2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-28a34def86e53882b978","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-28f65a1e4a970d0ce460","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":11408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-2ebf49154da3380d587f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":16094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-31492e12c2051bbec6b3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-319fb1586353f9bf979c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":12584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-324024e123c76341d586","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":18166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3313a1c7730a0f079c48","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3336421788437383e2cc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":15113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-34f290ac8ac48a8f3681","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-39b25a08623f358085e3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3abe5cbe7ce08e9c39ef","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18907,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3b834e2e1e9305adc7dc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":19689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3c15dad0de10fcb3940d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":13730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3c344177da39d32ebbb3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":11820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-3d3fc741cd693c321f3c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-42bfa76fce18d5b34428","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-433104e7d8c1442600ca","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-43365053282d79a2ef4d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":16225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-43a7b8e6fc2c81346e3f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":10825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-448846b13aaa4c960092","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-454d7ae3bb0f64862809","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16604,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-46adcce2c19f39334ac2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":15586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-47406fd7c5294829cd17","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17034,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-48370bd09b976d97dbd8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":13115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4935ec04bac029211d03","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4b4716d8c87319aaa92f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4b72173a8ebe71df8285","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4cbdcc28feeba140f2ea","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4ccbd565695fa5768657","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":12651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4d38fabf8de3bc50313c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":15028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-4d933fca87fdac097185","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":17889,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-50caa1b488c051292cc8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":17786,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-52a3ac737815ae734775","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-533ef8c505f142eba030","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":18700,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-545e6e53903fed82a826","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5585a4494ff06f0b626c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-590c184434bac31ae289","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-59c5b44e80429341d27c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5a969009255a2a964813","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":16162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5b00196bb214ede31674","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5ba53f6cc22bb1ca824a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":17784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5bd2a819a7b25eb274d2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5c4c3f255252af488b0d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5c65ba00083611ce622d","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17236,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-5e2a885b3d21932d846a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6236c10675925edb9b90","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":13553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6583488d0da01fc8ef29","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-65d9d74c865640a65a26","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":12576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-65dd33291f9b5de7ba4e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-68260693621f862d67b2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-69fbcd4a7e87daaae068","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":14088,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6c2e72a4195b2981a312","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19424,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6c6060cbfda413351fb4","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":19092,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-6f927725b3147cfc1549","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":10229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-70909101625a8fcca6a3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7248df367dfd2960be47","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":14633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7273ab0be89733ad080c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":12070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7618fdc6e84eff5f6dbd","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7d730e6039e107fd3ae8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19604,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7db92659d3391ad65c1a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-7e2dc5e8aac0d5fff8d7","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":23154,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-804af1ddf76c49910781","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":15480,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-80d7156a1b91ed22287b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":12864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-8150049125a7505036e2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":14003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-81d59491a1bf468b229b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-82683edd2cc5c2be916b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":19731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-86bb2767ec2061d053df","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":18727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-890d2284ebd3bdb51816","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":12107,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-894c46dfabd3533da75b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":19454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-8ebf174596f8bd815bea","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-8edcc5e6d6bb0f1a16ba","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":24918,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-905877fe766e2211d3da","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-91dfffdf023fd8d664e4","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-93332f160a13b68f334c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-93399eb07a69f20e4393","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":14511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-935d5d6eaae6efff8844","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":21746,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-96519457d8bbc8c5c44c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-97ed7970c64c03db8ca0","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":17441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-97f87447094342e0138a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":24628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-9a0f3261557420a0a829","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":21049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-9db0dc189483c3aa759e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":12581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-9e8346362c3dd59d8365","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":14308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a0ac272b87419b411d20","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":26420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a42f2967a883983f7eee","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":19636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a4d2e44b270d545690dc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":15891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a562f1607b5d97da27a3","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":11060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a5c06614bd30ae670149","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a6d20cb1d84778e47c4c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-a9010f9968be28f37ccb","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-add458358c6509860921","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":18779,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b081a458527dd4771f99","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b28f4f7e3438b4f89868","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b347863166e253de21ec","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":12883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b3a81cc243659b5b22d2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":19515,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b3eab2a5b7bac6d69f9b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":13722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b78de60c5b14eebde42c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":21179,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-b8fa07d6060299c39f8a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":17787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-bb3386e61fb78693df7c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":10919,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-bb40dcab0576d1ea381a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-bbeb537c5b28067ca5d5","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":13872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-be8661dc20d902f3ff6b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":13639,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c0c35dd94ce719f0b636","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":18669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c2a115cc084c1b8d1a18","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":11011,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c2cdcf6514943a118a32","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c3c5ddb9bebf03c0ec16","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c86bdbbcf24594eef792","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":13759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c871813cde4f307ea67f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-c994ce8b23bc3b24cae8","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":13695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-ca031813decb3155a1cc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-cad3b8bff0bfe9d71e62","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-caffc1fcf9b06d4b8168","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d1223cb6f1374f90ac92","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update displayName","durationMs":16098,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d14f44ac967a37b19113","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d2913f43967f6ace073f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d2a12ff88beae508ac9c","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":10770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d369aa150f9ce35db93b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":22066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d4a6824ffb45dfb27f03","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19976,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d624bd1de4f48d8c3f26","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":11030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d6759cdd35075bf16730","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-d6c7ad5b8c7bf815b262","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dc19daf4b9e9d8bd13ae","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dd7ab1e9b75187ae8c78","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":16208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dd88ae8713aa827fe8ef","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":13882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-dff7569cfc2418f45d23","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":20112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e0e5f798bbe87c7693d6","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":18532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e1d9500f79f1f507b9d5","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":17834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e2baa8f96ddd44d625fe","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tag Add, Update and Remove","durationMs":17923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e2fe242e40e7ecc5c28e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12348,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e4f5b5761c113321a49f","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e7a260ce54c82fa93a5a","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":18684,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-e9a0ac4eadb2bfe66a3b","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-eea4ca892981bf47608e","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Tier Add, Update and Remove","durationMs":16816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f4db9223c18459e4eda2","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":16081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f5032a00993091c46b58","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":14032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f82caafb000c9503dedb","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Follow & Un-follow entity","durationMs":24995,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-f9921789c29eb324c1c4","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"UpVote & DownVote entity","durationMs":15048,"attempts":1,"retries":0,"outcome":"expected"},{"id":"659315df23bffa2c64e3-fbd7a84a2f9ab8d3d0cc","project":"chromium","file":"Pages/EntityDataSteward.spec.ts","title":"Update description","durationMs":14938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-01848a9bbdce6b9464a1","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Container Column with OR operator","durationMs":23582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-01d3ad34adeb6f3572a9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Task with AND operator","durationMs":26659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-01e396d7fe625ea02be0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database with AND operator","durationMs":23841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-05d5089a21fbd76007e0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database with OR operator","durationMs":25969,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-0ed29065fa2f8ec2272b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Model Type with AND operator","durationMs":30988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-104c3fa8858e1ae3bd07","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Response Schema Field with AND operator","durationMs":26268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-10da06a834ad193ca900","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Field field","durationMs":34425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1265d5ff203e4d02a28a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database Schema with OR operator","durationMs":18927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-17159e54270c09d3b11f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Project with AND operator","durationMs":27269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-19c8b67e10d5e54c16b9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify count shows with Advanced Search filter","durationMs":15376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1d4be164ce6161534198","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Container Column with OR operator","durationMs":33638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1df04ebae89733aa49dc","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Schema Field with AND operator","durationMs":25914,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1e3349a7ef8159c1347c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database Schema with AND operator","durationMs":28102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1e9ffb963dd4a7583b7a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Response Schema Field field","durationMs":38788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-1ea2187d290d764a4b89","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Is not null – table with a description is visible","durationMs":14622,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-20796c01b78775d6c025","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Not in [tag1] excludes table1","durationMs":17722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-20c96d382fccf4ab79ff","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Request Schema Field with AND operator","durationMs":25267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-265b4edd463886300e33","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Filtering by status \"==\" shows matching entity and hides others across entity types","durationMs":28398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-28aeb826280919957ec4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags == tag1 returns table1 and hides table2","durationMs":17439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-296bab1d11c2b9ca845b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Name with OR operator","durationMs":27956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2aa7c1b0da131245354c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Name with AND operator","durationMs":35448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2b95e329ec5e4e31e5e9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Schema Field field","durationMs":38895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2c3d820f0145617856b6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Container Column with AND operator","durationMs":32008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2ccc28a7a13694b41740","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Container Column field","durationMs":50959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-2e183cba514fb3c2118c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service with AND operator","durationMs":31573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-322ce116d6306a5177f0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Owners with OR operator","durationMs":25076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-35e3f0c99d9eb1a34064","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Service Type field","durationMs":31471,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3728216e42f2d70c0ea6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tags with AND operator","durationMs":30804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-37e7f79fb6618a1e03b3","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Tags field","durationMs":36376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-37fca3a21c7cf0dda6f4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Domains field","durationMs":40494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-38ffce04e25ea99f6ea2","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Column with OR operator","durationMs":30178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3909c10761b7e38e4c65","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"should append page-2 items and make them visible when Load more button is clicked","durationMs":13737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3b2a5bee628fd4b430ec","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Task with OR operator","durationMs":29267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3b4256edbb1eb74b13b5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Chart with OR operator","durationMs":25178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3b768764404abfcf4c61","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Display Name with AND operator","durationMs":37148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3cb9d0ec4de9ab627c1e","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database Schema with AND operator","durationMs":31502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-3fa2fce0a766d87533ba","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tags with AND operator","durationMs":28862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4acd7f5fca00875e8136","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tier with AND operator","durationMs":26970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4b5c200835ff15944667","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Product with AND operator","durationMs":25626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4b9cb43c11746fef17d8","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Schema Field with AND operator","durationMs":21733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-4f927865854ea480aa3e","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Domains with OR operator","durationMs":33113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-55023d9cf5ab1d215a44","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Name field","durationMs":37145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-5f89518d523b9ba9aaac","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Not Contains – table is NOT visible when filtering by a word that IS in the description","durationMs":14502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-5fdfedbd523e3949feaf","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Model Type with OR operator","durationMs":27234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-605194d0ff1cc933d53b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags == tag2 returns table2 and hides table1","durationMs":14913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-63b0c7ba0ae092e35184","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Chart with OR operator","durationMs":22734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-6551e2d525c123143970","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Response Schema Field with AND operator","durationMs":24215,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-68eb716f87bfb906f7fe","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Data Model Type field","durationMs":48918,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-6d789214c13e0a4b34c5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Column with AND operator","durationMs":32384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-70515d66cc35b8507ad6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tier with OR operator","durationMs":25816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-705b359db456f1bc0884","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify count matches the API total for a quick filter","durationMs":12304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-72e8c3ea3b292870634b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service Type with AND operator","durationMs":29059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7474221eea6bd3f6f851","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Column with AND operator","durationMs":26292,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7593b16cd959b1bccb61","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Field with AND operator","durationMs":25978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-75e104c5eaa1b74c34f1","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tier with OR operator","durationMs":24378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-769657657a74bc339745","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Is null – table with a description is NOT visible","durationMs":15074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7a703a36be973b448822","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Is not null returns table with a column tag","durationMs":14057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-7c77a04a9941a95f1d4b","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Display Name with OR operator","durationMs":27691,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-81500305ba1d602123c5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Field with OR operator","durationMs":25153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-8234b81e5a5663597613","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Name with AND operator","durationMs":24278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-83aff3aa6b1a24d2d069","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Project with OR operator","durationMs":22539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-88367c4b6043b9c90965","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Description Contains filter returns matching tables","durationMs":12833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-8a8f8dc139a7a230d523","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service Type with AND operator","durationMs":33039,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-8e6b0455f554d30d7e06","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Data Product field","durationMs":34932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-9188bfd7d42b88264dd7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Request Schema Field field","durationMs":33408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-967c29378578d6fdea26","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Contains tag1 name returns table1","durationMs":13014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-9b337cbe854e86fa72f5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Display Name field","durationMs":44892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a012f1d06ec6466aa8b6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Display Name with OR operator","durationMs":31931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a159f21b5939cebf6a76","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Any in [tag1, tag2] returns both tables","durationMs":20168,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a41dafccec5f9c5ed119","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify browse mode has no count","durationMs":5237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a4e7df45b27cb472b042","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Project field","durationMs":48111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a55cbc04952eee33bff7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Request Schema Field with OR operator","durationMs":24808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a61ec30b0327dc631819","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Tags with OR operator","durationMs":26546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a7bfc8dce1c294247fed","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify search with non existing value do not result in infinite search","durationMs":11312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a8094f96fbbffc874b81","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Owners with OR operator","durationMs":29711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a9032d44e2e5425ad802","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Service field","durationMs":48297,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-a937f2c6c6c939c156b7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Domains with AND operator","durationMs":28352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-aadfd26e649f51ac33cf","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database with OR operator","durationMs":25595,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ad0865cf7553688429be","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Owners field","durationMs":33565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ae1ba0c1a9ffd00603bb","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Name with OR operator","durationMs":29890,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-aff5dd51e0721d50a905","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service Type with OR operator","durationMs":34299,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-b0ac72779a45d7811744","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Product with AND operator","durationMs":34859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-b51becf84e64b5a6b239","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"All entity status options are visible in the Status dropdown","durationMs":9833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-b7275e658eba3413629a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Description Status == Complete – table with description is visible","durationMs":17197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-bbbc587a68840bdb685f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Model Type with AND operator","durationMs":27776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-bd7b44947c9de08623b6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"should find page-2 items via search without clicking Load more","durationMs":9526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-bdd71fde1fcd7c7034f9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Is null excludes tables that have column tags","durationMs":14874,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-beac8ac076370c1e2d1a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Field with OR operator","durationMs":34705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c21787818e27a603b94a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Chart field","durationMs":39051,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c2dc8a3cbadd6d431363","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Task with OR operator","durationMs":31875,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c401249e8edfb596e267","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Description Status == Incomplete – table with description is NOT visible","durationMs":14617,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c4178f3f1a09fee9bba7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Filtering by status \"!=\" excludes matched entity but shows all other entity types","durationMs":26139,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c8e29a2085426519eea5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Chart with AND operator","durationMs":35737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-c91b448181fb0828b8a4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Domains with OR operator","durationMs":26365,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ce5bc3beeaeb56c7c7d4","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Response Schema Field with OR operator","durationMs":22858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d133030d44a21ade5bae","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service Type with OR operator","durationMs":27670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d3ce7297e440b403e050","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Domains with AND operator","durationMs":31466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d79e232222e4787c355a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Database field","durationMs":48163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d929d5fdf2bc919508c2","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Container Column with AND operator","durationMs":28527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-d9700ca4b5a3d6e23726","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Schema Field with OR operator","durationMs":29418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-da4ace00236ed1e3eff0","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify the toolbar Clear All button is removed","durationMs":10528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-dc1da3be5b340f81fe5c","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service with AND operator","durationMs":29056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-dcc05a544a77528fa228","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Field with AND operator","durationMs":21158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-dce1287be55029f6acdb","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Project with OR operator","durationMs":27812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-de073c560d5716e771cc","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Owners with AND operator","durationMs":24485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-de867e203297a3dc87df","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Product with OR operator","durationMs":25803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e07b93065e8a13f5458f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Data Model Type with OR operator","durationMs":23503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e0fcfe3b1c1255b12537","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Schema Field with OR operator","durationMs":29090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e2173d75f8617ecd7b30","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Database Schema with OR operator","durationMs":27926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e31d942443165346ed83","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Database with AND operator","durationMs":32727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e386dbc7762dc93f4e60","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Task with AND operator","durationMs":27512,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e3ca2f4c5a82a5530113","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Data Product with OR operator","durationMs":25060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e731ce0f8d9a3d4de465","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Chart with AND operator","durationMs":23829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-e98c930265f88b9c9ea6","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Project with AND operator","durationMs":19298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-eaec9a63094a1c230fe3","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tags with OR operator","durationMs":24368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-eb1c6c762c82fab9e5f7","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Display Name with AND operator","durationMs":36128,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-eca9d97cb9da576ef82f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Database Schema field","durationMs":44692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ed0b5bb92613ce933c2f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Column field","durationMs":45593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-edde44fec5e8f1dc250a","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Tier with AND operator","durationMs":38366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-ef9b3af75dd47ebf5374","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags Not contains tag1 name excludes table1","durationMs":12650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f03202f4045c687551e9","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Tier field","durationMs":52193,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f1bda9ce9ec6c293e189","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Column with OR operator","durationMs":27808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f338982eff0e858527a1","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify All conditions for Task field","durationMs":39133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f408b40000135ec0eb83","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Group functionality for field Service with OR operator","durationMs":34989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f596f76fabf5baba5568","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Owners with AND operator","durationMs":33511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f691e6bde217c36db0dd","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Response Schema Field with OR operator","durationMs":28886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-f9d8db08a5cca0ce8bd2","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Service with OR operator","durationMs":26839,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-faf56b02741dbae49628","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Request Schema Field with AND operator","durationMs":26992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-fbe116c672f82d125814","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Column Tags != tag1 excludes table1 from results","durationMs":16554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-fccef467d24b33c68ff5","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Not Contains – table IS visible (word absent from description)","durationMs":17005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"665a509785f6ae98f014-fd63e2d647bc5fe4cd6f","project":"chromium","file":"Features/AdvancedSearch.spec.ts","title":"Verify Rule functionality for field Request Schema Field with OR operator","durationMs":34312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-030f976d52547ffee6af","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"locks system-defined relation types from edit and delete","durationMs":12863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-2ae9d6664eb6771f90a9","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"parallel API writers both succeed when exponential backoff is applied","durationMs":8538,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-420283d7f82a561357d0","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"edits a custom relation type and keeps the name immutable","durationMs":13888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-4deb76eb39aff4718dac","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"paginates relation types when they exceed a page","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-62eb7208161f3640d24f","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"rejects duplicate relation-type names with an inline error","durationMs":13562,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-6819ceb2313f81ae13c7","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"creates a custom relation type via the drawer","durationMs":13979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-97bdef908422bd78cf90","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"findRowAcrossPages locates a row when the table has multiple pages","durationMs":15637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-a47fe4536a712063a893","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"delete removes the row from the DOM before the caller proceeds","durationMs":12797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6662893a8541aca2ba9c-eed27231e35e72bb34e0","project":"chromium","file":"Pages/GlossaryTermRelationSettings.spec.ts","title":"deletes a custom relation type","durationMs":12874,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-0d5b9a6fb6b3f1d36fc5","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission cannot see restore or delete actions on an archived document","durationMs":9115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-10825ea530d9799b47e1","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions but not owner sees read-only banner and no edit/delete on the row","durationMs":10283,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-20e0ce562f9ba525f683","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission can see create action but not delete action, and can create an article","durationMs":24399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-2739db8bc9b9a4df8761","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission can see restore action but not delete action on an archived document, and can restore it","durationMs":14214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-27b7063c112f47ef11b2","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission sees no row delete action on memories they do not own, but can delete their own memory from the modal","durationMs":11998,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-421f44e2cb09509abf6a","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see create or upload actions","durationMs":8574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-540e879d00fd41114f62","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission sees Add Memory button but no row edit/delete actions or modal action buttons, and can create a memory","durationMs":13474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-54d59da4e5d21f32b45b","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions and owner can see Add Memory button and all row/modal actions","durationMs":8824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-5fd1ea349c43b5f7ade6","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"admin user can edit and save a memory owned by another user","durationMs":9878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-679ff08bf7ab1e9638e8","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"Data Consumer can view and edit content but cannot add article, domain, reviewer, data product, or data assets","durationMs":5274,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-67ee0ef55073be2f7ff6","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission sees no Add Memory button, no row actions, and no modal action buttons","durationMs":10199,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-6c7c5e4060896807dfbf","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see upload, folder, or row actions","durationMs":9317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-7048ad1b2cdbba8c7098","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"selecting \"Updated By\" actually reorders rows by updatedBy","durationMs":8419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-75d84722d862535a7d5f","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission cannot see create or upload actions","durationMs":8854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-7bf2358642df91e09c6f","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission can see upload and folder create actions but no row actions, and can create a folder","durationMs":16257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-7fbf4a859228cd5d2077","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"created-by-me filter on the archive page shows only the current user's archived documents","durationMs":11806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8688c4eab1661197c622","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see upload, folder create, and all row actions","durationMs":9869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8b30f4dc8b9a4455def6","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see create or delete actions, but can use share/vote/conversation actions","durationMs":20559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8e9545a0b5baa5e47cbd","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission cannot see create or delete actions, and can move an article under another article","durationMs":18882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-8f70f3d35807262b000c","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with createAll permission can see create and upload actions and perform them","durationMs":14429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-9688a6c96efd0f62f947","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission cannot see create or upload actions","durationMs":10539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-9c43270f91aa02211126","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission sees row delete action but no upload, folder create, or move actions, and can delete a document","durationMs":13239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-a1a04fa4162c7391462d","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"a document archived by a different user can be permanently deleted, via the UI, by a user with Delete permission","durationMs":12359,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-aa88bf1cafba61d0b0c8","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see create and delete actions","durationMs":12409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-b2da0b8d956c9c571e7e","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission cannot see restore or delete actions on an archived document","durationMs":9722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-b83ccb07716204f13779","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"Data Steward can edit content, title, owners, tags, and glossary terms but cannot add article, domain, reviewer, data product, or data assets","durationMs":4304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-cbd6a4c438db46a87069","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission sees no row edit action on memories they do not own, but can edit and save their own memory","durationMs":12540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-d406b1d8244bd4837a02","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with editAll permission sees row move action but no upload, folder create, or delete actions, and can move a document","durationMs":12770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-d5d7c9b8b9a2392b0cc9","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see create and upload actions","durationMs":9458,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-e3b36012c515ccf872c2","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission can see delete action but not restore action on an archived document, and can delete it","durationMs":13652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-e45828987ae3f8cf1c7b","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with deleteAll permission can see delete action but not create action, and can delete an article","durationMs":21362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-f14a3d0a85483b085cb1","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"ViewAll-only user cannot create or edit articles","durationMs":10075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-f9b86eac13a88a92bf94","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with all permissions can see restore and delete actions on an archived document","durationMs":8948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6687b1971592d72be17a-fcde0758e6b601a806ce","project":"chromium","file":"Features/ContextCenterPermission.spec.ts","title":"user with view-only permission who owns a memory still cannot edit or delete it","durationMs":9326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-18c6f5eb9f9c19c50dde","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Data Product asset count should update when assets are removed","durationMs":41693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-3a3f742e93d47ca84940","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Verify Widgets are having 0 count initially","durationMs":14012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-81becdadc5311eeb58f8","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Domain asset count should update when assets are removed","durationMs":25055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-9c5b7d3adf677a591fe0","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Data Product asset count should update when assets are added","durationMs":49306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-c6a8e0211da1e6bd097b","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Domain asset count should update when assets are added","durationMs":57047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69931a0cdf9d00fcd477-e2b7b5f7dbe2189375ac","project":"chromium","file":"Features/LandingPageWidgets/DomainDataProductsWidgets.spec.ts","title":"Assign Widgets","durationMs":36440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-31c3cba0658c41ef8b20","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity stream API is called when visiting entity page","durationMs":19871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-5e9ae60fe863e3648021","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity feed left panel shows All and Tasks options","durationMs":14060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-78c3f0503d643e660906","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity count badge is displayed in tab header","durationMs":16097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-78ef0b8aae139b3200d9","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity feed tab shows activity events for entity","durationMs":19871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-b8948aa10be3f126124a","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity events are created when entity tags are updated","durationMs":22157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69abfe37c0839c35e30f-c01253c3651ccbe9853a","project":"chromium","file":"Features/ActivityStream.spec.ts","title":"activity events are created when entity description is updated","durationMs":22803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-052a649575c460f16115","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should display entity name link in panel header in glossary term assets context","durationMs":9162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-668b29b178430ef599ee","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit owners from glossary term assets context","durationMs":13070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-7d959402ac411fa1226d","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should display overview tab content in glossary term assets context","durationMs":8989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-7e30f5925bae38e11c8f","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit glossary terms from glossary term assets context","durationMs":11830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-8d7f4224e6da7668b1a0","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should open right panel when clicking asset in glossary term assets tab","durationMs":9161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-9a8a1508351c9a62e774","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should assign tier from glossary term assets context","durationMs":10924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-9fcb2cd0167b25ce5be3","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should display correct tabs for table entity in glossary term assets context","durationMs":8762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-dcabc8f167f7a85fe179","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit description from glossary term assets context","durationMs":11764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-ee18c163cf99218a6116","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit tags from glossary term assets context","durationMs":10962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69c0e3238d1349fa05cd-f3abb25309536ec109d8","project":"chromium","file":"Pages/GlossaryTermRightPanel.spec.ts","title":"Should edit domain from glossary term assets context","durationMs":11246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69cacca71964c08834ec-13d8e90a56a4cbcc29e6","project":"chromium","file":"Features/SchemaDefinition.spec.ts","title":"Verify schema definition (views) of table entity","durationMs":7335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-0d63c51a5b8439797ec4","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test search on Table version page columns","durationMs":4934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-1afaf40ca75b9169745f","project":"Basic","file":"Features/Pagination.spec.ts","title":"should display at most pageSize rows on each page and total matches task count","durationMs":3664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-1effafa017fa24dae3a8","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schema Tables normal pagination","durationMs":12576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-270586167806dc7a45d7","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Notification Alerts page","durationMs":11073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-4536ce90c513ea40babb","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Table columns complete flow with search","durationMs":16581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-4849a60b7f9b9c75970b","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Stored Procedures complete flow with search","durationMs":13189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-4a9e844a35462eb4ed53","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test API Collection normal pagination","durationMs":10893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-522675c74c67c05389c8","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Service version page","durationMs":5818,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-569e6236bb343a798340","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Table version page columns","durationMs":8623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5976c978fb8e0412cae3","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Classification Tags page","durationMs":9055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5a0809981ccad3fac96a","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Spreadsheets normal pagination","durationMs":12040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5b1b1a14ee145e3320a2","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Directories complete flow with search","durationMs":13820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-5deca5d41faf8cf09f92","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Users page","durationMs":11843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-61c3a2cd143654c345ea","project":"Basic","file":"Features/Pagination.spec.ts","title":"should reset pagination when switching between Files and Spreadsheets tabs and also verify the api is called with correct payload","durationMs":11197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-62a7e49254bc5ed1c0fd","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Files complete flow with search","durationMs":12560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-65a356df11068eb892a9","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Data Models complete flow with search","durationMs":11563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-6ccab878d5d132496901","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Table columns","durationMs":17243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-70eff9216ce9baf67def","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schemas complete flow with search","durationMs":13595,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-7230a3d6ac8be6c0b43b","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Bots page","durationMs":10740,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-755acad3b9ae48868e50","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Service Databases page","durationMs":12246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-7f9d55e3f06664f27de6","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Spreadsheets complete flow with search","durationMs":12133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-81562d6199750c91eedf","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Stored Procedures normal pagination","durationMs":12617,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-95f815f4af52e846761f","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Data Models normal pagination","durationMs":12429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-ac4a045699a81c56318d","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Service Database Tables complete flow with search","durationMs":13155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-b9120310e2cedd8c5bf0","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schemas normal pagination","durationMs":11860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-be507602cb869bf3d3a4","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Roles page","durationMs":10768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-c0e169775cd894d676f8","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Metrics page","durationMs":9811,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-c5300a813856c71be56c","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Pipeline Tasks normal pagination","durationMs":11341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-cf38d16dc446f8c57869","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Policies page","durationMs":11075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d09956c0604ead156107","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Users complete flow with search","durationMs":11963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d28067dfec2215fc2a1f","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test API Collection complete flow with search","durationMs":10389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d4ee9d0888330156246e","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Database Schema Tables complete flow with search","durationMs":13600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-d6cd483f8e72dec2aab6","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test pagination on Observability Alerts page","durationMs":10771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-dbd8d16a665a04625901","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Directories normal pagination","durationMs":9514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"69f04d167d027522a57a-fa33d3888c5145159d4c","project":"Basic","file":"Features/Pagination.spec.ts","title":"should test Files normal pagination","durationMs":10504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ab1a126f5f0454c42dc-aa12aecd843105a4100f","project":"chromium","file":"Pages/PipelineValidation.spec.ts","title":"should reject pipeline creation when task name contains reserved FQN characters","durationMs":8,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ab1a126f5f0454c42dc-efa1da2a9c4231a884ee","project":"chromium","file":"Pages/PipelineValidation.spec.ts","title":"should reject pipeline creation when task name is empty","durationMs":21,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-00d78358a54604aa5230","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Follow & Un-follow entity for Database Entity","durationMs":14746,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-05ceb395a88e2b017909","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-07fa338ea4eb691ca04e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":14426,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-095366bb3f9782e4b4ac","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":14674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-0d9793ea09690a80b966","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-0ebb53f319f2a67ff9f4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":5794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-0fe6b99ec9f67bfa9faa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":13264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-12ec4b8c5deb13223785","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":11781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-13e54e4ad192cd9efb73","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":21648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-141e1d403d78ee81d20d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":6428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-17428dd1dbd106320b78","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-17c18c4a39bde14e5a5b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Database Service","durationMs":24703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-19d75f5f67db078abe6c","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":17609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1b6aef52cf71f2f96cd8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":14151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1cef3376d98ef0bc6845","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1d6aa7210486e47f00e3","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":14781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-1f7257faa3ff6ee3d90a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":11219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2044951d3a73d0b2d996","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":19805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-22f08f8e66fb0a6b142f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2339e2d24363f2751c72","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-23f289761eea5d8ad0d9","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":18575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2415dc37c3890f585aaa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":16100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-28f4e85540f8278e7e5e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":7112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2b3f4a2ef8db1d71465e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":24716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2bb0ad11cb7c8c9e83ac","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":13127,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-2e1bdc838f7d0fd8bcd7","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":11774,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-315d4c39979d5b429be4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":11901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-330814fd205fc63c7a89","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":7135,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-36a6a7eff3583482208b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":14769,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-3d6d96bcfc6c2b28446a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-3f0f017751c0f9e5d24e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":11033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-3fd1a3fbb71265224dd8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":12562,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-439162d3691b598fbc91","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":8483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-44a0649dc047654eaf5d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":11532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-44d28a5b57954577834f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":8403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-456a6d64f84a51837dd9","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":7964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-46581f14ac1a04c5ae14","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Messaging Service","durationMs":27019,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-48696a6d0816b53ee59d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":6260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4ab33598b1cfd871bfe7","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":14717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4bf44086b6fb8019ca24","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":13068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4c97fecb78d90497f70f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":12905,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4ceda484206529830fc1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Api Service","durationMs":28727,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4d7762a289fe4ba86f4c","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":18603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4db8a131edf74e52d43e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":26816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4e3b0413aee3a8de3c8e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14713,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-4eccaafaf317fd3925eb","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":10345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-502d8da9de83d9520848","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-5405ded470cb5150a6d0","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":15556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-586f692293f073d1021f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":8764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-58bdff9e058f898c1af8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Search Index Service","durationMs":26405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-5956015465cac568e5fa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":6227,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-59781b41dd8cc26391e1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-61ca56e64d18f8db0689","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-64ec4bc4779c2028b4f6","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-66c12a591dde84d462a5","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":14362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-681341682d7d6ff41b5a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":15949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-68fd12d73abb2789cdb5","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":13916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6b438bbddf9c67179b23","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6b52238501c9dd87c323","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6e97f2492432e11bd72f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":26948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-6e9f9c02b1878da34748","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":17177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-71ad41b0d7192f9308b0","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-72b2976f74708121344b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Pipeline Service","durationMs":27372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-738ae92e7a456d8559cd","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":9210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-74a1e27f45394080d2a2","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-79f742b06207108de1fa","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":22055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-7c0ca4d50ff297de79ec","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":21151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-7ced936483e254bdc26f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-851289553bf3f933e4d1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":19464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-864ac85bd99a9a4cd647","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":11758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8a886064018e6d7ce40d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":16668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8c3e68a1db2f22a89a00","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":15995,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8dc41e621dab83ad094c","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":15951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-8e67349c98bdd3b3b16b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":16741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-901d2391b8c515986986","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":34446,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-90c9ce604f7a5005c6b5","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-90f41a42948dfce135db","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":10604,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9354d7b199cc56d1285b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Database","durationMs":29259,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-97d8de928397f494de98","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":25066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-98560e031b247e205bee","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":8380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9eb835bbaf3d632ff610","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":14508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9ed1e087674fbc9e90ca","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":14761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-9fe5cbbaefa01f3b8088","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":18724,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a1aa9e9e55e2aaf5c830","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a385aaaa6615db8d41b4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a5df7e6bc93587c9c39f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":14573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a8858778387f593ba0f8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":11738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a915ceb90728aafa8624","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a95000b4d2a834bca12a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":17994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a95af30fabe36816ae5b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Certification Add Remove","durationMs":18696,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-a9ace2bb98e05805214d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ad6771e7ca6599ec9d2f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":12664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-af5887e77e84824f926f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":7758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b1f3c51ac39336818657","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Follow & Un-follow entity for Database Entity","durationMs":25374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b2f8330ad165aa371918","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":7734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b5448a6d970596d21ff3","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":13016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b66b7fb8d4958d16af63","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":23026,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b87b5ff8369052806821","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Storage Service","durationMs":24703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-b8a15061fd3f12b20ddd","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Dashboard Service","durationMs":22284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-bd4d81cb27aebc7522c6","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Verify Search Placeholder","durationMs":9729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-beb2a792c179b0e18582","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":16246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-bfbb1f2951aa7247cfcb","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":11159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c059425f0ee306d51262","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":9095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c0e25a61c0c94d058b14","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":18050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c1ee83ea9c55a5143b78","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":19559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-c5f0c42ad03d6cd1533d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":28027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cd1f1f467e0f30044cdc","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":11102,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cd4638ad50da7c16713f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cd6cc1c77ceb3a4f813f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-cdb652309a855e8e8b6e","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":14262,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d401b8d4fdec50f4d527","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d41e33cf18f0a0f03d4a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":14520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d5c7e41187ffccee6c2f","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":13958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-d7acb023b21d042a3854","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":7153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ddd593594947a3f2f7e8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":8773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-dfa31604b8badf1fca29","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":14429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e2f4e4bd31755dce4ba1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":17203,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e56d1b8c2d393ba2eac6","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Mlmodel Service","durationMs":27952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e5745670b7663e6284ba","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Certification Add Remove","durationMs":18602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-e5b8f6da7ae9c9c091d8","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":26392,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ea74abe48bd512e6d744","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":29247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ea80f5ffeba8e3e514e3","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":13440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ed093e7198e33633d2f4","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update description","durationMs":13307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f19a60e986c74388fcf1","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Domain Add, Update and Remove","durationMs":14147,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f739417ab5977cadad8a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Drive Service","durationMs":28117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f74fb883c671c6c2adff","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":9490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f88eadfd770af9615a31","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-f8908380572ade6ba2bc","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":23827,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fc556a3cfc34a3a4842b","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Delete Database Schema","durationMs":21326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fc6a816a8d68fa625004","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tag Add, Update and Remove","durationMs":17223,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fd38fa8ea0050bc11f12","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Update displayName","durationMs":8960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fd72e28576cf322baa24","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":9244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-fd845648f618a8c8686a","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Follow & Un-follow entity for Database Entity","durationMs":27063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ff8a67b3c643a6de256d","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Announcement create, edit & delete","durationMs":31601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6af163fea506aa4566f2-ff8e8ecfffbb7bc11dbc","project":"chromium","file":"Pages/ServiceEntity.spec.ts","title":"Tier Add, Update and Remove","durationMs":15738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-60c875ad97424dee4e25","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create and approve entity-level description task for Dashboard","durationMs":736,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-786e6f8c70160627e0e9","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create and approve TagUpdate task for Dashboard","durationMs":483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-90cedc12661a4643946e","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"rejected task should NOT apply changes","durationMs":298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-b4317d710c370bd24be7","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create OwnershipUpdate task for Dashboard","durationMs":1661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-f378c009570f9449ef08","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should show task in activity feed after creation","durationMs":17862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-f4e63cb88ba395b56c54","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create TierUpdate task for Dashboard","durationMs":504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b3af04ece311f75689a-f505580b6048b9e7f4f7","project":"chromium","file":"Features/Tasks/TaskDashboardEntity.spec.ts","title":"should create DomainUpdate task for Dashboard","durationMs":354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-0f6f29e2f1c4b474fdd2","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"zoom and fit-view controls are visible in glossary scope","durationMs":8437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-155194eb24d2e2caccd9","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"clicking a node in the Relations Graph opens the entity summary panel","durationMs":9574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-1b32d1add1034bd536eb","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"an edge exists between a nested child and its cross-glossary related term","durationMs":8667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-2b0b559c4357595c86c7","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"search returns empty state when no term matches the query","durationMs":9435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-2d4e6ef72c33fc44d05b","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"deeply nested grandchild term appears as a node in the glossary Relations Graph","durationMs":8944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-4ac81f68eadb0eddd0f1","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"isolated term within the same glossary IS shown in the Relations Graph by default","durationMs":8616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-4d3660629680261514e8","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"a parentOf edge exists between a parent term and its child in the Relations Graph","durationMs":8989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-5ea646b31bc57f6ceb8d","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"cross-glossary related term has an edge to the term in the viewed glossary","durationMs":8393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-752887931640b36a1b6b","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"Relations Graph tab renders the ontology explorer for a glossary with related terms","durationMs":9651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-8a81ed58944bf0102167","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"search in the Relations Graph filters to the matching node and its neighbours","durationMs":9235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-8d45c5f6a1ebda6dab15","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"term from an unrelated glossary is NOT shown in the Relations Graph","durationMs":9951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-9f75d86f777103f3730b","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"global filter toolbar is NOT shown in glossary scope","durationMs":8689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-a02781b14c6c4a0560a7","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"nested child term appears as a node in the glossary Relations Graph","durationMs":9598,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-a6f0673f9f3ec464a1a6","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"related terms from the glossary appear as nodes in the Relations Graph","durationMs":9186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-b7bbd38343ffe4ec95b3","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"an edge with the correct relationType exists between the related terms","durationMs":9074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-c46a41f4509f43b3c19a","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"cross-glossary related term appears as a node in the glossary Relations Graph","durationMs":8665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6b41c0bfb13cd7424837-d0894452615bac35da92","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraph.spec.ts","title":"cross-glossary term related to a nested child appears as a node in the glossary Relations Graph","durationMs":8571,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-02a9f1f5bc2bb9cb4d3f","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"My Data filter should show only owned entity activity","durationMs":8822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-130907f22f9a222f9f78","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"entity tab badge totals conversations, activity and tasks","durationMs":6710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-218075417344154ad45d","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"creating task should immediately appear in entity feed","durationMs":12041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-25c0ae0e67cbf704171c","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should show task in activity feed widget","durationMs":11787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-2648a94a2a8068a286c0","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"Activity Feed widget filters should switch between All Activity, My Data, and Following","durationMs":11541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-2fa4a8b630563d1be0fd","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"activity feed tab should show task count badge","durationMs":9759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-495fa33b459cbee9a0c6","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should show description updates in activity feed","durationMs":8896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-4f7c55b775868a3cf15c","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should have clickable task links that navigate correctly","durationMs":9278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-637ba584c4c13c1ec867","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"assignee should see assigned tasks in Tasks filter","durationMs":9155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-64e4c0054be5e225e0a5","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should display activity feed tab on entity page","durationMs":7398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-7183d383884d0c16793d","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should toggle between All and Tasks in entity activity feed","durationMs":10872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-92037e70c926a2ee43db","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"updating entity should create activity in feed","durationMs":8340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-9a99af13dea9f806d0d2","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"clicking activity feed tab should show feed and tasks","durationMs":7660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-bb14751acfa82ef92787","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"entity task filters should request open, closed, and mentions views","durationMs":10017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-c0fb4e74dc25f2e9f4e2","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"All and Tasks panels each show their own seeded items","durationMs":7522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-c8ec51c30cc18befab0d","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"should display activity feed widget on home page","durationMs":11580,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-e0b6d76a34064a97d805","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"Tasks filter should show only tasks","durationMs":8568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-fb6c38e52d91ff7a7ad1","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"following an entity should show its activity in Following filter","durationMs":8937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6cc7ad72eff3575197d7-fef19851f322651f1034","project":"chromium","file":"Features/Tasks/ActivityFeed.spec.ts","title":"All filter should show all activity","durationMs":10055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-69ef15cf8752da40f2d0","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify table search with special characters as handled","durationMs":20697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-b2d9d31b73fb2eb60e67","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify domain platform view","durationMs":6368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-b6a72c0554063dbc917e","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify platform view switching","durationMs":4856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6ced39ffec1acbbdd0e0-f85c9a5692010b56850f","project":"Basic","file":"Pages/Lineage/PlatformLineage.spec.ts","title":"Verify service platform view","durationMs":7404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d0fae529d1edab6e47b-b7e0c7af5d202caa41de","project":"DomainIsolation","file":"Features/DomainIsolation/DomainIncidentIsolation.spec.ts","title":"admin sees incidents from every domain","durationMs":7128,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d0fae529d1edab6e47b-fa37465f7517bf023bcf","project":"DomainIsolation","file":"Features/DomainIsolation/DomainIncidentIsolation.spec.ts","title":"user without a domain cannot see incidents belonging to a domain","durationMs":7767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-55e0b895422ddbcfcabe","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"should render the service listing page","durationMs":6251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-9661a49fa27744bd3143","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"should send wildcard query_filter on name and displayName when searching","durationMs":4627,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-b799453e514626e37076","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"service listing pages should use the correct search index for search","durationMs":18797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d35fb77b389ad17aaae-d7a58326fcfc4813852f","project":"chromium","file":"Pages/ServiceListing.spec.ts","title":"should find service when searching by displayName","durationMs":4278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-0e8840821fdd9591c08c","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create glossary term via row action (+) button","durationMs":9168,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-0f76b5d2ce502173a58b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Add and Remove Assets","durationMs":20690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-1bbd2c7b10a1630cab95","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify Glossary Term Deny Permission","durationMs":14311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-1f0f00122ded66da4ee5","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - multiple deletes all succeed","durationMs":11910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-24070596b72f9abe027d","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Column dropdown drag-and-drop functionality for Glossary Terms table","durationMs":8157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-250c033f5b7545226c98","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify Glossary Deny Permission","durationMs":10001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-2e2d5dcd6abb731f559b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Add Glossary Term inside another Term","durationMs":11323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-2fc1b4844bf346a49db7","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - WebSocket failure triggers recovery","durationMs":9939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-324008c43bb03cdc58ba","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify asset selection modal filters are shown upfront","durationMs":24960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-33111021a8e04784f97b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary & terms creation for reviewer as team","durationMs":40952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-33c9092459c128f840b0","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create glossary, change language to Dutch, and delete glossary","durationMs":18502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-39d846e87c6473185980","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary Term Update in Glossary Page should persist tree","durationMs":8305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-3ea56dcec13cfd0cb14b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary & terms creation for reviewer as user","durationMs":39582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-3eb3ff25dcb18cef8261","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Check for duplicate Glossary Term with Glossary having dot in name","durationMs":9387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-4bb9baa9d5c21cfdbf9f","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Verify Expand All For Nested Glossary Terms","durationMs":8923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-5a610d0a9eb613d67238","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Request tags for Glossary","durationMs":31784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-5a931a565618611e9157","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary creation with domain selection","durationMs":11501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-671802bb890487e49835","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - multiple deletes with mixed results","durationMs":15499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-72c1dc9f8709dfe8230e","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Cancel glossary delete operation","durationMs":9181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-7fe26832ef78f2917c1f","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Update Glossary and Glossary Term","durationMs":32430,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-81dc43d85a215ab8b165","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Delete Glossary and Glossary Term using Delete Modal","durationMs":16784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-857ca83e7559df6d36e0","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Glossary Terms Table Status filtering","durationMs":7096,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-8cb20faba23be878c6dc","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Request description task for Glossary Term","durationMs":13073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-8d87915326d11af4cefc","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create term with references during creation","durationMs":9304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-8e7d0dee5127a7499a42","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Rename Glossary Term and verify assets","durationMs":49110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a15003491770da48495f","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Cancel glossary term delete operation","durationMs":12354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a19e65f930c31ed62640","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Async Delete - single delete success","durationMs":14060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a32aed4937ee6208029e","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Change glossary term hierarchy using menu options across glossary","durationMs":21061,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a6cb7e10eba2ff9cdce7","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Column selection and visibility for Glossary Terms table","durationMs":21094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-a710897c7d486fbb4486","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Drag and Drop Glossary Term","durationMs":17553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-b9921bc7a75085d79508","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Change glossary term hierarchy using menu options","durationMs":10064,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-c748c4ce0e07a48a2b83","project":"chromium","file":"Pages/Glossary.spec.ts","title":"should handle glossary after description is deleted","durationMs":10265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-c7d137db2fa513ee316c","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Approve and reject glossary term from Glossary Listing","durationMs":27215,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-cf340c60c05ff8f90b01","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Drag and Drop Glossary Term Approved Terms having reviewer","durationMs":14086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d0d74d1eebd0e9ec349b","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Update glossary display name via rename modal","durationMs":9220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d35fc5f3b1a45324e336","project":"chromium","file":"Pages/Glossary.spec.ts","title":"should handle glossary term after description is deleted","durationMs":10455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d889c49c19047a815116","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create glossary with all optional fields (tags, owners, reviewers, domain)","durationMs":18159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-d9372e9478961f7918e0","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Request description task for Glossary","durationMs":12484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-dae7065ebeb1f43dad4e","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Add, Update and Verify Data Glossary Term","durationMs":13783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-e37cc1dc3d2ab84a987a","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Update glossary term display name via edit modal","durationMs":8411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-e4264aa2f6b7d75c5586","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create term with synonyms during creation","durationMs":9250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-f62b0df349afb243d895","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Create term with related terms, tags and owners during creation","durationMs":12671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-fc77f94d1b063e3741af","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Check for duplicate Glossary Term","durationMs":10499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-fd3cdcb2fa734b3b5501","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Term should stay approved when changes made by reviewer","durationMs":30009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6d3641a6caa36e9cc3cb-fe267b81be07d2c8b0d4","project":"chromium","file":"Pages/Glossary.spec.ts","title":"Assign Glossary Term to entity and check assets","durationMs":17554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-15e7a6655993cf472f71","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"FAILED import job shows error styling and dismiss button","durationMs":5333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-2c8ea2ed5e902ca58987","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"can cancel a running job from the tray","durationMs":5475,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-50a6a22f1167181c90a0","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows Download button for a completed export job","durationMs":6053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-5dc1fd8ecf1e78491cab","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"multiple jobs co-exist in the tray","durationMs":5658,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-74fc8dff0080e7079d56","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"auto-opens the tray for download when the poll completes it, minimised and multi-pod","durationMs":8572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-abf606d9a6ab5b15ca5a","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"Clear completed removes all terminal jobs and hides the tray","durationMs":5819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-d3918016bff34a387cf5","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"reaches Completed by polling, without a websocket event","durationMs":9498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-d498b16902150f020cf6","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows a lineage export job in the tray","durationMs":5327,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-e8bb44e083b6c9008b89","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows a running export job and its progress text","durationMs":7378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-f4e002a0ef30f8649c0c","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"shows an import job in the tray","durationMs":5844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6daebe33bb608edafce7-fd7fc1a370ea9ae52400","project":"chromium","file":"Features/CsvJobsTray.spec.ts","title":"dismiss button removes a completed import job and hides the tray","durationMs":5290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f0590c0231406c6c5a0-022fa2831b7edf55d8f0","project":"chromium","file":"Features/TierDropdown.spec.ts","title":"should show tier again after re-enabling disabled tag","durationMs":13876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f0590c0231406c6c5a0-26e804d4f6811de98994","project":"chromium","file":"Features/TierDropdown.spec.ts","title":"should show enabled tier tag in dropdown","durationMs":9081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f0590c0231406c6c5a0-468f85de81c9afec7bfc","project":"chromium","file":"Features/TierDropdown.spec.ts","title":"should NOT show disabled tier tag in dropdown","durationMs":9274,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-00204bf3d420e3c1362f","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Any_In","durationMs":27812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-0a941e8cff652ad32a0b","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is Not","durationMs":23433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-0ddc285347b228f85206","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is Not","durationMs":25569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-150515a15c5e4f366b88","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Less than <","durationMs":22345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-171540945652ea1c4669","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is_Not","durationMs":30402,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-236779457b0d1656b12c","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Less than equal <=","durationMs":21290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-23f7096c73ed3b03ea31","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Greater than >","durationMs":21542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-24f53ec25d5a2ae1b8f0","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Not_In","durationMs":22477,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-293d5150c418db58f951","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is_Set","durationMs":20831,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-371b66dc6824959e3445","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Any_In","durationMs":26469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-401cf2233b89cc98bc05","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is_Not_Set","durationMs":21414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-45ea20bc75c5c6030bd0","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is","durationMs":22209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-4f736eab9ff01cba8174","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Not_In","durationMs":32022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-5837ce00a1f636832c29","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Is Not","durationMs":22793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-69de011bc32436fd94f7","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Is","durationMs":25453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-6b295db5f949a01405ee","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Contains","durationMs":23422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-6b58e52550f8b1fa9dd5","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is_Set","durationMs":24817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-71cc9056833b064bdb3d","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate semantics fields","durationMs":12360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-728dc344e20efb9729b9","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is","durationMs":25987,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-761e52994497d5d1e897","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Any_In","durationMs":22554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-76b8bbfc4abe6888a560","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is_Set","durationMs":23478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-77dab837438ee562ad3f","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Is","durationMs":22869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-82a0d03adf940fb889c8","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Greater than","durationMs":17782,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-8ff70b2979cf0715ab91","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is_Not_Set","durationMs":22697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-9cfe99b98caf05fddac1","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Is_Not_Set","durationMs":23863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-a04ece8b45d647faeb43","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Not_Between","durationMs":19247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b00a58585fdb947f1ae7","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Less than Equal","durationMs":16018,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b2713e50d8d09a875c66","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Not_In","durationMs":20816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b2f8faabd3ce8bd6fe9c","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is_Set","durationMs":23453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b376a2ffda8ffaaf70fe","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Not Contains","durationMs":22714,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-b5b5798172033fc42f0c","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Between","durationMs":18079,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-c71827d0e1bc939645d1","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is","durationMs":24760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-c982caaa50eb72dbae85","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Is_Not_Set","durationMs":23896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-dcee5e388fad4727090e","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Description Rule Is_Set","durationMs":24793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-eb537c1fbd594f3b40b2","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Greater Than Equal","durationMs":17671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-eca97bb8f81b98afc82d","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Owner Rule Not_In","durationMs":29481,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-f218a044c71b677a3ff1","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate UpdatedOn Rule Less than","durationMs":18408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-f6bec3efb1ea171da67b","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DataProduct Rule Is_Not_Set","durationMs":18981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-fa4ea30a932d11c1087f","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate DisplayName Rule Any_In","durationMs":20630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-fd19177a0b37dd31d6a6","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Domain Rule Is Not","durationMs":22404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6f9684bba76ed22e1a8c-ff5f445d50fd4aca74f2","project":"chromium","file":"Pages/DataContractsSemanticRules.spec.ts","title":"Validate Entity Version Greater than equal >=","durationMs":21194,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-0dee03971527229cf2b4","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"Copy column link should have valid URL format","durationMs":13984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-19f3266acdd6cf2bbe8a","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"schema table test","durationMs":65030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-55dc5f002f5389dd54c6","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"Copy column link button should copy the column URL to clipboard","durationMs":23682,"attempts":1,"retries":0,"outcome":"expected"},{"id":"6faed9784dd78915caa3-d9fd88aeb278a136b4b9","project":"chromium","file":"Flow/SchemaTable.spec.ts","title":"Copy nested column link should include full hierarchical path","durationMs":29938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-10870a5ff304ba82d6e7","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Single Filter Alert","durationMs":40520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-40be061349021020fcd0","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Multiple Filters Alert","durationMs":37027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-5f357d0a8f543a66ce84","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Task source alert","durationMs":20640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-624bf59d0b99f47aba5f","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"destination should work properly","durationMs":11484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-a5110db8fbca70dbfb81","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Conversation source alert","durationMs":22577,"attempts":1,"retries":0,"outcome":"expected"},{"id":"702cf19111f276bfa648-df4c09990358fadaa853","project":"chromium","file":"Flow/NotificationAlerts.spec.ts","title":"Alert operations for a user with and without permissions","durationMs":61361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-089ac879c8a1bf48e14e","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":6046,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-2123239773951a420d08","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":8424,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-607ce3ae26140d8d5214","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":9040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-a9296610d946263c61d6","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":5808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-aec4f097f30f2f6f3d5b","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":6621,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-c8f9791788c2c6562291","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":8560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7056daffd6e7ec39475f-ebee8e531238cd9a1ce1","project":"chromium","file":"Features/LandingPageWidgets/DataAssetsWidget.spec.ts","title":"Check Data Asset and Service Filtration","durationMs":8911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-1791da577014ae152bcb","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Export maintains hierarchy structure in CSV","durationMs":9950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-3d16c444f1c9c329db61","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Glossary CSV import rejects unknown relation type","durationMs":19122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-493528214858d92fd7a5","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Glossary CSV import preserves typed relations","durationMs":40584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-679f70fff3c550677e9d","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Import partial success - some terms pass, some fail","durationMs":10018,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-8ea351f3c7814ef9e3d9","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Export large glossary with many terms","durationMs":14230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-9ffaf4d7a82a18e1f940","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Import validation - missing required fields","durationMs":9866,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-a2b1b1d4e5d988307f70","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Glossary Bulk Import Export","durationMs":135241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-cee2d57c047fe3642660","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Check for Circular Reference in Glossary Import","durationMs":50519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"706a63ec57eceb58c5a5-fdb534fec42101d87676","project":"ImportExport","file":"Pages/GlossaryImportExport.spec.ts","title":"Import validation - invalid parent reference","durationMs":10256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-00dc2bfe21cad2f9df2a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":17981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-05419e782211d9d1de2a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":12164,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0734f3c96e7f54ce6c6a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-07b4ea279b562bfe5f3e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":12542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-098aa2e4c7da1b046465","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":18005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-099a8b05c67e2846d078","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-09ad004942c23feecedd","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":12099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0af5b5347fe1881e8bd8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":17343,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0be37046a03f74efd994","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-0f1f2d5e8d4043861466","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":16036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-104abf45b88605c51ba2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":23804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1233936a260349b16c83","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":16190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-13079334487a6cadd03d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":15498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-13add27af4975daea758","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":15900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-13e4d9f5ee7a05fd7ba3","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1505cf28cd885f4777a4","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":11214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-159605a397828a93f493","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":10010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-15b85784d9980e662aac","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-171caaaaadb1abdde4e8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":18781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-179a76d9663cf8294023","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1dc7f85d16a2b90bb9b5","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"DisplayName edit for child entities should not be allowed","durationMs":15376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-1fce82f531f7060e9a80","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":13670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-207d899430f83bd70026","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":16952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-25d1ff90961691a28f62","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2615b128abf51a2b722e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":20420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2846038d5787a94b6221","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":12773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-28b4f6bcc80a1469e2a6","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":18531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2b2b7ce855f4c94504cf","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-2fd5d612894f1dc087d2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15199,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-313f7934124ca3a6ec1e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":13401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-31cac5cc40a390e2ada4","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":19214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-32c128143c6af1999483","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":9305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-35d5a3a5220f9b82914e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-3674479f1e1d92294596","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":14797,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-368e75ff19cf7240c335","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-397071d12f931d852590","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":19375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-3cf9455e51dd60f34c9c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":18275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-3d5a8b6ded213476ccb9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":22900,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-40e20c32f73b2f1e33db","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-42ed38552b351ed6c93d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":17156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4349f30cfdd7afe581f0","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":12574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-451b7a6d09e89e02b130","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4a795e20925174b2ebbf","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":12958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4e2068c8100414367241","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":13192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-4f77ec64b3961ae26287","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":13999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-55df040662d878f36358","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":13293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-57c6d7653390fa73f1af","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":10332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-58090467bafe4832be37","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":16816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5bbca01e71559b6833a9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":18567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5bbd17233fbb970090c0","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":18716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5e7dd90d5176a4da519b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":17964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5e913694e9bf25d7a0da","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":10512,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-5fe9f87da680252d5de7","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":12157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-62a7ab20daeb7fd9d75a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":11556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-63ebcb256954060a40e2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":19153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-64c9dec746918237cfc9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":15207,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-665195c1bcf8ae7d6dc5","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":13113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-66b9bd452e0e1785a5d7","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":20421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6a354d7e70e5fc359cec","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6ce1ce593dc1604c0d8c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":14076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6e073fa1c99cfcd9614e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":21581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-6e3155a8180681dce32f","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":15383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-741ba010d8001a9fd629","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":16432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-764889744082814f83b9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":27973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-764f83da00cc0a2bc041","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-77d5fb9465e2342072eb","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":10843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7954ae16633a0595e250","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7c7fe35a843c7aa4c1e7","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":18807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7d8680096167e16dee4e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7ee85a0df418f4685ece","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-7fe4517367fdf10aeb2e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":21873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-80ea803681cb43d239a8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":16022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-811ff9238e656b089a1e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"DisplayName edit for child entities should not be allowed","durationMs":15451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-84d793627d1430a44c63","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":13080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-871014d136a919f8ddac","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-89be5e692516eb5ace57","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":11335,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-8d75a1daebe16b4ad248","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":14652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-8da24219a87618238385","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":22923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-8f18317ce2a8dedc296b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":15507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-918beeac313c2d5b006f","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":12600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-92203d502969bf810290","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":12221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-92af334a81058c115c6d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":21398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-97043d7c0e95c7a9b538","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":16579,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9b061925110794967937","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9b0a261339c941b15ef9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9b4e7d5a9d9be16b81a2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":15056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-9f8fe0076ba3960c5ed6","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":10241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a110445f4bb0e5a9249b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":14029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a239abd986ca12d3b089","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":10893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a4b590de5fc7b09886b5","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":9999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a5cb67bbd403c122b448","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a944d4b83c40d64ad528","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-a9fcd65f05b20919cc7b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12096,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ac9d289deb13e7de0d5b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":13333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ac9dd7137941fa967739","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":21947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-afc588b98fc64a39d3cf","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b1e7b2c2ce671c777b00","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":11561,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b47625127ce7c655c09a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":11373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b524c69bb71c565d2b58","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":17634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b65beaa3001a816f6cae","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b6826b78d1ecfa486857","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":13838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-b76587fc8ad7db226e8b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-bb1ec5293b3152b029eb","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":10932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-bb31d3b1cdc3a33b4aee","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":18596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-bc218ae35c432f47e3b2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c2ace8fd6a3946f909d1","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":17965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c428f095b19e7cf46395","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":20523,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c7722802523210206b72","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-c9e3527162de0406d5c1","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":13535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-cbc65211b511edc84eef","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":16031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ccb5da6fbf33b4fc343e","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":17352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-cd8b6feff9b29b140db3","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":16899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-cef54b49eb30d934016a","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":13180,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d41355c268d0640de0b2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":16405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d45d573707423b4333c8","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":25108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d6a7c54426412861c898","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":15208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-d6dc2c7f4c00079cdea2","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-da2efd47495633f62256","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":12565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-db55f0ef1567c8eb8dc9","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-dc91d3dc044f44f23f34","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-dd6d3dcd3b2bec3dec99","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":11432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-de0da7c7009cd8139681","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":12680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-dee80a2bdb8cdeaae997","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-df0cc209a2c7e2be249d","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":14331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e0e7f3e88e2fe516e148","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":14369,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e1150544251e50df2ef4","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":18228,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e1f548ad3eb98feedc9c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":18608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e2b289727fffe1359476","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":11578,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e3bf544a74276372dc76","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Follow & Un-follow entity","durationMs":25265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e4aa4620bb993ec7c6b0","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":15730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e4cb394bd3ed4d377f45","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20632,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e5368f1856ed3179634b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove","durationMs":20105,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e54846b3978101495d15","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":18816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e627170fb572721ecd2c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tier Add, Update and Remove","durationMs":14376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-e6683721b86aac6fa89c","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":16022,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ed316521ba0802cb2f9f","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":20208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ed48b466904dfd246b36","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15345,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-f37f7f8af59b042bd1fc","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"No edit owner permission","durationMs":16551,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-f8ce0fccb9088a10ed3b","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":15284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-f8d220191366b9f7beef","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":14318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-fbcfe7b1efb2c8a34834","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"UpVote & DownVote entity","durationMs":13348,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-fd8fee043148b3cd8527","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Update description","durationMs":16012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"719a1c77382793645da8-ffc56bac94bcaaa595e6","project":"chromium","file":"Pages/EntityDataConsumer.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"71f3811ba836bd5d2426-0cef81448f669267012e","project":"chromium","file":"Pages/TestSuite.spec.ts","title":"Test suite tab switching keeps active bundle suite data after stale table suite response","durationMs":8413,"attempts":1,"retries":0,"outcome":"expected"},{"id":"71f3811ba836bd5d2426-89887dbf3e98dfa2e74b","project":"Ingestion","file":"Pages/TestSuite.spec.ts","title":"Logical TestSuite","durationMs":22478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-01d1dce9230b25ea2505","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Metric in recently viewed","durationMs":12607,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-13b7a204ff200c336897","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check SearchIndex in recently viewed","durationMs":12536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-24032ed075b8c41897c3","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Dashboard in recently viewed","durationMs":12968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-2586c2bf4dfb82bef75c","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Store Procedure in recently viewed","durationMs":13371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-2f3fd80ebc9a9ce7ed65","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Container in recently viewed","durationMs":13550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-47c55d1985c5945153c6","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Table in recently viewed","durationMs":14122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-5618482fdd645a26b706","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check ApiEndpoint in recently viewed","durationMs":12458,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-5f1972c128aabaab7ad8","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Pipeline in recently viewed","durationMs":13242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-9421df08f5c6615cda5d","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check MlModel in recently viewed","durationMs":13594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-9929792040eb7c5e6031","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check Topic in recently viewed","durationMs":12356,"attempts":1,"retries":0,"outcome":"expected"},{"id":"721771e7f27c31f3ac50-f40caac58f9f81e19025","project":"chromium","file":"Features/RecentlyViewed.spec.ts","title":"Check DashboardDataModel in recently viewed","durationMs":13208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-083dec8015a3843e7cd2","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify cycle lineage should be handled properly","durationMs":9009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-32f8b0ccd2482bf59ee5","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify multiple non-platform layers can be active simultaneously","durationMs":9641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-420eb75a7ad41f3f161d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"grays out non-traced node-to-node edges when a node is selected","durationMs":10964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-590c0cccca1fd8b28312","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify edit mode with edge operations","durationMs":9427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-6c7e50b5a927cef3105e","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Column-level edge deletion persists across a page refresh","durationMs":10291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-7887942fb4b1a81cf4f2","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify function data in edge drawer","durationMs":27730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-893bf3a839f3d965551a","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"highlights traced node-to-node edges when a node is selected","durationMs":13391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-8cbc1d5f3df767e1a30c","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Node-to-node edge deletion persists across a page refresh","durationMs":13913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-993dfeaec0379736db1d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Node edge tracing state responds to column selection and pane click","durationMs":15493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-a18e7ad071eeb5841602","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"highlights traced column-to-column edges when a column is selected","durationMs":13597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-aaffec18ebc6fd24d065","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"hides non-traced column-to-column edges when a column is selected","durationMs":12244,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-af9a6883f6bfe2044127","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify node panel opens on click","durationMs":36593,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"72d52555450cf448e344-bcda310ae42da5f9981d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"grays out node-to-node edges when a column is selected","durationMs":9963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-c817ed50e2845dccca7b","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify node full path is present as breadcrumb in lineage node","durationMs":12425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-d3c613365a48705e9f08","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify edge click opens edge drawer","durationMs":8190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-f060811fb20415a34c46","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"Verify edge delete button in drawer","durationMs":11033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"72d52555450cf448e344-fd9777143ac55c7ff05d","project":"Basic","file":"Pages/Lineage/LineageInteraction.spec.ts","title":"hides column-to-column edges when a node is selected","durationMs":12334,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-22575bd0187b55901bec","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should add and accept a requested api endpoint request schema field description","durationMs":22734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-65c54cf0e0efe55e1890","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should edit and accept a suggested table column description","durationMs":23585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-80f4fe7e66749741bb2f","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should decline a suggested container column description","durationMs":22694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-93993cb9c92e1cd67d6b","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should add and accept a requested topic schema field description","durationMs":23159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-be064f2bb0d81c98522c","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should add and accept a requested table description","durationMs":24267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-df608fd0fde9ffb3dcd8","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should edit and accept a suggested api endpoint response schema field description","durationMs":22498,"attempts":1,"retries":0,"outcome":"expected"},{"id":"73d31798764c6937a787-fa64ee029c7d508dae0f","project":"Basic","file":"Features/DescriptionSuggestion.spec.ts","title":"should decline a requested api endpoint request schema field description","durationMs":23992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-04adac79fce387536d5a","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should replace focused documentation when a new field is focused","durationMs":8868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-136d19e6f39cd1065416","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render code blocks inside pre > code, not as raw text","durationMs":8222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-67847c8372f8e027537e","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render image in Mssql doc panel","durationMs":7635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-7df729b7f0f4b0f06d1a","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render links that open in a new tab","durationMs":7611,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-8384bb8c4d3d5c6fceed","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should auto-focus service name input and show name docs when entering step 2","durationMs":7879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-858dc1ba7e867d341974","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show service name docs without requirements when service name is focused","durationMs":8835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-a353893f87d30e844b91","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should update panel when a oneOf select field is focused","durationMs":7908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-a8c66091c37ee0517c7b","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show section docs without a field fallback for fields with no markdown docs","durationMs":7956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-aa3c42f2b54ccca226aa","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should copy code block content to clipboard and show copied tooltip","durationMs":7744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-b605c6fbbd9a2fc001d4","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render headings not raw markdown","durationMs":7991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-cb0cb27b27b2eef3e924","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should render admonition blocks with correct class","durationMs":8699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-cc58195c92559dedbdad","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show general docs when no field is focused","durationMs":7833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-dfb092691560c4c5f613","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should load the correct doc file for the selected service type","durationMs":7956,"attempts":1,"retries":0,"outcome":"expected"},{"id":"741dcf110393f398e3fc-fa45cd6f9878dc6c4cbb","project":"Basic","file":"Flow/ServiceDocPanel.spec.ts","title":"should show field documentation when the corresponding form field is focused","durationMs":8072,"attempts":1,"retries":0,"outcome":"expected"},{"id":"75e196e842ebd82840f4-f9512e6353ddfe34a4a3","project":"search-nightly","file":"Search/SearchNightly.spec.ts","title":"should load global search suggestions for sample data query","durationMs":3899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-0769921c525897eff595","project":"chromium","file":"Features/Container.spec.ts","title":"parent Deleted toggle reveals the deleted grandchild — its actual direct parent","durationMs":3971,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-3913d4f58462a7a3df4e","project":"chromium","file":"Features/Container.spec.ts","title":"Copy column link should have valid URL format","durationMs":13359,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-42b547ec6ff262456209","project":"chromium","file":"Features/Container.spec.ts","title":"should correctly load, display breadcrumbs, and navigate deeply nested containers","durationMs":8165,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-45da7c2e7258e334c204","project":"chromium","file":"Features/Container.spec.ts","title":"Container page children pagination","durationMs":9532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-4f996668155242b716c3","project":"chromium","file":"Features/Container.spec.ts","title":"Container page should show Schema and Children count","durationMs":9966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-6d000f93734bfa3641f4","project":"chromium","file":"Features/Container.spec.ts","title":"Deleted toggle reveals and hides soft-deleted children","durationMs":3884,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-74d2687b81ec34d1df25","project":"chromium","file":"Features/Container.spec.ts","title":"Copy column link button should copy the column URL to clipboard","durationMs":8773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-814af37fb8584f11c87e","project":"chromium","file":"Features/Container.spec.ts","title":"grandparent Deleted toggle returns empty — deleted grandchild does not bubble up","durationMs":5893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-99a5693eb43b1b956e3f","project":"chromium","file":"Features/Container.spec.ts","title":"search + Deleted toggle compose to find soft-deleted children by name","durationMs":5104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-b25813e92d687c1ac664","project":"chromium","file":"Features/Container.spec.ts","title":"auto-collapses the breadcrumb into an overflow menu on a narrow viewport","durationMs":7355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-db68482bfca9911d3811","project":"chromium","file":"Features/Container.spec.ts","title":"expand / collapse should not appear after updating nested fields for container","durationMs":15006,"attempts":1,"retries":0,"outcome":"expected"},{"id":"769d362cfe237d3b404b-dd86738ce9af0c2bd293","project":"chromium","file":"Features/Container.spec.ts","title":"search filters direct children only — sibling subtree never leaks","durationMs":6705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-46773b2126fe5bb8eb31","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create OwnershipUpdate task for Pipeline","durationMs":1009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-4a8117316e1eb5a1d1fa","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create TierUpdate task for Pipeline","durationMs":307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-7fd5240fe33065f768e3","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create and approve pipeline task description update","durationMs":483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-bd22bafa09fe5baaf2c2","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create DomainUpdate task for Pipeline","durationMs":470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"77d7aa39b50e81c9c70d-c8dccd6e61c2e9dea7de","project":"chromium","file":"Features/Tasks/TaskPipelineEntity.spec.ts","title":"should create and approve entity-level description task for Pipeline","durationMs":438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78095862efae8cf216ee-6119e7b35fd37214afd1","project":"Ingestion","file":"Pages/IngestionLogStreamLive.spec.ts","title":"Live logs arrive over SSE while the agent runs, with no polling","durationMs":33157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-07402fbc3d954dac78b8","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"searching for a term shows it and its neighbours","durationMs":2100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-092270212c19cdaa4908","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"unconstrained built-in relations omit endpoint labels","durationMs":1950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-0fd42fa09b4645db923a","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"searching for a non-existent term shows the empty state","durationMs":2437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-11fd427817bd9d655f42","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"cardinality map survives a Data-to-Model round trip","durationMs":2133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-2db29163257de252b256","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"Data mode shows an empty state when the glossary has no assets","durationMs":2085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-37cd6e390ea42415c6e5","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"switching back from Tree to Graph restores the graph and stats","durationMs":2024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-3a301091329822c5d151","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"custom ONE_TO_MANY relation shows \"1\" at source and \"M\" at target","durationMs":1772,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-407235e749dda8ee080a","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"returning to Model mode restores graph controls","durationMs":2176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-4eccf3be34c45254b555","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"all three term nodes have canvas positions","durationMs":2074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-6d49d78bfe49b343cf22","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"Tree surface renders the glossary hierarchy","durationMs":1856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-b03f0a71701825a04fd3","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"stats show 3 terms and 4 relations","durationMs":2189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-bb1c308761249a94185c","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"concept inspector exposes the full-details action","durationMs":2016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-ddb75b6bd2bd20a31525","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"graph edges contain all four expected relation types","durationMs":1982,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-dfd025e99a6dc28bd7b3","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"graph renders without empty or error state","durationMs":2161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"78853c2eb541e6f033ba-f1f2b8e2b3a7545b4790","project":"chromium","file":"Features/OntologyStudioE2E.spec.ts","title":"clicking a node opens the concept inspector","durationMs":1937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-022759ec864b56b71bcc","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Copy domain FQN to clipboard","durationMs":7232,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-0ebd54efbc2b2b155beb","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Add expert to domain via UI","durationMs":10497,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-1f1c563e90bcce9f6d8b","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete data product via UI","durationMs":6582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-2449dd2855d6489495e5","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete domain with assets removes domain from assets","durationMs":5504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-28a3b2486df912d34410","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Clear domain selection returns to All Domains","durationMs":5948,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-2a56fa3766116e1c5585","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Add owner to domain via UI","durationMs":11003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-3b3349f8197353baba62","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Add owner to data product via UI","durationMs":9095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-3c0793e4d0a02a034dd6","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Domain description required validation","durationMs":4859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-572e07b57107a81c8a5a","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Domain name validation - special characters","durationMs":4598,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-8257af9327d0aecb1a57","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Navigate from data product to parent domain","durationMs":8122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-94706ce6c0a223ba7d9c","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Select domain from global dropdown filters explore","durationMs":5555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-95eb86ffe8e67da8357f","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Search assets within domain","durationMs":8231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-986797853ac5b5f33e0e","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Navigate from subdomain to parent domain via breadcrumb","durationMs":6677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-a3eec08a270058e9c4a8","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Edit domain style - change icon URL","durationMs":9353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-ac6bba54da09716d0bb1","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete domain with subdomains shows warning","durationMs":8115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-ae62dad6a8513b600bd8","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Remove owner from domain via UI","durationMs":7822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-c792ca79ac2754e7a040","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Rename data product via UI","durationMs":7374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-e665fdbd2e91e08e4f8b","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Rename subdomain via UI","durationMs":8806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-e67dcb1bdd80adb3ef5f","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Delete subdomain via UI","durationMs":9567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c01e63d87f0aa6b4172-fe4f73c64fe8c8e5de31","project":"chromium","file":"Pages/DomainUIInteractions.spec.ts","title":"Domain name validation - max length","durationMs":5076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c313e060173ac894b2b-403f9052a3a13d25ac40","project":"chromium","file":"Flow/AddRoleAndAssignToUser.spec.ts","title":"Verify assigned role to new user","durationMs":6474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c313e060173ac894b2b-cad45ddec1ffc014868e","project":"chromium","file":"Flow/AddRoleAndAssignToUser.spec.ts","title":"Create role","durationMs":6524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c313e060173ac894b2b-ee14ce47b05f65e1ffd4","project":"chromium","file":"Flow/AddRoleAndAssignToUser.spec.ts","title":"Create new user and assign new role to him","durationMs":7830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-5d577d037f46e4e6ac12","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should render connector forms that previously stalled at loading","durationMs":13651,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-bff0435e79efac0348cc","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should scroll the form when the wheel is over the blank margin beside it","durationMs":7903,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-d2f910cd545265e60c99","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should clear inactive Snowflake auth fields before test connection and unlock ingestion filters","durationMs":13034,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c5ee51f50dc4397de9c-d9a6d1d97ea16fafc5c8","project":"chromium","file":"Flow/ConnectionConfigLayout.spec.ts","title":"should align nested sample data storage config fields without overlap","durationMs":10784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-00c5931044e86cac81ab","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should accept a valid name with allowed special characters","durationMs":4817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0198f50c773eac76637b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for mlmodel in right panel","durationMs":12134,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-046fb43e97de2c99aded","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on mlmodel","durationMs":19379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0586bf3c032e2e35530a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for table in right panel","durationMs":7936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-06fcc5757ec84237d9d4","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on pipeline","durationMs":15185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-073ad5c7df0d928319e5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Markdown","durationMs":17339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-090b772ba3caf2d12879","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-099f20268d1f7b48745e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on dashboard","durationMs":23574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0b461a5e0578cd2efd31","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on container","durationMs":14267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0cb4d8f7a9199c942503","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for dashboardDataModel in right panel","durationMs":12597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0cc0177e680651493e9b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on database","durationMs":17626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0d1c5ed8b0999aa6e657","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time Interval","durationMs":18044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0d1e7593a663f34a4167","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Duration","durationMs":16911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0dbdcff683eb513dc0f5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should accept valid http and https URLs","durationMs":7103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-0ede02e520a7dc955605","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Number","durationMs":17816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-11f7e608c623dfca5f06","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for topic in right panel","durationMs":12606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-13131035a68d36358766","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a tilde","durationMs":5461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-13c94bba599eb95dce34","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Timestamp","durationMs":17863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-13e7ba4bc2cad9b1de63","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for storedProcedure in right panel","durationMs":10388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-144b42f1d0bcd87467bb","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for chart in right panel","durationMs":9141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-150a7f419a6502d5f7af","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on glossaryTerm","durationMs":19093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1542edf5a447db147b2c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Create custom property and configure search for Pipeline","durationMs":20639,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1661fababed9adc53f9d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for container in right panel","durationMs":9060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-16aa58907a6fdfcaf258","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a colon","durationMs":5137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1928de880af6bb1217b1","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":16864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-1b3f3bdd4a95d12e5782","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Email CP with all operators","durationMs":30254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-20ec70d5fe0c22fab8a3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should display URL when no display text is provided","durationMs":6687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-215123aafd70cf8361ec","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for searchIndex in right panel","durationMs":11074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-22c1d84db9283bdded31","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for topic in right panel","durationMs":12163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-234372fa7573d8422663","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for glossaryTerm in right panel","durationMs":10466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-24855e52e738b6d8cc55","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Duration: advanced search equalTo and Contains operators","durationMs":13306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2666fae5eaf8b524f8b2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for apiEndpoint in right panel","durationMs":12862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-26a002b822c0a4f22189","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a backslash","durationMs":5375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-284272a57881394530a8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for chart in right panel","durationMs":9679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b3f1ca73d2b19cd7829","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Integer CP with all operators","durationMs":32391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b44204ae297960da4ca","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for apiEndpoint in right panel","durationMs":14385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b958f7c7ead420a53cf","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set string custom property on column and verify in UI","durationMs":15721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2b9e2f2bf4b05988942e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Integer","durationMs":17143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-2dc55bac67402b99ea1c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-33ead8586aacbd1e7514","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String CP with all operators","durationMs":33357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-36c2e3f98f9691386383","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Number CP between operator sends gte/lte bounds (Issue #27482)","durationMs":29044,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-38c5b4f50e470a21dec5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"DateTime CP with all operators","durationMs":36493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-39ca4bac99e8c38f4893","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name exceeds 256 characters","durationMs":5038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3af16c42b7e43de3610a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for databaseSchema in right panel","durationMs":9305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3cd6204cfd0c101ede1b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a caret","durationMs":5055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3e66b795beaabcfc4e18","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should accept a valid name starting with a letter","durationMs":5376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3fc0be82527ff18dbf4d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for container in right panel","durationMs":9081,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3fe3da753570171b89f8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference CP with all operators","durationMs":35260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-3febd7d88ddcf14f9d74","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for chart in right panel","durationMs":9175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4337412e95b645514b11","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for storedProcedure in right panel","durationMs":10543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-443430595829177dc49b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":20171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4440d5c29ebf7b879e13","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a less-than sign","durationMs":5574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-44413c5a1543a1f5a65d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show No Data placeholder when hyperlink has no value","durationMs":5169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4448b5bfa30f03224bd5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for apiCollection in right panel","durationMs":9716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-47b51888cdfc4692d610","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15929,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4827e24fda5a1d45d22f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Hyperlink CP with operators","durationMs":56863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-48a4ae191a789b00d2b2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on apiCollection","durationMs":14923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4b507b63d20449a81643","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a double quote","durationMs":4910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4c6f5910036e8a8ecd06","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table CP - Role column with all operators","durationMs":32441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-4c7f9c476c2ed0007bee","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for dashboard in right panel","durationMs":6636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-5134cc15da4d82e27660","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for searchIndex in right panel","durationMs":9909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-52d82632ab1dbfb46acb","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Create custom property and configure search for Dashboard","durationMs":27685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-53e6f09a5c52bf7df3ef","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for metric in right panel","durationMs":9901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-55e07b0e789c9713f0e1","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for container in right panel","durationMs":9717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-578a14db66c772d9f19a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time Interval CP with operators","durationMs":56527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-5b8fbffd20b99a05b306","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for dataProduct in right panel","durationMs":14280,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-5ec7d3ce5e4c562daa12","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for dashboard in right panel","durationMs":6992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-631d2b822a425a37f1ad","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"sqlQuery shows scrollable CodeMirror container and no expand toggle","durationMs":14777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-65307a93e05183f89aea","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for metric in right panel","durationMs":10258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-656cc7d8ddbc7c49d430","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time CP with all operators","durationMs":24103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6655b40bd42bf7dd92cf","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for dashboardDataModel in right panel","durationMs":12555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-68023ece76e3b9d66801","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"no duplicate card after update","durationMs":23695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6822a41e8f427108e34d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for apiCollection in right panel","durationMs":10429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6d9247cb6f905ac30d36","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for dataProduct in right panel","durationMs":13876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6e0b510a4357a92405ad","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":24298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6e2dcbfa65968e44a7c7","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on dataProduct","durationMs":18973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-6f453e86d7a1c3ac71e3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference","durationMs":21176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-706fba167c2158a9f19c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for table in right panel","durationMs":8949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-74f1413fcd08c3e9eea9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for searchIndex in right panel","durationMs":10050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-758a3345517b4a31f72f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for pipeline in right panel","durationMs":10511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-75b13a66cc9bb065087a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for database in right panel","durationMs":12140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-78380c7e57ee93066467","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains an asterisk","durationMs":5530,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7841102043c30e3f1f34","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Enum","durationMs":18816,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7b91914a9fad1814c71e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Enum: Set Value, Verify, Remove Value","durationMs":8306,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7cc62919e3b9e1b62694","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for pipeline in right panel","durationMs":9734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7d2ecf1e1524a2e1892d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on storedProcedure","durationMs":17277,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7d3bdab21816548f036f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Date CP with all operators","durationMs":34596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-7d916dac346243f25b87","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for topic in right panel","durationMs":12776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8008a10e168b1c34bc42","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Number CP with all operators","durationMs":27768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8206d4dac7f2ead1c59c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for searchIndex in right panel","durationMs":10641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8465025d34d1ba303095","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for storedProcedure in right panel","durationMs":10387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-85d2000be90731f68ff3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"User visible in right panel when added as entityReferenceList custom property","durationMs":7581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-86a58b48381d1d8e95d3","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":20787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-87e8c056c3709eb4e491","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for glossaryTerm in right panel","durationMs":10176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-880378d44be14f2a0d8b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on dashboardDataModel","durationMs":19979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-88b29e301c7885391aba","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8afc594c33cf95e66ff6","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for dataProduct in right panel","durationMs":13545,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-8ef70bdc69877ccd56cc","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for table in right panel","durationMs":8201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-918132860676bf7ef176","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for metric in right panel","durationMs":10677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9188e4d6124f320a46a9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for databaseSchema in right panel","durationMs":7992,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-925b2a5ddef6f183d467","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"table-cp shows row count, scrollable container, no expand toggle","durationMs":9978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-92e66352c532d1282ab5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for dashboardDataModel in right panel","durationMs":14158,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9543959e2b5605de9ea8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Date","durationMs":12949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-95da432fd800c29682ce","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15924,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9642fc35ba00455535b1","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for apiEndpoint in right panel","durationMs":12984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-97e0f312e86c2b042db8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":15140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-98578f04c3c4935811d2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on topic","durationMs":19838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-98c8415db3b1f4ca0569","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for database in right panel","durationMs":12129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9a7507dc2536c9b96f53","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a greater-than sign","durationMs":5533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-9c0b89b0755adc0f5919","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":14175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a2d9c2586f84fe5251aa","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a dollar sign","durationMs":5124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a4e24951e57deeb9ee69","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference List","durationMs":20329,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a55f86c4ec59405c15b9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"entityReferenceList shows item count, scrollable list, no expand toggle","durationMs":14661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a733d29eb95f348d8d7f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for apiEndpoint in right panel","durationMs":14273,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-a77692b01e6eca70c785","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set all CP types and update representative properties on table","durationMs":35155,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-aba34920bf0b82ae95bb","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for dashboardDataModel in right panel","durationMs":13101,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b1308b8a516b8cb9ebf8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Verify Pipeline custom property persists in search settings","durationMs":5776,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b1b39433ec030281258b","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":16734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b29df081605055efcf39","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b3388fdecc2ad8d1a917","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name starts with a non-alphanumeric character","durationMs":5560,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b3574c7e673e7661e1d0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table","durationMs":20319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b42635480458c69c0058","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for databaseSchema in right panel","durationMs":9103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b49c14b444b41ef871c0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":16915,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b4fe5b76badf6f07556f","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for dataProduct in right panel","durationMs":13796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b55d69150fb57f8ebf3d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for table in right panel","durationMs":10049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b5a3c351a5994c7468ba","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for pipeline in right panel","durationMs":9961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b89bfd43a8bfc7e51b34","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table CP - Name column with all operators","durationMs":33385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-b8bf915ba142ddcac4c0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-bd447013e59274885103","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for mlmodel in right panel","durationMs":13787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c00429d0241747787024","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on chart","durationMs":13630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c2a6e896d6c984cc6a55","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Enum CP with all operators","durationMs":33812,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c5145b1f6116551c054a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for dashboard in right panel","durationMs":7284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c8cd0c7b62f24c8bf605","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for pipeline in right panel","durationMs":10103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-c8f4fdafd8c406812655","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on searchIndex","durationMs":17355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ccbbec56928c924a0364","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains a forward slash","durationMs":5677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-cd5c20bf0878e3ddfb88","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should show error when name contains an ampersand","durationMs":5638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-cfb9e8e45a2cf6f8edba","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for databaseSchema in right panel","durationMs":8931,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d1f1d6682c54f0eee731","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for dashboard in right panel","durationMs":6582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d367410a3d276e768f1e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Sql Query","durationMs":16349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d3690b8817694bcb83b7","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Email","durationMs":17619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d404277b926d9d8d2069","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for chart in right panel","durationMs":9357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d47e27129966726f7534","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for glossaryTerm in right panel","durationMs":10833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d65630934d80acbe62cd","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Duration CP with all operators","durationMs":26247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d7e8ad039d71e8a7c572","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for topic in right panel","durationMs":12338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-d93a7140bf1bd5bdd8d8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for database in right panel","durationMs":11609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-dae6e741e568b0557027","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for mlmodel in right panel","durationMs":13004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-dbc2b32a754a0f964545","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on apiEndpoint","durationMs":17523,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-df87952db325e9d6d907","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String CP with numeric-like string value","durationMs":30536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e4ba59ec229c66902e0d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":18342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e694ff42b3b887567bfd","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for apiCollection in right panel","durationMs":9829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e769b190aa8fb84b45e4","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Date Time","durationMs":17172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e84c3c0137f1039e28c2","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should display custom properties for glossaryTerm in right panel","durationMs":10035,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e8ad632e57cd4726f62e","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Entity Reference List CP with all operators","durationMs":37156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e8bc3c66a99f793df1d8","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for database in right panel","durationMs":12061,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-e8fdc4505ec39607a36d","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Markdown CP with all operators","durationMs":25043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ea562b6d00e8518d2137","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Timestamp CP with all operators","durationMs":22773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ea89b0ef843ab4311f58","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":21027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-eb0bd2320ea66fd86706","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on metric","durationMs":16288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-ef476d3b4603c8a4381c","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for metric in right panel","durationMs":9266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f079a72c9858cbf038d7","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Set & Update String CP on databaseSchema","durationMs":16830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f206353a5c99d247c672","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for storedProcedure in right panel","durationMs":10654,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f24f565618b6ef1ce3bd","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Verify Dashboard custom property persists in search settings","durationMs":3289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f3634eddf4aeb8ede7a5","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"SQL Query CP with all operators","durationMs":20114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f3d24db98506074025a9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Table CP - Sr No column with all operators","durationMs":31309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f4100ee1ffe0946ec7f0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should clear search and show all properties for mlmodel in right panel","durationMs":12107,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f49b660fff35024b8100","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"should reject javascript: protocol URLs for XSS protection","durationMs":6753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f5a397a6f934257987e4","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":20313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f5a8dbb1a3170bea745a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Time","durationMs":19367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f6475c472a261574fcb0","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should verify property name is visible for apiCollection in right panel","durationMs":10470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-f9f2a10de961b60567fa","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Hyperlink","durationMs":19777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-fad45bcbe2162604d3b9","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"Should search custom properties for container in right panel","durationMs":9089,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7c975cd1ceb31d5d60dd-fb579170cd1d7c4a289a","project":"chromium","file":"Pages/CustomProperties.spec.ts","title":"String","durationMs":17453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-174101936d3896ce9f47","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should add multiple different target terms in a single save","durationMs":8737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-21c26aaf5eca59e26cc8","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should delete a specific relation while keeping others","durationMs":9285,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-347289cdde81b2e86c77","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should add three relations to a single term and persist all after reload","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-471da3990b61252d964c","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should edit the relation type of an existing related term","durationMs":8938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-99084aaab07cdc368d6b","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should reveal the related terms hidden behind the overflow toggle","durationMs":11803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7d2965287e0679e85b3b-ac6e5f3ff65f304cd641","project":"chromium","file":"Features/Glossary/GlossaryTermRelatedTerms.spec.ts","title":"should add Related To, Narrower, and Has Part to the same target term and persist all after reload","durationMs":12821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-03c1b4a263999577617b","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by middle level status shows nested term as flat result","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"7ee79c9e9918f9ca7835-0b22ed09f9439ea8c7ff","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"search for child term name + apply non-matching status filter shows no results","durationMs":7919,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-234737f04928d20473b5","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"expand all button loads all terms","durationMs":8060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-27e6f44e8b15f854d098","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"apply filter, expand parent, verify children shown","durationMs":6580,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-466fc3ab5bfc5a841ed3","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"all children have same status different from parent","durationMs":7881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-4f00a63e0200f02e1523","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"search for child term name + matching status shows child","durationMs":6788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-57f0b473b90da6940065","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"expanding grandparent shows parent with any status","durationMs":8308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-5cd7639c3dbcd18fba5f","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by leaf level status shows nested term as flat result","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"7ee79c9e9918f9ca7835-79bfb46ac41aa25bf7bf","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"clearing status filter maintains search results","durationMs":8325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-8db8c485b9ff1b220d60","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"search for parent term name with child status filter shows no results","durationMs":6483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-a3ffe4e7ef370a9818c2","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter shows parent when status matches and all children on expand","durationMs":8761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-ac556f0de995587cfa8f","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"clearing search maintains status filter","durationMs":6942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-ae74ac03d84aac90be70","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by parent status shows parent and allows expansion to see children","durationMs":7700,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-b670df663ced880eb115","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by child status shows child as flat result even if parent does not match","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"7ee79c9e9918f9ca7835-b99d3ceddec644ada565","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"multiple status filter shows terms matching any selected status","durationMs":7023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-c2facc4c319dc59d5305","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"filter by grandparent status shows only approved terms","durationMs":6883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-de1c9c9f19f09f7f3f74","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"only leaf nodes match filter - parent chain does not","durationMs":6404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7ee79c9e9918f9ca7835-e2c08e3717cd88d91692","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"deeply nested term (5 levels) - filter shows matching terms as flat results","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"7ee79c9e9918f9ca7835-ed1a87cd827864150908","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterNestedTerms.spec.ts","title":"change filter while expanded updates visible root terms","durationMs":7331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7f83f47ccb329ee308eb-2d5871a8c22b587d7bc9","project":"chromium","file":"Flow/ApiDocs.spec.ts","title":"API docs should work properly","durationMs":10004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"7fe377069ec905157f69-c57732e5a453d5d11e48","project":"chromium","file":"Features/EntityRightCollapsablePanel.spec.ts","title":"Show and Hide Right Collapsable Panel","durationMs":7535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8353b5bd378f555885cd-ced9991ca1236b535306","project":"chromium","file":"Flow/ApiCollection.spec.ts","title":"Verify Owner Propagation: owner should be propagated to the API Collection's API Endpoint","durationMs":39737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"83b398fa84d933d87686-04e325d8cc12eba5e53e","project":"Basic","file":"Pages/LoginConfiguration.spec.ts","title":"reset login configuration should work","durationMs":3745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"83b398fa84d933d87686-1a9e5feffef3d3445b26","project":"Basic","file":"Pages/LoginConfiguration.spec.ts","title":"update login configuration should work","durationMs":6197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"84796481a57bc647802f-242f17fe293eed0e4f58","project":"chromium","file":"Features/Glossary/GlossaryInheritedReviewerApproval.spec.ts","title":"term inherits reviewer added to the glossary after an earlier term ran the workflow","durationMs":13230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"84796481a57bc647802f-37f3e60b3e7ddf0777cb","project":"chromium","file":"Features/Glossary/GlossaryInheritedReviewerApproval.spec.ts","title":"inherited reviewer is shown on the term page and it is not left in Draft","durationMs":6717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"848329c182e7112e80ae-9df4121368d3676326e8","project":"chromium","file":"Flow/PersonaDeletionUserProfile.spec.ts","title":"User profile loads correctly before and after persona deletion","durationMs":10859,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-21870b80ea06c6c61080","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should be able to select multiple terms for bulk operations","durationMs":12342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-69563df3d8d1bd29ecc4","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should prevent dragging parent to its own child","durationMs":12459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-791826c9cc34ae77ae2a","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should be able to toggle mutually exclusive setting","durationMs":12188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"851d7513080497ad708a-a3e7717d96e1c52463d5","project":"chromium","file":"Features/Glossary/GlossaryBulkOperations.spec.ts","title":"should navigate to bulk edit page when clicking bulk edit button","durationMs":13449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-1845d01e7ccdda0095af","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"renders the stale cache-state badge","durationMs":3032,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-533404d5aa35173d9319","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"caps max assets at the backend maximum of 1000","durationMs":4528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-700160c385a041b6b4c9","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"renders the failed cache-state badge","durationMs":3090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-98777200bcc547a3549c","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"rule card shows the condition count for a multi-condition filter","durationMs":3513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-a3f208ae7d0498a397c3","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"surfaces the persisted generation error on the settings card","durationMs":4636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"862718b332a943bd0c11-aa7a9fec272b5dd4104b","project":"chromium","file":"Features/PersonaAIContextRuleCardAndStates.spec.ts","title":"rule card shows the all-entities state when no filter is set","durationMs":3429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-39e2d4210de3a6aee51c","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should show term count in glossary listing","durationMs":8222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-51c90aa3d3cbd50f7c3d","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should expand and collapse all terms","durationMs":23499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-5ce50f557be26da6421c","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle large number of glossary terms with pagination","durationMs":13026,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-66452f74ee29979cc6d3","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle large number of glossary child term with pagination","durationMs":25945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-c321395812e83839cd55","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should maintain scroll position when loading more terms","durationMs":9601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-c75ef376e0e3aeac99e7","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle drag and drop for term reordering","durationMs":20518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-dfd827b0183ea271ab84","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should search and filter glossary terms","durationMs":12307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-f609aa3b78d2f65881fd","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should expand individual terms","durationMs":9758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8727528fe1628229cdad-fd6356c420635592f5ea","project":"chromium","file":"Features/Glossary/LargeGlossaryPerformance.spec.ts","title":"should handle status filtering","durationMs":9234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-140cb435ed84863f3897","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Alert operations for a user with and without permissions","durationMs":64459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-517df8c4e105fea3132d","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Data Contract Name filter lists matching data contracts","durationMs":7074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-8c8069db90344336e8b3","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Test Suite alert","durationMs":25083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-918aa5763e716d122442","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Test case alert","durationMs":32355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-b916a573700fed09d859","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Table alert","durationMs":21605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-c2cb524aacc68f08f74d","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"delivers table schema changes to an external webhook","durationMs":34252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-e080c3944816b4fb8c10","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Pipeline Alert","durationMs":37873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"87456cf819b0233163b3-f843143498ffba623720","project":"chromium","file":"Flow/ObservabilityAlerts.spec.ts","title":"Ingestion Pipeline alert","durationMs":26064,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-05d6b12140e7b158a71e","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should reset pagination when filters change","durationMs":8988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-0a10b0e44065fb8502c3","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should filter test definitions with single-select filters","durationMs":9743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-2f0ed50d9a397315fe21","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should handle filter UI interactions correctly","durationMs":8279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-4537e6e3d565f4a5c602","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should handle multiple filter operations","durationMs":10608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-6220e7b1bc4fccbd3504","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should restore and persist filters from URL","durationMs":15236,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-6cfa09b12a7300edb68f","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should not revert to previous value when changing filter selection","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8774de73139c5a67ca33-8e7b0ff4ff1be00a6fd0","project":"chromium","file":"Features/DataQuality/TestDefinitionFilters.spec.ts","title":"should make correct API calls and show filtered results","durationMs":7888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-024f722ac50dd9817b74","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"DataProduct - Certification assign, update, and remove","durationMs":11753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-049fb397dbc7f673f76b","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Edit buttons not visible on Domain","durationMs":7758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-8e0b212ecad90a923a5f","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Domain - UpVote and DownVote","durationMs":8393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-c6fcf77553a572dac672","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"DataProduct - UpVote and DownVote","durationMs":6996,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-c82d83f43577ab6478e0","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Domain - Certification assign, update, and remove","durationMs":11729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-d89f229dce3bfd3c5897","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"DataProduct - Tier assign, update, and remove","durationMs":10230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-fd03e39a19b2a7270353","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Edit buttons not visible on DataProduct","durationMs":6549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"877ab5ffd9592be99930-fec525a76b0cc14929bb","project":"chromium","file":"Features/DomainTierCertificationVoting.spec.ts","title":"Domain - Tier assign, update, and remove","durationMs":10425,"attempts":1,"retries":0,"outcome":"expected"},{"id":"881e65180b3903b61009-329957068f1e26fcddaa","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":23301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"881e65180b3903b61009-b5eebb5ec29f3085052a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":23152,"attempts":1,"retries":0,"outcome":"expected"},{"id":"886b17c78623def558cb-655d3f46261756c6406e","project":"chromium","file":"Features/Tasks/TaskCustomFormWorkflow.spec.ts","title":"renders and resolves a workflow-driven custom task end to end","durationMs":15181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"88aed568d27816e1e7bc-df00a43a3c43019be57b","project":"Ingestion","file":"Flow/ApiServiceRest.spec.ts","title":"add update and delete api service type REST","durationMs":10879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-0dc418f1c23a4844a197","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should add asset via Add Assets dropdown button","durationMs":18038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-28906e2384c9a1bab9f6","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should search within assets tab","durationMs":12574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-4a7e377e96c978147e0a","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should add pipeline asset to glossary term","durationMs":17198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-61b40f6d4808b291d05e","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should add topic asset to glossary term","durationMs":16823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-96fa4ed1ffebaddf928d","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should remove glossary term tag from entity page","durationMs":10305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-9f29d348a57a79cc841b","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should bulk select and remove multiple assets","durationMs":14441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-b0bdefe972c5bed0bcca","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should paginate through assets","durationMs":15465,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-b1f3d6ed1b08d1a4bb24","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should filter assets by entity type","durationMs":12943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-cc69574004082d93a6c5","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should remove asset from glossary term","durationMs":15573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"890c0d202106a51b1736-d3d22f75cff0fb556b4b","project":"chromium","file":"Features/Glossary/GlossaryAssets.spec.ts","title":"should open summary panel when clicking asset card","durationMs":11929,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-01b2b9560e74a71c4e80","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for topic","durationMs":11806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-01b32310e41f5a980287","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for databaseSchema","durationMs":8122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-01fb2e8333263723922b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for pipeline","durationMs":14958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-021b43b75a663324a24f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for searchIndex","durationMs":7592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-04c9500a66e07a0f4d19","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for mlmodel","durationMs":6320,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-075ca5b3b707726c1fed","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for container","durationMs":10042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-08f3053810bc0d9eabc9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Data Quality tab should show permission placeholder for ViewBasic-only user in column detail panel","durationMs":9311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-098503b11056d698e6d5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for topic","durationMs":7074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-09e1f1bd7ce4581c08be","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for searchIndex","durationMs":21435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0b0f6011525649c413ca","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for topic","durationMs":8819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0b717bcb08d7229c39ed","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for dashboard","durationMs":8563,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0cb8b557b5588a3a58fb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for container","durationMs":7024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-0d014fe4158d6b11b3cc","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for topic","durationMs":7757,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-108197f2ea7989151511","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show lineage connections created via API in the lineage tab","durationMs":10262,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-10b1487c0530097575fe","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for table","durationMs":10449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-11009753c55f5981d8ac","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should add multiple tags simultaneously","durationMs":12090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1239865fabbb2f7594c2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for database","durationMs":6140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-12b33b3886ab0aba320a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for database","durationMs":9833,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-133d2e4520c8ec06a4f8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for mlmodel","durationMs":7087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-13567b059282c60d0137","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for table","durationMs":11112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-13de2cfc701692d2a9ea","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for dashboard","durationMs":11252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-13e86c10ca16df0499a1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for dashboardDataModel","durationMs":11461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-14d4eb746eba76f718ca","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for topic","durationMs":7923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1538d123f2c2a8811c53","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless searchIndex","durationMs":8831,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1563e5297bd085a588eb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no tier assigned","durationMs":7647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1585959eee57db3c7549","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for topic","durationMs":9629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-186ced8275acfdbf9e0d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for dashboard","durationMs":7416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-18ba5f44c0099f79d0a3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless databaseSchema","durationMs":7898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-19a477c372c716a9b39e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for container","durationMs":7418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b2b323f53e816de1c91","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for searchIndex","durationMs":9159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b34f2684127b3d55c88","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for pipeline","durationMs":6473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b365f5b11a18b0c3a39","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for table","durationMs":8820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1b60622e03798838715f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for topic","durationMs":7959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1cca72e08823914fe23d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for dashboardDataModel","durationMs":72291,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-1e2b0ffad049bc59c8d0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show lineage not found when no lineage exists","durationMs":8955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-210dadbfa945990935c3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for database","durationMs":11241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-244b13ccd0f7b900fb28","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for container","durationMs":7068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-24c9ce8ce0dabd0d509c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for searchIndex","durationMs":7407,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-25d41d54b9b04a45678b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for database","durationMs":39097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-265891ba968cefecc439","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for table","durationMs":12780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2678b9d0b7d021634922","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no domain assigned","durationMs":6492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2a1b4bcab0fcc6c2ce4a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for container","durationMs":6574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2a4c2dca654df7df1006","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for container","durationMs":20042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2d3f1768f2cb5afafa65","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for dashboardDataModel","durationMs":31124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2e6e45b67faa36697299","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for dashboard","durationMs":8204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-2fc3809a0d019d09cae9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for database","durationMs":7459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-30ea32e8028fb027e06a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show incidents tab content and verify incident details when a failed test case exists","durationMs":8510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3165aa7bde7820a3795c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no glossary terms assigned","durationMs":6358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-32005e753a77f02e59b8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should update panel content when switching between entities","durationMs":17403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-336bac00f4185cc63b6f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for databaseSchema","durationMs":10446,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-33c5fbe2f0d2d2b46928","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for table","durationMs":8497,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3462732720adea629df6","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for mlmodel","durationMs":11999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3563f62190ac2b1c45b1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for databaseSchema","durationMs":6780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3686e6b7490be9179d9d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for container","durationMs":10679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-36938a136687ea4b0aca","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no tags assigned","durationMs":6002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-379ca13bb8e867f09013","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for table","durationMs":14347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-38405a0dff0a4e15c280","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for dashboardDataModel","durationMs":12955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3a90fe95b59eae1daa7a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for database","durationMs":8321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3afc31365a9afae9a2b2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for container","durationMs":9252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3bd8882671b45f246ae3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for pipeline","durationMs":7233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3bec1cf9f34fbf374128","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for database","durationMs":8570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3d138dec7cdb5adc679a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for dashboardDataModel","durationMs":11737,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3e934042c6730b3de1ce","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for database","durationMs":9224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3ec0933dab0a3b371888","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for table","durationMs":18042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-3f76b3e13a73d4472bf3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for container","durationMs":9461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4043f9e1c36ea0ea6a60","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for container","durationMs":9756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-429f7a20fda2da1e9bbb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for searchIndex","durationMs":7717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-42f94f41e925d9ccfe5b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for searchIndex","durationMs":9387,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-43e1553306030ed869f5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for table","durationMs":60946,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-473216426419bf5f9a0f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for topic","durationMs":7536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4880722314bd7f82cdfb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for databaseSchema","durationMs":9614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-48fc388a6c2a2863b1f1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for container","durationMs":10277,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-499f0373baa46d13eaa4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for topic","durationMs":8268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-49e28f6489c7e97ea574","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for dashboardDataModel","durationMs":9509,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4a62b223c60b06477ffb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for table","durationMs":8840,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4b303bd077ac40ef58a2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for pipeline","durationMs":11328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4d7466661908a3d14775","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for dashboardDataModel","durationMs":8208,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4db7926c584af28e377e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display incidents tab for table","durationMs":9893,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-4ee18c4acfd795b9804a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for dashboard","durationMs":9272,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5233209655e60c3a8994","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for topic","durationMs":13860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5292139b2be76c19f5f9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for pipeline","durationMs":6855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-530577a1b9881140aa0b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for databaseSchema","durationMs":10670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-54c8de9b6bc6f04c9f93","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for pipeline","durationMs":6945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-564cf22c841556fb5bfb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for mlmodel","durationMs":10293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-56c2bf919a99f01eaed5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for databaseSchema","durationMs":6490,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-57573d1765bdeaa7dd3f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for dashboardDataModel","durationMs":10550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-58a5555b60b70ce5d6b7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for container","durationMs":10266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-59aec5b13e4c7fd0035f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for table","durationMs":10099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5a4c679cefbe0fd7a08f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for searchIndex","durationMs":11248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5bf2dc1bad8025064534","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for dashboard","durationMs":20912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5d117c59ba118aee6ec5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for topic","durationMs":8803,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5d3b2212dda5295f2c25","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for searchIndex","durationMs":8810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5fefb66da2175223e06a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for dashboardDataModel","durationMs":10257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-5ff2addc90e11b5b1429","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for database","durationMs":5804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-62eb3a55c6a5df575ff2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for pipeline","durationMs":8694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6473eb373e9b0fb070e0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for topic","durationMs":7510,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-656d7787e6bd7e9df922","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for searchIndex","durationMs":11355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-663bba2a53845b8ea55b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for topic","durationMs":51962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-685ed0fc7776cf71b618","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for pipeline","durationMs":8182,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-692888610a61ccdff209","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for dashboardDataModel","durationMs":9861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6970a240acfb0e1d8b51","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify empty state when no test cases for table","durationMs":6391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6d0142300f3217f0e21c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for pipeline","durationMs":9916,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6d9d673d723e25f12f7e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for container","durationMs":9137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6ecc15f9f9ba3f23f44a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for mlmodel","durationMs":10261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-6f44900a3c4281198d6f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for database","durationMs":9536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7219436bbdd76d7279fe","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for database","durationMs":13466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-727e88a336b4ec778ffc","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for databaseSchema","durationMs":7008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-737a0f1778b15fc44600","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for table","durationMs":10823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-73cb8c486fbda270c14f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for topic","durationMs":8594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-742072c30dbb99bd0484","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for topic","durationMs":14922,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-768ccc8bc120323d821b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for mlmodel","durationMs":7075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-798159f734b0c332a42b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for mlmodel","durationMs":9628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-79e4216446a38640e9a1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless dashboardDataModel","durationMs":8353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7d9f4e48e9dcfe591dce","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for searchIndex","durationMs":9366,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7dd33f8b24d0f71db45d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for table","durationMs":11853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7dd365bcb6c0d8f3c1dd","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for mlmodel","durationMs":9211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7e0095dfd25254c7f75f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should search and filter test cases in Data Quality tab","durationMs":10901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7ea3408a9784bedb27b5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for container","durationMs":8245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-7eda860aa3972132c9dd","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for databaseSchema","durationMs":13262,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-83db68eb1c852d7ff609","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for mlmodel","durationMs":9848,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-846a0cefdd1305f9ed1f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for searchIndex","durationMs":7185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-84e1e82f8a7d650659ef","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for database","durationMs":13302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-867ab86eaca612a373f5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for database","durationMs":11452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-870a0dd2d3a32a952a61","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to data quality and verify tab structure for table","durationMs":10778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-88258c610239b8cb1322","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless mlmodel","durationMs":8377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-88c53fddc30f751fa124","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for dashboard","durationMs":11594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-894ae9960c4b6b84a946","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for databaseSchema","durationMs":7077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8956232c87a9e10cb734","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for topic","durationMs":8814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8ad72141d07f120d17f3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for searchIndex","durationMs":7858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8c027a0666e7c0718c7b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show no test cases message when data quality tab is empty","durationMs":7289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8c0f36ededad10ee0c0c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for databaseSchema","durationMs":13239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8d8ab167de121658e7e7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for topic","durationMs":7153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-8e0c627d31aa7c2e7e7c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for topic","durationMs":9327,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-930c4957721075839350","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for database","durationMs":9549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-93f9949605954467bc13","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless container","durationMs":6553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-94b895bd39cbeecbf478","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for pipeline","durationMs":5524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9754cdab78f1f70cba04","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for mlmodel","durationMs":8009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-97f0ce9aaeb905d35f7e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for dashboard","durationMs":7196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-98de6578045812df76c9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for mlmodel","durationMs":6400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-99839712f24fb735f384","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for dashboardDataModel","durationMs":9056,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9994533a4719723b9d4b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for searchIndex","durationMs":45322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-99bb36c88847f6d6f3b1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT allow Data Consumer to edit owners when entity has owner","durationMs":19172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9a4b9416d84f1f23c897","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for database","durationMs":8221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9b25a468e966bd069a74","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for table","durationMs":7770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-9fa9aacf3b07fb05ba7d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for dashboardDataModel","durationMs":9341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a0841d6bc1c9f097bda0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for searchIndex","durationMs":7436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a201f5c4eb58c110901e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for mlmodel","durationMs":12993,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a229c05471eda8fa1d5f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for table","durationMs":9231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a31a06cd87f69b9df866","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for mlmodel","durationMs":7749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a58f95651ebdd39a4baf","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should not make forbidden API calls when ViewBasic-only user opens column detail panel","durationMs":11501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a5f2ecf8b4476450c4db","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for dashboard","durationMs":11006,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a671dc22f0967afe3bb3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for table","durationMs":12089,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a744c11227116d506e78","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for databaseSchema","durationMs":10178,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a7514af88554d985d47e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for pipeline","durationMs":180524,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"8b186e385bbdb2574005-a7c023e88c4f118f6f02","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for databaseSchema","durationMs":37131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a8514f3a07691b47119f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for databaseSchema","durationMs":13482,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a96ef28811ef2178b45a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for dashboardDataModel","durationMs":10183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-a99d3370ba468f21cab1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for container","durationMs":7531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-aa1561bf1073bcc3c435","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for database","durationMs":11752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-aad46b378dfde5d87619","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for searchIndex","durationMs":8354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-acd8015ef4305973bce6","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for searchIndex","durationMs":11321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ae0d88c8e231ab65349f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for table","durationMs":16171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ae56396e3657654ed95a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for pipeline","durationMs":9314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-afc78822b98d1c640ea5","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for searchIndex","durationMs":10242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b0181c53477b65c05d35","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for mlmodel","durationMs":6398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b0cd45603d85986f08c7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for container","durationMs":8507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b15a31f4e5af43faba7c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for container","durationMs":7255,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b43a981d6c7c7d843812","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for mlmodel","durationMs":50474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b5a9ed0234ef1e52bc52","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for mlmodel","durationMs":7789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b8d5ea42f6a6b6f8535b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for topic","durationMs":10313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-b98a58764e43cdd18b86","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless topic","durationMs":6836,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ba47593ab31c61081912","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for dashboard","durationMs":9634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-bd02f0788f67382d3e11","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for pipeline","durationMs":9255,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-bd0ba1f1db8e8ebaba73","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless table","durationMs":9647,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-bff139f834dd62f12ca0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for mlmodel","durationMs":15701,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c0ae5ab7d970d296c1c8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for pipeline","durationMs":10401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c263c93a44e29c3e55e4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should show appropriate message when no owners assigned","durationMs":8376,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c36f059d2c6d8059e39f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for searchIndex","durationMs":10246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c38d013f1592751af7e8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for table","durationMs":11132,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c441e734d3b80c96fbd8","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for database","durationMs":12850,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c45af9ddb6911f2c8c08","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for dashboardDataModel","durationMs":8602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c666d823b842348f9a68","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for container","durationMs":8635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c6b66ba86aa55c55c210","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should handle lineage expansion buttons for searchIndex","durationMs":8636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c6b8adb0e10a3fb5bded","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for dashboardDataModel","durationMs":9287,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c6d8cc4def9c9829081e","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tags for dashboard","durationMs":9688,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c70c7ab1e9b13167250c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for searchIndex","durationMs":7342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c8767c2bb584879cd982","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless pipeline","durationMs":8390,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-c9724a2b13445c4d6a92","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for dashboard","durationMs":7814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ca5bb991ac4fd8652e2d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for dashboardDataModel","durationMs":10156,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cc4f5e3a70eaab5107d0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should clear description for pipeline","durationMs":14667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cdc74314b0b746849d53","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for searchIndex","durationMs":7988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ce9287a9a94ad35fa4f7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for pipeline","durationMs":8582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cf77fd2cc064e138e21d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for container","durationMs":8800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-cf880f1b73444ae5e7dc","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for dashboard","durationMs":52634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d24b82b38fba9393a77f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for pipeline","durationMs":7069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d3313262932f8e5c26e7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for table","durationMs":13267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d423c43dd26c1009523d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display stat cards and filterable test case cards when runs exist","durationMs":7764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d42c7dfcafd0c3d20840","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for dashboard","durationMs":12224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d63bb39fad8fff480982","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for pipeline","durationMs":8033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d775f5c5071bc10a90b1","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for dashboard","durationMs":8430,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d936ca38aed47123aaf3","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tags for mlmodel","durationMs":9313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-d94149b5a027a424200d","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted glossary term not visible in selection for table","durationMs":12603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-dc17507cea6f5e2a941b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for dashboardDataModel","durationMs":8431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-dd46065e3973aee948da","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for dashboard","durationMs":14352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e04473dc158500311e77","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to view all tabs for mlmodel","durationMs":6478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e0b5cd5b646038da6ef0","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should navigate to lineage and test controls for table","durationMs":8867,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e192c717ec35efbb64d4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit description for mlmodel","durationMs":9186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e194f00ae1a12a13554c","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for databaseSchema","durationMs":8844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e34c8aed94d117851885","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for pipeline","durationMs":7037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e3cad63d1a8b0b4c2dec","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for database","durationMs":9041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e3fb9bdf40b67d9a1af4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless dashboard","durationMs":6667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-e738a7e725f877070b42","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for pipeline","durationMs":9857,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ea6b87c9fc3944212e89","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should perform CRUD and Removal operations for container","durationMs":52143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ebd41d2da61ea044cf0a","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"validates visible/hidden tabs and tab content for dashboard","durationMs":8099,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ec8c77e3c18d343605fe","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for topic","durationMs":11209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-eccdbe7dc40257a66039","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted tag not visible in tag selection for databaseSchema","durationMs":14312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ed2e3b93c0b849fff721","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for table","durationMs":10233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-edced786962dcff47e08","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for dashboard","durationMs":7379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-edef11e1a1af8f147e7b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit description for dashboard","durationMs":7555,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-ee8242f1129ae6921c9b","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for pipeline","durationMs":11828,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-eff9436d5c602a9c7b94","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit glossary terms for container","durationMs":11058,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f1c5fb133e74cb02ba04","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should verify deleted user not visible in owner selection for dashboardDataModel","durationMs":15828,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f1fa161c211323ab8f5f","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit owners for topic","durationMs":9717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f2db6acc6a6d463a17a4","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for databaseSchema","durationMs":6756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f3fbb9968dd464480148","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for database","durationMs":6370,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f4372152a4fcdb25efb7","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for databaseSchema","durationMs":10070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f460875c4dd4aceea8ab","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit glossary terms for dashboard","durationMs":8363,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f5df5a41b9ea36e9a8c2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to edit tier for dashboardDataModel","durationMs":8540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f77c37995878f4aa92bb","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should follow Data Consumer role policies for ownerless database","durationMs":7981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-f8d216682ae91929ed81","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Steward to edit tier for databaseSchema","durationMs":7468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fbb48b233aa1d7eb84e9","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should allow Data Consumer to view all tabs for dashboard","durationMs":7196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fbcddae2be02fc636284","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for dashboardDataModel","durationMs":8637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fc164bb0e2000feff2d2","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should display and verify schema fields for databaseSchema","durationMs":12692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b186e385bbdb2574005-fcd6c78be3acd0f339db","project":"chromium","file":"Pages/ExplorePageRightPanel.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for dashboardDataModel","durationMs":7290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-021e38b069566a0daa2e","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"task creator CAN close their own task","durationMs":237,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-05984b7d2794709c41a6","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"task without assignees should still allow admin to resolve","durationMs":533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-0ae4f3085e70138d8eb2","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"assignee WITHOUT EditDescription should NOT be able to resolve RequestDescription task","durationMs":5300,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-3fc026dfedbe459b7b0b","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"assignee WITHOUT EditTags should NOT be able to resolve RequestTag task","durationMs":5535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-4ff4535b84dea3c9a774","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"assignee (owner) should see approve/reject buttons","durationMs":6809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-749c4f5bccd84796fcc1","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"owner (has EditDescription) CAN resolve task","durationMs":5872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-78bbb9afa7c6fd8804ec","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"admin CAN resolve any task","durationMs":397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-873f2c7f083db40f1b18","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"non-assignee without permissions should NOT see approve/reject buttons","durationMs":9012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-88c636be3e54d14ad5a1","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"admin should always see approve/reject buttons","durationMs":8939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-8bd75f03604a4d71ca36","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"non-creator non-assignee CANNOT close task","durationMs":8181,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-936f1eccfe11f4493261","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"non-team member should NOT see approve button","durationMs":9422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-d7be48a39e974fcc4df8","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"team member CAN resolve task assigned to team (team owns entity)","durationMs":9253,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8b4feea5d75ba28aaf2e-f726bad0f784021dbbd5","project":"chromium","file":"Features/Tasks/TaskPermissions.spec.ts","title":"resolving already closed task should preserve closed status","durationMs":304,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-03f2be6de2c2761ec72e","project":"chromium","file":"Pages/Teams.spec.ts","title":"Delete a user from the table","durationMs":13432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-05575cd61e82f379b794","project":"chromium","file":"Pages/Teams.spec.ts","title":"Team search should work properly","durationMs":6362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-1a55f23c25c53060de8b","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New User in Group Team","durationMs":22526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-1f668e63ea29ab01be29","project":"chromium","file":"Pages/Teams.spec.ts","title":"Teams Page Flow","durationMs":44386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-2ae1f95f7a82d858d799","project":"chromium","file":"Pages/Teams.spec.ts","title":"Export team","durationMs":12892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-36f0b663f675c074e314","project":"chromium","file":"Pages/Teams.spec.ts","title":"Permanently deleting a team without soft deleting should work properly","durationMs":11716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-4f1e0c1f52584e8f4a5c","project":"chromium","file":"Pages/Teams.spec.ts","title":"Team assets should","durationMs":31016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-6880dd63ad3dc1c9041a","project":"chromium","file":"Pages/Teams.spec.ts","title":"Create a new public team","durationMs":8731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-7fa42402660989954fc2","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New Team in BusinessUnit Team","durationMs":20615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-8c42ddd21ea38410b62f","project":"chromium","file":"Pages/Teams.spec.ts","title":"Should not have edit access on team page with data available","durationMs":14083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-a496a11b02113f60becd","project":"chromium","file":"Pages/Teams.spec.ts","title":"Create a new private team and check if its visible to admin in teams selection dropdown on user profile","durationMs":12557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-a5acf3c890d0c5f803f0","project":"chromium","file":"Pages/Teams.spec.ts","title":"Should not have edit access on team page with no data available","durationMs":14308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-c5fe5613722668c57494","project":"chromium","file":"Pages/Teams.spec.ts","title":"should fetch teams with correct include parameter","durationMs":5377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-cc91d06ccdf4881127a6","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add and Remove User for Team","durationMs":17248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-d3248786cf8970f94aea","project":"chromium","file":"Pages/Teams.spec.ts","title":"Verify breadcrumb navigation for a team with a dot in its name","durationMs":10265,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-d3d5abbdc9d39264f83e","project":"chromium","file":"Pages/Teams.spec.ts","title":"User as not owner should not have edit/create permission on Team","durationMs":14845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-dfff4b28227075cd2686","project":"chromium","file":"Pages/Teams.spec.ts","title":"Total User Count should update after a member is deactivated","durationMs":9162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-e3b63fffd21ca18f715c","project":"chromium","file":"Pages/Teams.spec.ts","title":"Total User Count should be rendered","durationMs":8119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-f21a59b81da22614e543","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New Team in Division Team","durationMs":21241,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d2c02a06574da4cfaab-f25d2e4da47eecaf9a5d","project":"chromium","file":"Pages/Teams.spec.ts","title":"Add New Team in Department Team","durationMs":16631,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d689656782b1a6f7390-02e6d12455e39839a2aa","project":"Ingestion","file":"Features/ServiceAgentsLiveProgress.spec.ts","title":"agent discovered from the stream updates card and tab counts without reload","durationMs":3906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d689656782b1a6f7390-0359032648b44be54dd2","project":"Ingestion","file":"Features/ServiceAgentsLiveProgress.spec.ts","title":"agent discovered while on another tab updates count and appears on Agents tab","durationMs":3896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d689656782b1a6f7390-18b39c8b1f7b73274a0a","project":"Ingestion","file":"Features/ServiceAgentsLiveProgress.spec.ts","title":"agent card and summary update live from the progress stream","durationMs":4411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-26379e695749933a92ab","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Glossary - multiple rename + update cycles should preserve terms","durationMs":18495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-3e546bf80dc1c11ecdc8","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Domain - rename then update description should work","durationMs":9873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-68eddb3465aced4adc35","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Domain - multiple rename + update cycles should work","durationMs":17271,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-b01e664284f9a0880abb","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"GlossaryTerm - rename then update description should work","durationMs":12841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-b23330247ae47b829cbe","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Classification - rename then update description should preserve tags","durationMs":12151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-d1fcf7e4f6f6e75c9761","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Glossary - rename then update description should preserve terms","durationMs":11169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-dcf818914ebfbadca568","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Classification - multiple rename + update cycles should preserve tags","durationMs":17227,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-ebbe7e5db1a435a00b8f","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Tag - multiple rename + update cycles should work","durationMs":18249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8d7e28fd2b7d98f9cf98-fb1fe9989fbcbf716ad2","project":"Basic","file":"Features/EntityRenameConsolidation.spec.ts","title":"Tag - rename then update description should work","durationMs":11566,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8db3ea1719f4294139d3-393169e3864b22ec2ed6","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":29264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8db3ea1719f4294139d3-8c81d37581eec9265a23","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":28612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8e1475d7a8d4511cde98-9dcce7a238957e980241","project":"chromium","file":"Pages/OmdURLConfiguration.spec.ts","title":"update om url configuration should work","durationMs":5303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-2ca00a647f78c1967420","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Test result tooltip stays fixed while the pointer enters its incident link","durationMs":3961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-334d02c260205a6db082","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Pagination functionality in test cases list","durationMs":6781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-49cf503e6a93539fab49","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"shows exactly one banner for the latest test case run","durationMs":5322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-4c790438c32345b62a1b","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Table test case","durationMs":16415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-553212bab134ed00779b","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"shows every section for a scheduled failed test case run","durationMs":4752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-5ea2f7b91b5b348ee4ba","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Editing display name does not emit a phantom tags patch op","durationMs":5830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-61c21b5abf3c66acede8","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"TestCase filters","durationMs":30191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-9bccae9af98ba5a7c082","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"TestCase with Array params value","durationMs":9433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8eb529397dd159859ffc-b948b3260475ba5169a1","project":"Ingestion","file":"Features/DataQuality/DataQuality.spec.ts","title":"Column test case","durationMs":12896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-00f9606596c3016580e0","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel allow entity-specific permission operations","durationMs":6137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-020742af52a481d6b34a","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database allow entity-specific permission operations","durationMs":16045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-02e76560310002da73e9","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"File deny common operations permissions","durationMs":15115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-048cd5bb07db0b092c46","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel deny common operations permissions","durationMs":14353,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-07b9537cf71ed31371ed","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table allow common operations permissions","durationMs":6438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-09a091accaad0d82c91e","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel allow common operations permissions","durationMs":5996,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-0af671909bde7a013f64","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic deny common operations permissions","durationMs":18239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-0cc373dd04ff8030233f","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Worksheet deny common operations permissions","durationMs":13017,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-10deae907d09b964fcfa","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database deny entity-specific permission operations","durationMs":14872,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-13452946d5045d9f0db4","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline allow common operations permissions","durationMs":15666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-18ae617d79e5d7b7f079","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"File allow common operations permissions","durationMs":16249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-1f326d25e5fc9a9637ce","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard allow entity-specific permission operations","durationMs":11881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-393b9b78f8201b11c857","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline deny common operations permissions","durationMs":16796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-3ad159e3ed8c31713208","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database allow common operations permissions","durationMs":18778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-3c9a28545246bbdc73fb","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Metric allow common operations permissions","durationMs":17694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-45a17df84917860b8165","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Spreadsheet deny common operations permissions","durationMs":7200,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-4d8f171e51cb0d2e42e1","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Worksheet allow common operations permissions","durationMs":10275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-5bfaabe1489bae588f50","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table allow entity-specific permission operations","durationMs":6641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-638c851f124e342a619e","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline deny entity-specific permission operations","durationMs":15123,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-6b2b0ce6cc129f162e51","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Metric deny common operations permissions","durationMs":14567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-7103f95de221bffd41e4","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex allow entity-specific permission operations","durationMs":13968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-76eeb463ff3652b7951f","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table deny entity-specific permission operations","durationMs":7592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-7ae5321fb8e02ddc6a2c","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel allow common operations permissions","durationMs":7711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-7afc5f7035b8498c6583","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard deny common operations permissions","durationMs":15239,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-82058782f5a5195dbf14","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"EditAll allowed but EditTier, EditOwners, EditCertification denied – edit buttons not visible","durationMs":11409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-8497ba3282344447e2e7","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Container deny common operations permissions","durationMs":10885,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-852f1640c17c28a14391","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard deny entity-specific permission operations","durationMs":12690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-8cde431a28f77402aa93","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Container allow common operations permissions","durationMs":11457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-98622cead2f44658d0c6","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel deny common operations permissions","durationMs":10823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-9ecf0c8e4c89f192c4df","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Table deny common operations permissions","durationMs":7020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-9ed49d22924150c2919d","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex deny common operations permissions","durationMs":15497,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-a21c41bd3db9957ede73","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Directory allow common operations permissions","durationMs":10385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-af9cea942959e42519d9","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"EditTier, EditOwners, EditCertification allowed but EditAll denied – edit buttons not visible","durationMs":11608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-b23b07500ce1df682796","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel allow entity-specific permission operations","durationMs":7373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-b6907275b5a16eba27dc","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic deny entity-specific permission operations","durationMs":15899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-be98efca59a108071401","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex deny entity-specific permission operations","durationMs":13954,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-c7b1063f20150b9224a9","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Spreadsheet allow common operations permissions","durationMs":6484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-cdc7161e3a6adaa0c2e4","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Directory deny common operations permissions","durationMs":9892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-ddfdf503467d77c54ffc","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"SearchIndex allow common operations permissions","durationMs":15841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-de36bce534daf48cb1ed","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"DashboardDataModel deny entity-specific permission operations","durationMs":10222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e064b13617abbe309243","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Dashboard allow common operations permissions","durationMs":8456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e4e4e805ca158b580f5f","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic allow common operations permissions","durationMs":18295,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e5bb4189f7681667f866","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Pipeline allow entity-specific permission operations","durationMs":15240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-e84df0a6339c03bd5290","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Database deny common operations permissions","durationMs":15495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-ee4a0b3aec10677417e2","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"Topic allow entity-specific permission operations","durationMs":15478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8ee4c71fd1ee04fef09a-f2f190d2e4df85e59203","project":"chromium","file":"Features/Permissions/EntityPermissions.spec.ts","title":"MlModel deny entity-specific permission operations","durationMs":12885,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-050339a5b3b27948c82d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"view modal switches to edit mode and saves changes","durationMs":9680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-0cbdc9f31920a92283d9","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"deleting a memory via the row actions menu removes it from the list","durationMs":10901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-115d742c3cab23b0a244","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"ArrowDown + Enter keyboard navigation selects the linked table result","durationMs":11451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-123127191309ad6f3c8a","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Add Memory button opens the create modal","durationMs":11972,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1574850a94a988ecbe44","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Private memory shows \"visible only to you\" description","durationMs":9835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-16b3484cc09d5255f8d6","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clearing search restores the unfiltered list","durationMs":9602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1aedfce00d8c5946c8bc","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"shared memory is NOT visible to a user absent from sharedWith","durationMs":12360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1b4f86b0208e986fc6b0","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"adding a linked asset in edit mode shows entity badge on the row","durationMs":14554,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-1c9d85e1c706f63a2d86","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"form is empty when modal is reopened after cancel","durationMs":11323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2a172730b1b53f63f35e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Create Memory button is enabled once memory content is filled","durationMs":9660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2aa5a395123a8c3cdc3d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Preview tab shows \"nothing to preview\" when content is empty","durationMs":9692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2ad5e7e1ef935567b0ed","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"row shows owner name and memory title","durationMs":8856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-2ff20097b005186ec189","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"navigating back to page 1 shows original memories","durationMs":10452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-3867569b1addfa8a9f5c","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"selecting \"Most Used\" actually reorders rows by usageCount","durationMs":9038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-394aa041e4c80c1b07c7","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Preview tab renders markdown content correctly","durationMs":9227,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-46ebbf692c088e16f169","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking \"Total Memories\" count card activates the All view","durationMs":9456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-51a791024388a119e500","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing title updates the memory and the row reflects the new title","durationMs":11380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-54cb6b919c18ad54110c","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"entity-visibility memory is visible to every authenticated user","durationMs":12601,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-55e0a815e60bb09ce57c","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"pagination controls are visible when more than 10 memories exist","durationMs":8514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5942dd11a9d4b64ec829","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"sort dropdown shows all three sort options","durationMs":8120,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5a7baea2b091d24da57b","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking a memory row opens the view-only modal with owner action buttons","durationMs":9021,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5bc1df2528c2b5058f83","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"private memory (admin-owned) is NOT visible to a non-owner","durationMs":12519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5bc84e17ae75eb005f5d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking \"All\" tab after applying an author filter clears the filter","durationMs":11416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-5c94648cb13fa0cbffb1","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"copy link button copies URL containing the ?memory= param","durationMs":9260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-64649ab2041f5d3fe8f3","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking \"Created by Me\" count card activates the created-by-me filter","durationMs":8381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-6512f16c5a112b85a606","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"shared memory IS visible to a user explicitly listed in sharedWith","durationMs":11699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-72b54a939c562fb1c204","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"search box filters memories by title","durationMs":9354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-735e01e2899164788fe8","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"content typed in Edit mode is visible in Preview and preserved when switching back","durationMs":8616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-7b3fb940c312905d5060","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"linked asset card shows remove button; clicking it removes the asset","durationMs":9932,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-8090e9d3ebd02b77c47e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"creates a memory with title, content, and type — card appears in the list","durationMs":11201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-833efd0cc52341230add","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"navigating to a URL with ?memory= param auto-opens the memory modal","durationMs":8541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-8b1f26e601d5baa9ff70","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"closing the modal removes ?memory= param from the URL","durationMs":9288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-8ecc1dad1c384a343e2e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"changing visibility from Shared to Private shows \"visible only to you\" after save","durationMs":15229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-93771ed3a6e8bed91a7e","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"link an asset button opens the search popover","durationMs":9487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-94ab0b32cbe40c045b6b","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"row shows linked entity badge when memory has a primary entity","durationMs":8404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-95c9093fdd3ff5e51c44","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"cancel button in edit mode closes the modal without saving","durationMs":21626,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-9e097128eef15ee87968","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"delete button inside the edit modal deletes the memory","durationMs":10637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-9e8a0babb0950a756604","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"\"Clear All\" button resets the author filter and restores the full list","durationMs":14378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-a506eaeb50a155ae247d","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing memory type persists after save","durationMs":12858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-a6e380a210b52c7dda25","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Create Memory button is disabled when memory content is empty","durationMs":8213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-abc24ab8a7d2cbc7bbcc","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Shared memory shows the shared-with-specific-people description","durationMs":10243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-ad770b579565ae2fd108","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing visibility from Shared to Private saves and updates the badge","durationMs":13375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-b91c37ad31594d56093f","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"typing the linked table name in the asset search returns it as a result","durationMs":10473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-bd5714317a0b47826f87","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"data consumer sees a read-only modal for shared memories they do not own","durationMs":13332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-c89dfb6c8cf1605c7ebf","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"\"All Assets\" option in asset filter button resets the asset filter","durationMs":11950,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-d1e2a2780b71025dac99","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"\"Created by Me\" tab shows admin's own memories and hides the second author's","durationMs":8500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-d71b0b2f0cec854dd4fe","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"navigating to page 2 loads a different set of memory rows","durationMs":8324,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-da46a9af079413eb60af","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"selecting the second author in the author filter shows only their memory","durationMs":10896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-e47a22c54616939b72ef","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"clicking a memory row adds ?memory= param to the URL","durationMs":9470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-e651d4373580504f54fa","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"Entity memory shows \"visible to linked entities\" description","durationMs":10192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-ec8e38c378a883334cb8","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"edit-memory button on the row opens the modal in edit mode","durationMs":9380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-ed83a3eeb82edd110766","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"no results message is shown when search matches nothing","durationMs":8531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-f0c1da1240b0e4613ed2","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"switching back to Edit tab restores the textarea","durationMs":11478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-f10ec76507ba30b98ad4","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"shows header with title, breadcrumb and Add Memory button","durationMs":11783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8f00f316c6c46c156a1c-f3277503da5d3d73f903","project":"chromium","file":"Features/ContextCenterMemories.spec.ts","title":"editing memory content updates the memory","durationMs":11537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-215a8878c531328977c2","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"rejected OwnershipUpdate should NOT change ownership","durationMs":477,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-2602a3aa080b731b4749","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should create and approve DomainUpdate task","durationMs":670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-3a096d2f4ebade0afd91","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"rejected TierUpdate should NOT apply tier","durationMs":467,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-5d012330bf9c4bc78527","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should approve description update task and apply to entity","durationMs":456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-6e386755207335934c43","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should create and approve OwnershipUpdate task","durationMs":636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-c0065d9d29e0659d6c34","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should create and approve TierUpdate task","durationMs":535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"8fac0fef0ac2a4ce9990-cbee75183bf50baef2a7","project":"chromium","file":"Features/Tasks/TaskEntityResolution.spec.ts","title":"should approve column description update task","durationMs":385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90ed2060a2a8751f24f5-24638cee4dd18362bdb5","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Install application","durationMs":3726,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90ed2060a2a8751f24f5-b104994da51b7cdfaabd","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Edit data insight application","durationMs":4040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90ed2060a2a8751f24f5-e421dc1031935e8b877a","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Run application","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"90ed2060a2a8751f24f5-f7537948d9d62bd69376","project":"Data Insight","file":"Pages/DataInsightSettings.spec.ts","title":"Uninstall application","durationMs":2726,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90f483905672abdab8d4-395ef9ff12b9b1cfd420","project":"chromium","file":"Pages/ProfilerConfigurationPage.spec.ts","title":"Sample Data Ingestion Configuration","durationMs":8242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90f483905672abdab8d4-d388e31b6ee015b2c18e","project":"chromium","file":"Pages/ProfilerConfigurationPage.spec.ts","title":"Admin user","durationMs":14612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"90f483905672abdab8d4-d9c6a62871c623262969","project":"chromium","file":"Pages/ProfilerConfigurationPage.spec.ts","title":"Non admin user","durationMs":10764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-010947e1f2ae5f490fdf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":18516,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0204627a501622ee8deb","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":14906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-04a73b3abdf07d99230b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0515d537e10283b36e45","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":16764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-05cb4526aee30bf31b27","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":11009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-05cba1d1810b00e6da0c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":9858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-06621cfea096a95864a1","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12477,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-066ed7052e902f07afd7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":23790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-07d3752db441d6dcd5c9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":14845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0808415fef188619b0c3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-088ab01bbb6af83198b5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":27417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-08a72d1ea60f89919542","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":27506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-09d0849a721c46ed4e27","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":22225,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0a52cbeb44d811c97ae9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0b285034c080279bfe87","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":10804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0b31a83be6093fccd9a8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":16567,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0c601eb8ae577401535c","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":23489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0c9147c3faa959ed6d1f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":24231,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0cae867a36cfb2330728","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0cca9e90033054e752e4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":18802,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0df78730b187b80fb609","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Search Index","durationMs":28108,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0e9f56083fd2fb5d9faa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":27313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0f315b07f498e7688a32","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-0fea7c50c0a5a82872e1","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":7904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-10586eb08b05b663021c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":19723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-10823933e7cc47252622","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":23535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-10ddfe5a92169df86b00","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":19432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-137ec6b7227be9ad99da","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":15119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-139c5016d99093c360b7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":22929,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-14011a0248e6b08f80a7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel key profile metrics validation","durationMs":16163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-14470019ffd97004dcbe","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":18769,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-149227e4460fabcd42c6","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":17377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-14ac924ed8bcb7e68832","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":18256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-15d1273f787e5fa2d04a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-163b977d15c76c372a6b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":62817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-164caa239e68ee9d019b","project":"chromium","file":"Pages/Entity.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":17403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1694b0714d00d5c71ac2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18200,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1699b841032a65cec187","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":26028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-183d1f957e327795eb4a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":19507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-18a47a9004653643fb64","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1943709640011d77ed36","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":17697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-19c2bb2e9c1e146d40e8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel - Data Quality tab shows test cases","durationMs":19488,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1b72ac1fa7bcb9a1a474","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":9124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1c94f2df230f3f14fe7c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":17979,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1cecbcaa17cb6913726e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":9205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1d091ca31ae29db2c8ea","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1d1fa86265503c79342c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":10503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1e2cf9c79c0a9525a66e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":15788,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1e8f2077ec976b52a489","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":17293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1f106521cf5f4bc3d32a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":17451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-1fee3fc39291ed69f8d2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-20f71b2d07418575475d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":33492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-20ff1e5b739d9faf71a9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":27606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-224784ca851aca125dc5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":15010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-22a6f18eb0af4e42f50e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":19243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-23222301ac380b5bdf2d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-255c0b0482bb4fe51e92","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":16574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-260a08f521c36666d45e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":22861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-26bf78922e154401df45","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":16357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-26c62f4d3d117052c242","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":25705,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-286080b65df7a8bc3d85","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-298fdb3a31fa6071e859","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":24323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2b98e260a7accd3dd5e3","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2d387ded98f7768265c4","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":14188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2d76b56f14c39477bfa8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2e8162d5d22dc70ab80c","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2fb15765b5b25a485ab8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":9606,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-2fd19b049110a1f7576e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Api Endpoint","durationMs":27076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-30412ac8a486dbe6db56","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":12451,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3049f221e1833056bb4f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":20380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-30604efc6717f760cb19","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":21745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3130e46417f6b8ee0ddf","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":14286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-31675e337df06a59163e","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-329014335b0953e9a963","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-33a2b8dcb127802d7ea4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3449766d9eea852cb02a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Topic","durationMs":27314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-355b38942f8be1c21038","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":17854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-37b56a8c64057cd16849","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-388ca052aec51e76c129","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":10414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3940d8d78d5447a24d94","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":26572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-39437ad5d0bb92bd3f56","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13305,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3a30f163c9cf41e7b0a2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":24003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3af3ec90e38be2bb9b8a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":13205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3c3dc27e5b016fad1c34","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":26309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3cff397f5942cb1e4415","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":16246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3d1743b61f22211f8cde","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":27885,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-3fd66bb77526bc0549c5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":28249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-40abc10c3cbf325d0814","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":18983,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-40b5f757c2e50ab4c423","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":8316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4186a53379bf3038d6df","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":16084,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-41930b02ea7ae699543b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15438,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-423cbdd8a1649ef25e03","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":19375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-44558ad1c4b6295c42ef","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Dashboard","durationMs":24541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-44979265001c53ce1aa3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":27187,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-459f81112fb7567b0275","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":13082,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-45ce2f3980113cfb8fc3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":12040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-48a178691f7d801b79b0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-490c4b163ecfb2791f11","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4924df03b181449afbff","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":21804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-492726a2addd8a53a89d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":15911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4a4f175326692f1e1df7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4ac150db5e30c650fbf6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":14711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4b66ca7fb325742907a7","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":16147,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4bc0347bfb50f8ba6efa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4bebf2eddb62c1c0a27d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":11789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4cb9c7949e76cfd2158d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4d4f0ab999224ca222c3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4ea337e0978f71f7787a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Complex nested column structures - comprehensive validation","durationMs":15617,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4eb7ba29ce3f14453e74","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":24426,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-4ffc30215ba4fd0f309b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":21732,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-520498925292ca429e70","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":27824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-521bba060aebc0805243","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5237c058076927c64a4b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":23589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-528578f052a6a5d372de","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":15367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-52ded41a9f92477b9e8d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":26005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-545e1e1606596daba844","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22890,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-55c1c83398c224c17777","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":27688,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-57413ea2ee24eacebe86","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5760cca191d53021860e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":32045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-57656fc4e202f6fe94ae","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":25399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-576c627662fa68e8fdf5","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20371,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5783fe4fac5585eab4e8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":24166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-578975ad1fa2b90690ef","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":26824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-589a2251bfac9347931d","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":23290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-58fcb7bc23b74494562d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25418,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-58ff7eefdb13abde7b0b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":17970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-596d6153699326e4a88a","project":"chromium","file":"Pages/Entity.spec.ts","title":"DashboardDataModel page should show the project name","durationMs":9834,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-59f0ea7d5c7e17ed7068","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":12141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5a2fd88bc28e89ca1895","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":26798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5a8a4f525e79dc02ee22","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":33898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5ae58d54d9462234aefd","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14138,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5b54086826771a0d829a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":12526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5b89a6d1f13278f64fb4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":23881,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5bdd95036294d02d6aed","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":18484,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5bfca70544447baacc27","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":19242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5c2dee6d5dee89070889","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5cca7fa93e2963965949","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":19685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5ce7395d57a38e605045","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":19963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5e5602eadda15814cb1d","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20589,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5f55cadeb5b75f2d9827","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":11548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5f73f22159832459f8d6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":19195,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-5ffbcd9603be554d72cc","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":21014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6090b3469968428010ca","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-60d6762c4b0ae5b80aa3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-61888ffb206a1f9cd606","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":14693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-635acc3dd237ce3372f3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Array type columns with nested structures in NestedColumnsSection","durationMs":15373,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-638bed0d16d0fe08b913","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-63d6f16376792bf39ec4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Dashboard Data Model","durationMs":25794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-64cbef5facf9a46414f7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Spreadsheet","durationMs":17251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-658673c37e533eeef774","project":"chromium","file":"Pages/Entity.spec.ts","title":"Data Consumer should be denied edit access in column detail panel when deny policy rule is applied","durationMs":14636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-65e50d3c39f208f5c8b8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":16173,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-660a5d76fe1e2a33c402","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":14256,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-665622c28ce75a44b7d1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":28196,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6688dd944533a6843776","project":"chromium","file":"Pages/Entity.spec.ts","title":"Data Consumer should be denied access to queries and sample data tabs when deny policy rule is applied on table level","durationMs":14016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-675a7eb6037656e443a8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":26436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-67b5ea7d270e6f0d7212","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":10055,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-689e5012886587487afd","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":21570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-68c3d140aa232b18343a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":23772,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-69642132f4c8d46914f0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27903,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-69a4bb362989003c8fe5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":14725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6a7c1cfa25aee1b88332","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":21398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6bf622162eec9ddb280f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":14495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6c45206d1c7e364d3dab","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":24443,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6c6d5e53693ae91f974d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":8689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6cb3a9042fe63e651e6f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":19525,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6d27b11bd3329db0c3da","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":14109,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6db5a8684315b09e586b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":28294,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6dd976c84561bec7292c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":21535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-6f27ade629aa21259930","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":14472,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7033bd8a589efefc6460","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":22243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-714c7c04f6771c55b417","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16153,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-715e918fa77d52c93d3d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":23151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-717c3379a8b317c17d8a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":18823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-72de070373835646c330","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":22125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-73396497c9550736ee6b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":10966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-733d7d7ac05db37816ba","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":14131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-734125bcdd8222736844","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Ml Model","durationMs":26459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-738fa5dafee2cc5efba2","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-74d0bd71eeeca6f080ea","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":25455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7557b6f4c5e94da74b0a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Metric","durationMs":26719,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-76f7c1dce024366a65ad","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":12229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-76fed440252571c4ac35","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":13694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7ac6d76c0b0762dc7654","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7c5857a17226f22628da","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":15202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7c7e74ca9adebcc53967","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":31052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7d3b7ccbffa26944736d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":26286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7dba101412de85e23071","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":13318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7e2e7b59a31556b2749f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":21506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7ed713af973c88618eab","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":19692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7f0a484980e667964f0b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":29258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-7f9e6aef30246153c9f9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":21300,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-80c0a4b111e70096228f","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":20312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-81886e104470f3edf684","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-828bef0287fa1c5da67e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21724,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-831dbe32138dac09e7d8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":18065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-83395592d0affb7528ba","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":27659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-83854023e08436751e88","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel does not call /columns/name GET for DashboardDataModel","durationMs":9043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-83fd602de32ac38f1777","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8487bc28a50fe9aa2194","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":25650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-853d61f316a0d5af5ffd","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":26535,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-85936fb882a2786fd7c7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15664,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-85b99b63d5290506f285","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":13888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-88f8bdd28e992ed4732b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":28708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-89255caaa20ed42f11c1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8a420f6c0389278e14a8","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":9961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8c43a40bbe3dab735d28","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":14421,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8c51774ba5e172b0e5df","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":12690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8e34dc2db65998150cbc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":14603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8ea4f124a947e104dfc4","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":10145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-8fba808d32c7edb58b11","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Pipeline","durationMs":20052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9040c78d20f9f8c4dd0c","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":10090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-90bd676080f86b4a617f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":17841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-91428c93cc268ca60069","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-91543bc8d8167f5065a1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":6191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9231b4fba6be912c3a58","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":13151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-92a98accb4a75ac9bd41","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-93fb297d11c0da8eb925","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":32245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-94398585e76e7076dd89","project":"chromium","file":"Pages/Entity.spec.ts","title":"Switch from Data Observability tab to Activity Feed tab and verify data appears","durationMs":10720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-974cf3128b2fe509f68e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":13939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-981422561ba577ab278f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":16047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-98295172b077e968710d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":30163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-98a764c8f8883afbfc61","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":22852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-98beffeeb1691cfc46e3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":18454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9947441fa2bdd31d2579","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":20699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-99df0dd4ce461e379bf1","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":17077,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9bb7b088737745749568","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":11753,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9bf8262a50e226dc14e0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Dashboard page should show the project name","durationMs":13122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9d47fed51de1a82ea61b","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20360,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9e32c9c3455f40d45c51","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Table","durationMs":33226,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9eb19184071a33394559","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":30023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9eb5d4b065166f22f57d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":29127,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9ef758d01c78546f9e36","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":15385,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-9fca75ad842b940cc462","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a0b8122c30252e10af37","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":13637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a29f3c417fe4c951b553","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Container","durationMs":17692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a2cfcd0d99157a65bf75","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":31160,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a3c11ebaa1e3e2d4c067","project":"chromium","file":"Pages/Entity.spec.ts","title":"DisplayName Add, Update and Remove for child entities","durationMs":9852,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a492547f9007a342a812","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":19139,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a5998ef2edac55039257","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":9635,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a5d17a88fd978d0b50f0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":15975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a7412694cacae19f6d47","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":19281,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a76b7d4955e681a340e2","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":22200,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a7c74023a04b469dc54a","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":15937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a8a7d0dae0901dc05bbf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":10933,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-a9d8535c0845968fbeae","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Worksheet","durationMs":21275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-aa3cf3f233e4209c62d7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-aa8f971f04aec8ed12d5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":13411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ab9125e3be00b247e5c6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":24323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-acf4ed1c6b31c9deb82b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":26541,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ad454c2d5478c288a398","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":24379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ae1753b8395d90f206d5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15719,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ae2e3a33c620656a9e25","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":13389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-aed8de3b484856dea5b5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":18570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-af920abc6c341912e2c4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":16021,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b02919d12e5158bbd751","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":23526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b02c0574cfdb0a3c8631","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b03cf38e18dfe4fa6513","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Stored Procedure","durationMs":18065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b147c972de2ca1979612","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":23675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b1bc3c6efd67cde75543","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b2898eb27b3458212bb9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":9079,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b326e8761d37657c85bc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":18839,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b32b7349dcb65de985b6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Directory","durationMs":24336,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b3d6c097f77e0b107d33","project":"chromium","file":"Pages/Entity.spec.ts","title":"Mixed sibling columns (simple + nested) at same level","durationMs":15586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b57f4cfea36c6106e54d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":16449,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b72b1bcf49a07cf93c31","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":12734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b7d62202728d8accd1ff","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":29192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b80d667c0acf38204010","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b819774aa9824797ce0b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-b8a1c25981278f288325","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete Chart","durationMs":18667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ba27de8b1b49b885f461","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":33600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bbb4b786ce82a4dc2641","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":18722,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bd64ed3fbf1b8cc239da","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":15522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bd7db5cd6f03951867e3","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":17570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-be0fc17cfe43ab5f959f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":10069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-beaa3406691cce197eda","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-bf6e8dfcb77c6e2ca2ac","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":18520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c0a53f27e3c7f00c3183","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel - Data Quality Incidents tab","durationMs":16580,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c1805fb6858404bea377","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":15660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c1ba3f2ea3699ed7ba49","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":25652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c295439fe870d89f8e3e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":21663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c2ead24a21c62c63dddf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":12078,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c37a1dcd7a72a8ab98bc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20742,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c419e22430f8d60c5f38","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":15201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c4d5c714289b65cd5065","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":15571,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-c723be406a26ef3415bf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15048,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ca5a4347882991d25ec0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":16251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-cbee4371fcd3aef15c86","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Selector should close vice versa","durationMs":16175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-cce5d4d36933d42e3bc0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":27511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-cd1b25a5a5e7c2a942f4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":30367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ce196a55488b928c2d30","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":20281,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ce268a04010e8041efb5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":25864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ce2c9e42affef0f8e984","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d03431d009cfb98964d5","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":19886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d19f58e4d5f295f56efa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":13392,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d1c622df7f7867c3494f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":18464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d246aab59a2dd5f44424","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":9666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d247c88f16904422d795","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":16927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d2612844f69066702a65","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":22350,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d3b17d6328d0a5be8f9c","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":14397,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d4574f5523cbdbd41ffb","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":8661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d485e529727a1a0f65a3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Column detail panel data type display and nested column navigation","durationMs":14399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d7f2d6a1270f33fc5c96","project":"chromium","file":"Pages/Entity.spec.ts","title":"Team as Owner Add, Update and Remove","durationMs":13652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d8c173ce639ccb75f5cf","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":25110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-d91d2f8bb2e0cdc843fe","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":21120,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dad73eda2f4b068c10c8","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":20838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dbcb8ef877e0a29eaa84","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":15713,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dd2889a0fa137f0ce3a9","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove for child entities","durationMs":20923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-dea1ccd58511090988d7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-debe98100f5126a60f3a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":19600,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-df5a5db4037d28aa590b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":28211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e042722a07ea0a3de54d","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20994,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e1446c2f53e8f61fe0aa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":18514,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e1bcfa96b3dd42189461","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":15007,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e1f23382e9baf6978200","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":20949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e241f0f086944e77301a","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":52390,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e24c535d92bc2f637cdb","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":24548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e366da710e50f4f64e8f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":21169,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e4e04c52194d563079e6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":10733,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e5c2865265d1af10ee7d","project":"chromium","file":"Pages/Entity.spec.ts","title":"Filter columns by tag prunes non-matching rows","durationMs":17347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e7bfd4ae8f07e04b2381","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":23715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e941ffbc92ab76be5259","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":15367,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-e9f5e0e08338ec03967f","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":26415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-eb01173d188cbe8393dc","project":"chromium","file":"Pages/Entity.spec.ts","title":"Inactive Announcement create & delete","durationMs":12172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-eb0d5e5b36d7c532a4d6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":21629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ec00f7977e836a98c1d6","project":"chromium","file":"Pages/Entity.spec.ts","title":"Description Add, Update and Remove for child entities","durationMs":20734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ec976ce21d731948f7ae","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":18734,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ed3bfea6fbaba7b39813","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":12164,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-eda0173586502e9586b8","project":"chromium","file":"Pages/Entity.spec.ts","title":"User should be denied access to edit description when deny policy rule is applied on an entity","durationMs":18269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-edae0655ec0cb6bdc6a4","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":19796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-edee178e64d24e4b5320","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":23065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-ee704d960a0d87348125","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":20672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f3f9c17a2c9aa8bc7f09","project":"chromium","file":"Pages/Entity.spec.ts","title":"Certification Add Remove","durationMs":31205,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f50fa4fafad289f59bf0","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":20694,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f56e37113ccb0ba50171","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":24163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f5b5f7e6288392d9c64c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update displayName","durationMs":6806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f6b50a299a49f1965028","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Propagation","durationMs":25185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f793562b25de9479b901","project":"chromium","file":"Pages/Entity.spec.ts","title":"Copy entity URL from header","durationMs":10537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f83796dc12fc01216f2c","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":24966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f9b076446ad4902e6057","project":"chromium","file":"Pages/Entity.spec.ts","title":"Domain Add, Update and Remove","durationMs":21358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-f9f0cc30af4d50635e45","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove","durationMs":25849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb095fce3e726deb2671","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag and Glossary Term preservation in column detail panel","durationMs":23327,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb1b344006049a57fe6e","project":"chromium","file":"Pages/Entity.spec.ts","title":"Announcement create, edit & delete","durationMs":26961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb26f3d3063f75474b76","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":17576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb54e3be502528a811a3","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":19917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fb5aa2f181bc190325c7","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tag Add, Update and Remove for child entities","durationMs":21221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fbb1b5d546048e8a6ce0","project":"chromium","file":"Pages/Entity.spec.ts","title":"UpVote & DownVote entity","durationMs":9333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fbf0ad523a6b32d423cb","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner with unsorted list","durationMs":23319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd02335b2dcae5e08711","project":"chromium","file":"Pages/Entity.spec.ts","title":"Glossary Term Add, Update and Remove","durationMs":25908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd73955b30bfc3f6b34b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Follow & Un-follow entity","durationMs":21358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd7481fb2c651161f990","project":"chromium","file":"Pages/Entity.spec.ts","title":"Tier Add, Update and Remove","durationMs":24665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fd930e32aac736574382","project":"chromium","file":"Pages/Entity.spec.ts","title":"User as Owner Add, Update and Remove","durationMs":21843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fdcf50e13a6a2a4bbd2b","project":"chromium","file":"Pages/Entity.spec.ts","title":"Delete File","durationMs":25393,"attempts":1,"retries":0,"outcome":"expected"},{"id":"92f4b5f6dbf60767921f-fe5a4733fff8ccf670fa","project":"chromium","file":"Pages/Entity.spec.ts","title":"Update description","durationMs":16040,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-0e1b5c1c44a8f2279d06","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the MlModel Service entity item action after rules disabled","durationMs":14856,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-1cd87d9dd281b2dece0d","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the SearchIndex Service entity item action after rules disabled","durationMs":17409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-2cb867da73a9a971f77a","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Container entity item action after rules disabled","durationMs":17805,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-30575d4022cfb3b0782b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Storage Service entity item action after rules disabled","durationMs":18659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-38d54bc660f074f9097b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Dashboard Service entity item action after rules disabled","durationMs":14851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-3b609306040a234cbfeb","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Messaging Service entity item action after rules disabled","durationMs":16406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-4cc494c7283e8466765d","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Database service","durationMs":59144,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-52a8397186c3af51af32","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the DashboardDataModel entity item action after rules disabled","durationMs":17337,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-609686451a9f7a7ebeea","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Api Collection entity item action after rules disabled","durationMs":17597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-61b78ce0d330fc59d4ec","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Table entity item action after rules disabled","durationMs":24358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-6737dba688f9167420f0","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Database Schema entity item action after rules disabled","durationMs":20943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-68f16dbd339a5bdbe466","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Database Service entity item action after rules disabled","durationMs":13699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-6b2ea7bfd8bb286c24f3","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Drive Service entity item action after rules disabled","durationMs":16680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-6efff7b892881b0179ad","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"should allow multiple domain selection for glossary term when entity rules are disabled","durationMs":5423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-7333face1ace08be4fd8","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Worksheet entity item action after rules disabled","durationMs":20487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-7b50302fbb1ca636773a","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Directory entity item action after rules disabled","durationMs":19518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-80572a8c0e9e51d6d17b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Api Service entity item action after rules disabled","durationMs":17016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-90309c057da02ade63a0","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the File entity item action after rules disabled","durationMs":19311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-90c89420e6df7139aab1","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Topic entity item action after rules disabled","durationMs":19518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-913e01f78ba46179b9c4","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Pipeline entity item action after rules disabled","durationMs":20050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-982c393f021f67ee967c","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the ApiEndpoint entity item action after rules disabled","durationMs":20711,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-98909ef36befccbe6fbb","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Database entity item action after rules disabled","durationMs":19494,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-afbe709e30f6facd3dbd","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Database Schema","durationMs":51041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-b06f911eea6817b73cad","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Chart entity item action after rules disabled","durationMs":20574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-b13f119926cde07f3531","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Store Procedure entity item action after rules disabled","durationMs":19531,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-c83bce24def2c5be23fa","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Metric entity item action after rules disabled","durationMs":12569,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-cc81aa5e99065f424e4b","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Spreadsheet entity item action after rules disabled","durationMs":17357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-d1dd9a785ec3db3fd0e3","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the SearchIndex entity item action after rules disabled","durationMs":19850,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-e4bf750e93899dca5942","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Pipeline Service entity item action after rules disabled","durationMs":18171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-e5bc6e17521e70fe27d4","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the Dashboard entity item action after rules disabled","durationMs":19923,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-eb3f22266d782e009e06","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Database","durationMs":59659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9308de5e0d9b01cc3b0e-f66c740a854d5362dc0f","project":"DataAssetRulesDisabled","file":"Features/DataAssetRulesDisabled.spec.ts","title":"Verify the MlModel entity item action after rules disabled","durationMs":15457,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-010a5c0cb7d2aa43b4e6","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"built-in relation type shows M:M cardinality in the cardinality map","durationMs":34520,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-26134fc2ed2b34ae9ce4","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"cardinality map is populated when edge labels are on (default)","durationMs":34076,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-42930591193b65ce7249","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"MANY_TO_MANY relation type should have label \"M\" on both ends","durationMs":34150,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-43a99786fe79755b89b9","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"edges for cardinality-typed relations appear in the graph edge data","durationMs":34302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-4721e6b8fc9bcbc4080e","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"stats reflect the cardinality-typed edges in the relation count","durationMs":34054,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-4ad4422093a1862c9ac9","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"MANY_TO_ONE relation type should have \"M\" at source and \"1\" at target","durationMs":34090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-56c3132792953bd52609","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"graph renders without error when cardinality relation types are active","durationMs":33908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-70353e5908dbdf148f9d","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"CUSTOM relation type with sourceMax=1 and no targetMax should produce \"1\" → \"M\"","durationMs":36565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-ae82da3861a5051db70a","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"graph remains stable after toggling edge labels off and back on","durationMs":34136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-b276a74b45becd923aaf","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"ONE_TO_MANY relation type should have \"1\" at source and \"M\" at target","durationMs":33984,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9323ee980f727f1b1d5b-c3ad9884715acf7b9b76","project":"chromium","file":"Features/OntologyStudioCardinality.spec.ts","title":"ONE_TO_ONE relation type should have label \"1\" on both ends","durationMs":37311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-05afe72e2517126b831c","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S01: Selecting ME child should auto-deselect siblings","durationMs":12388,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-07c5485ffe70af9efaf5","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H05: ME glossary (top level) children render checkboxes with ME behavior","durationMs":11179,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-1fd7aeb46dbe55939735","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H06: Deep nesting - non-ME parent under ME grandparent allows multi-select","durationMs":10835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-39d8b39132ab09f17d4d","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-T02: Apply ME term to table column via detail panel","durationMs":14087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-490fe051b00e05508785","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S05: Mixed selection - ME siblings deselect, non-ME remain","durationMs":12841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-4eb760f5a611886c7801","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H04: Toggle ME flag via edit after children exist","durationMs":16277,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-59cbad295850012fe314","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-R01: Children of ME parent should render checkboxes","durationMs":13508,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-7db74194a6481c407de8","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S03: Can deselect currently selected ME term","durationMs":11878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-982e188c2d0faee81352","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-S02: Can select multiple children under non-ME parent","durationMs":12860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-c73698374be52746af65","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-T01: Apply single ME glossary term to table","durationMs":11428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9380cd5f2172e9a1a418-dd551949ba09fa30d34a","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivity.spec.ts","title":"ME-H07: Non-ME parent under ME glossary allows multi-select for its children","durationMs":10662,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-19d2e2f60fe8424ceb98","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should cancel deletion and preserve sample data","durationMs":8027,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-2d25e25ebbc138c884ef","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should display sample data tab with rows and columns","durationMs":5540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-60a661d10879c9cc9007","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should show only export option for data consumer without edit permissions","durationMs":7045,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-887ef71abcfe0e95a672","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should show empty state for table without sample data","durationMs":4151,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-955c7fc1aacedef99996","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should download sample data as CSV when export is clicked","durationMs":5782,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-aea7d9d516ae343cd09b","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should open delete confirmation modal","durationMs":6296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-bc8f12de342882c9876e","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should change row limit using the selector","durationMs":5581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-c79b78f0d0a5b6acc220","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should show export and delete options in manage dropdown for admin","durationMs":6106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-d03354ab10143b83b4f1","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should render sample data for columns with reserved names","durationMs":5161,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-eabdba275e13219c035b","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should delete sample data and show empty state after confirmation","durationMs":6401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"939870cd9e56b1f49a39-f5b810780f21ec70c533","project":"chromium","file":"Features/SampleDataTableOperations.spec.ts","title":"should persist row limit selection after switching tabs and returning","durationMs":8374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"93bd9f4090791ca89375-80c585ad9ba6f0b328b8","project":"Ingestion","file":"Features/TestSuiteMultiPipeline.spec.ts","title":"Edit the pipeline's test case","durationMs":8448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"93bd9f4090791ca89375-9e57b2112f917b31f412","project":"Ingestion","file":"Features/TestSuiteMultiPipeline.spec.ts","title":"TestSuite multi pipeline support","durationMs":15355,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9467adbab3a83cfec66c-3dae36d63205fa0caf33","project":"chromium","file":"Features/Glossary/GlossaryRelationsGraphPerf.spec.ts","title":"opening Relations Graph tab does NOT fan out per-Id glossary term fetches","durationMs":12983,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-1e4bd98b74ceda0fe09c","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should not offer Test Login for a confidential client","durationMs":7319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-3aa538554a17e9a1b306","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should offer Test Login for auth0 as a public client","durationMs":8383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-80d48f5a288d4db55b18","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should show the resolved identity when the test login succeeds","durationMs":7943,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-91d295ca2e48b253e2c9","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should offer Test Login for okta as a public client","durationMs":6949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-a25eb06064c876ff691a","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should not offer Test Login for SAML","durationMs":7381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-c1c499b12b7762408bb7","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should not offer Test Login for LDAP","durationMs":7489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-e21597b879b2be344862","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should show the failure reason when the configuration would reject the login","durationMs":8157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"94818779029e61db2c94-fed6410cd76bffb3a1f0","project":"chromium","file":"Features/SSOTestLogin.spec.ts","title":"should offer Test Login for google as a public client","durationMs":5752,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-28d3656567a51c3d6dd1","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":11188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-2bd6a7f1da1b57259832","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":10681,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-351b07cb01348ee01865","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":8609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-680178bebcb35c8d0570","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names in Explore Summary Panel","durationMs":10163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-addabe3e2b1839a794b3","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names in Version History","durationMs":7656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-c64a38d97f36769aaae3","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":9374,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-e55a329b63a2050517c2","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":8442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f694e0831ef9afa291f6","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":9730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f73ff4b1baddd098ad83","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":9495,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f8a6fc0f3baf8682f689","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names in Profiler Tab","durationMs":12157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"954b70112d570270f615-f8d08bd67e5189c8a6e8","project":"chromium","file":"Features/NestedColumnsExpandCollapse.spec.ts","title":"should not duplicate rows when expanding and collapsing nested columns with same names","durationMs":7468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-00c41106f8eca12d9a6a","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Worksheet","durationMs":18172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-0ec1ae19f5783c5db694","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Database - closing version drawer navigates to entity page without tab","durationMs":10411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-367e0529fecd218661bc","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Directory","durationMs":18897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-384ea6bd7b52e528d275","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Table","durationMs":27246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-3a435f2426b65f5fcb06","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Container","durationMs":23767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-46b4c939b2a66ef2b79a","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"DatabaseSchema - closing version drawer navigates to entity page without tab","durationMs":10871,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-56bad44722170d3bf33b","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Dashboard","durationMs":19981,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-5b4eee1a2c982dc07a0b","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"MlModel","durationMs":20537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-79688ef1070ce564ebe8","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"SearchIndex","durationMs":21968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-89220cdd73aa9b8291a7","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Store Procedure","durationMs":20002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-94b43b544c431b49fa87","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Table - should show historical column descriptions in version view","durationMs":10973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-a2db654e9810d2d0b299","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"ApiEndpoint","durationMs":20456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-ac166e994782e916f5d6","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Table - closing version drawer navigates to entity page without tab","durationMs":12106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-b5ec54360f22d1b13764","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Pipeline","durationMs":19463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-d2324e735fc64ab4d022","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"File","durationMs":19246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-d6a35e540eacbde345fb","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Topic","durationMs":22368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-dcb2e97f35988ad7b740","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"DashboardDataModel","durationMs":21177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9571fe92ad0469efc018-fd945c597e9f89b122f5","project":"chromium","file":"VersionPages/EntityVersionPages.spec.ts","title":"Spreadsheet","durationMs":19213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"95abbb840354c898cbad-34fea57348ad3c34f876","project":"chromium","file":"Features/Glossary/GlossaryApprovalAfterMove.spec.ts","title":"rejecting an open task succeeds after the parent term is moved under a sibling","durationMs":15842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"95abbb840354c898cbad-3aaed8dc99103d883367","project":"chromium","file":"Features/Glossary/GlossaryApprovalAfterMove.spec.ts","title":"approving an open task succeeds after the parent term is moved under a sibling","durationMs":18800,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-2fa097ab78b1de01ba8b","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"non-assignee should be able to add comment","durationMs":11666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-4044e26f020808eeeb02","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"assignee should be able to add comment to task","durationMs":11624,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-499a39f09e66aa4d428e","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"POST /tasks/{id}/comments should add comment","durationMs":31,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-6615c1b10bfdc115c4f2","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"GET /tasks/{id}?fields=comments should return comments","durationMs":7,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-7d04368e1ade72494167","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"selecting user from @ dropdown should add mention","durationMs":11286,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-7d73e30d5f57254faedd","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"should be able to delete own comment","durationMs":8091,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-8d821b64fb7359981457","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"non-author should not see edit/delete options","durationMs":8116,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-8ecdb599b122929a7165","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"comment author should see edit/delete options","durationMs":7557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-b16f7fa7ab19dc6d68ab","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"admin should be able to add comment to any task","durationMs":10680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-e74262a4256762b27023","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"typing @ should show user suggestion dropdown","durationMs":10559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"969d592f9a1ff138340d-ff55d1327b746f190307","project":"chromium","file":"Features/Tasks/TaskComments.spec.ts","title":"should be able to edit own comment","durationMs":7637,"attempts":1,"retries":0,"outcome":"expected"},{"id":"980a32fafab996c34f4c-3a5c1a8728e9f65e696a","project":"chromium","file":"Features/Tasks/TaskAssigneeManagement.spec.ts","title":"admin can reassign an existing metadata task from the task details page","durationMs":10461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-502ba903b9d98f4b6361","project":"Basic","file":"Features/Dashboards.spec.ts","title":"should change the page size","durationMs":7252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-606502ef644302893802","project":"Basic","file":"Features/Dashboards.spec.ts","title":"should be able to toggle between deleted and non-deleted charts","durationMs":13951,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-a9186932ace2c0e8aded","project":"Basic","file":"Features/Dashboards.spec.ts","title":"should display data model when service name contains dots","durationMs":5934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"99a4f3601d57ec84a21a-ab012b7a43d0b2fea651","project":"chromium","file":"Features/Dashboards.spec.ts","title":"expand / collapse should not appear after updating nested fields for dashboardDataModels","durationMs":14352,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a109e5bd20f766cfd0b-cae5f8ac7fb76a194f42","project":"Basic","file":"Features/CustomizeNavigationNewItems.spec.ts","title":"new sidebar items absent from saved persona nav are toggled OFF in admin settings and hidden in sidebar","durationMs":14709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a109e5bd20f766cfd0b-f3a369e4a4413c840fc3","project":"Basic","file":"Features/CustomizeNavigationNewItems.spec.ts","title":"cancel button on customize navigation shows a single confirmation modal and Discard exits the page","durationMs":10550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-01bd0c44f0f49343c457","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":5318,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-21df6d035bdfa80c9962","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5035,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-2ce7e69a85607992ac60","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-2f39ba17e3d032870fe7","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4736,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-3c75ccb62f351a160e0a","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a table-scoped user sees tables but never dashboards","durationMs":10988,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-3cc9ff5d69980702f3cd","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":5086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-499cc24a0ae76d742af4","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4842,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-4abdb862b466e0e7c4ed","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4902,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-4d1b8bd26d4658097189","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-574ca7618da3f2f3ca61","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a dashboard-scoped user sees dashboards but never tables","durationMs":11522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-6c38a2a0c5e8fa49d2ef","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-6ddfec14585b9ddd1059","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"the browse tree only shows the asset-type categories a user can access","durationMs":13059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-740ca699b4783a25a25e","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-742a40dd2d1eb06da541","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-87cc8fd5ad9434623334","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a fully denied user sees neither asset type when browsing","durationMs":9254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-912df73111d625a0803d","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5087,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-950c1df173e71bdc12e8","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-956aebac642646bfa5dd","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4712,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-a9257c1d69db95a1fd68","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":6823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-b18d71356f6988da426f","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-ba2b5d8d484e2f24ea82","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":4701,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-bb51860dedb5584d3392","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"a user permitted on all asset types browses both","durationMs":12825,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-bc6de9691f9f161ee64d","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":5250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-c079cb6b3b96546c506b","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4728,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-c268cdd384dadfb181a8","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4745,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-c54f4b84f6f604c133dd","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":7157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-cc3cb9faa9cc57493e9f","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User with permission","durationMs":5591,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-ee381a738fbd0dc4377d","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a59ac2e535f176cdcd0-eed2b6cdaa2a0c64e969","project":"SearchRBAC","file":"Flow/SearchRBAC.spec.ts","title":"User without permission","durationMs":4445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-05f708f2d1cdfd1fa6d1","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify if string input inside oneOf config works properly","durationMs":4297,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-15c93e78abaa0de33616","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should persist empty schemaRegistryTopicSuffixName when the field is cleared","durationMs":4798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-266d14068dc8b304eeca","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify SSL cert upload with long filename and UI overflow handling","durationMs":5036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-47ed6f62b24203eb27e4","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should show service name error and not open modal when test connection clicked without service name","durationMs":3634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-8d4708988dded1567bfb","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should include service name in missing required field count shown on test connection card","durationMs":3546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-a047a9cda0d5b9f201b1","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify form selects are working properly","durationMs":8030,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-a5c7eb4bf34fc5b40e02","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"Verify service name field validation errors","durationMs":5813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a5dacf234a0bce82036-f0abdfb7867ffaf3d72d","project":"Ingestion","file":"Flow/ServiceForm.spec.ts","title":"should focus the service name input when test connection is clicked without a name","durationMs":4141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-2135732f3cee91474e0a","project":"chromium","file":"Features/Tasks.spec.ts","title":"task link should NOT navigate to wrong URL like /table/TASK-xxxxx","durationMs":8744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-4cc20545f3ea89a5cb3f","project":"chromium","file":"Features/Tasks.spec.ts","title":"clicking task in activity feed should navigate to entity page with task tab","durationMs":13568,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-5f056158560407af55cc","project":"chromium","file":"Features/Tasks.spec.ts","title":"accepting task without edit permission should be rejected by backend","durationMs":1046,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-70993b1999a80774e963","project":"chromium","file":"Features/Tasks.spec.ts","title":"should create request description task from entity page","durationMs":9546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-9d610b2a4bf240005c7a","project":"chromium","file":"Features/Tasks.spec.ts","title":"non-assignee without edit permissions should NOT see approve button","durationMs":9905,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-cca01761a6bce7840070","project":"chromium","file":"Features/Tasks.spec.ts","title":"task should appear in \"My Tasks\" filter for assignee","durationMs":9312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-ce441478210b113bc6e8","project":"chromium","file":"Features/Tasks.spec.ts","title":"task count in Activity Feed tab should match actual tasks","durationMs":9659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-ce84dc240cc971195d1e","project":"chromium","file":"Features/Tasks.spec.ts","title":"should create suggest tags task","durationMs":7663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-cf8f3ae2b0df3d4acbae","project":"chromium","file":"Features/Tasks.spec.ts","title":"should allow manual assignee selection when entity has no owner","durationMs":11110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-d0117757d14e7f9f21e5","project":"chromium","file":"Features/Tasks.spec.ts","title":"tasks should respect domain filter when domain is selected","durationMs":414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-e340914676cf0a37e04a","project":"chromium","file":"Features/Tasks.spec.ts","title":"/tasks/count API should return correct counts for aboutEntity filter","durationMs":38,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-e4cc23c6e6759c544109","project":"chromium","file":"Features/Tasks.spec.ts","title":"assignee should be able to approve task","durationMs":9582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9a655e973f0904bc0fc2-ecba6f0d13b071ccda94","project":"chromium","file":"Features/Tasks.spec.ts","title":"creating a task should appear in entity activity feed","durationMs":9454,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9ad28d1300bc7e823686-45b8fb897f98a5e0274c","project":"ImportExport","file":"Features/LineageExportPNGSnapshot.spec.ts","title":"exported PNG includes edge lines between nodes","durationMs":15879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9afd1effa5e585c919c1-0202e91439f881e1c55b","project":"chromium","file":"Pages/AppStopRunModal.spec.ts","title":"should show stop button for running app runs with supportsInterrupt=true","durationMs":4714,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9afd1effa5e585c919c1-e120f5235a1f6bdd9b6c","project":"chromium","file":"Pages/AppStopRunModal.spec.ts","title":"should close stop modal when cancel is clicked","durationMs":6808,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9afd1effa5e585c919c1-fc943d277ec271917f28","project":"chromium","file":"Pages/AppStopRunModal.spec.ts","title":"should open stop modal when stop button is clicked and call stop API with runId","durationMs":5774,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-0f35c21074decaa9ede6","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import full ODCS contract with all sections from test-data file","durationMs":6679,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-192e2055cc5d10d95676","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import button disabled when schema validation fails","durationMs":8755,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-19d6c07cf1b64b9600ef","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with wrong kind shows error","durationMs":8761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-1b2d52f8844a5db4ab7c","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import malformed ODCS YAML from test-data file shows error","durationMs":7558,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-1dbb8d203da32d4198bd","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import malformed JSON shows error","durationMs":8460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-2a4f6681e24c3ed945c5","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with wrong apiVersion shows error","durationMs":8062,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-2f6345811939517d83af","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Merge mode - adds SLA to existing contract and verifies export","durationMs":9832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-31f5f908ebafe7e82206","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import invalid ODCS missing required fields shows error","durationMs":8575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-3ced6bde454b2b7e8dd5","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Schema validation shows warning when fields do not exist in entity","durationMs":7887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-3d1f611b09e8c9ef621f","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Verify SLA mapping from ODCS to OpenMetadata format","durationMs":9410,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-4006caf2f955fd60d10c","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS full contract and export both formats","durationMs":9288,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-460adca51a4ffd67a61f","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS and export as OpenMetadata YAML","durationMs":8787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-4a8aff38de2e68a8df0b","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Single-object ODCS contract does not show object selector","durationMs":7912,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-5eaab8c7bd23d55a1e79","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Export ODCS YAML and verify download","durationMs":9068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-5ef3cdccd67443bc6683","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS missing apiVersion from test-data file shows error","durationMs":6963,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-6625cb02e6927aa9d5f5","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Schema validation shows loading state during validation","durationMs":7710,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-6711a9829a0c3d96f2fb","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import basic ODCS contract from test-data file","durationMs":7157,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-68261486d0f6a0937ae2","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with security/roles","durationMs":8642,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-69ef911b31d21c257033","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with SLA, modify SLA via UI, export and verify SLA changes","durationMs":9324,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-716a0af0d51f4b0c05a3","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"OM format export and import round trip - create, export, delete, reimport","durationMs":10444,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-7289ec2ac14dfd1f6f3f","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Create contract from UI, export OM format, import with merge, verify data","durationMs":10412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-7e6cc49f08adc16d1b20","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS missing status from test-data file shows error","durationMs":6940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-81f8e3c6a41a1ca48ae1","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with timezone in SLA properties","durationMs":9469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-85188b1415ad6420ab68","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import minimal ODCS contract (inline)","durationMs":8785,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-8abf2104f87c2c423be3","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS contract with draft status from test-data file","durationMs":7565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-8f5576117ee809a480e6","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import button disabled for empty/invalid file","durationMs":8529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-955bd6b3717101c17e96","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import modal shows contract preview","durationMs":7940,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-9bd1f1c0379d9ba1bc85","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Multi-object ODCS contract - selecting object enables import and completes import","durationMs":9483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-9cbea79159672c071dca","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS, modify via UI, export and verify changes","durationMs":10925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-9ecf02851221f72256af","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with quality rules","durationMs":7972,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-a067522af929e79d8feb","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS contract with v3.1.0 timestamp types from test-data file","durationMs":6830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-a739845e4bd30e73b5ca","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import malformed ODCS YAML shows error (inline)","durationMs":7703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-b6dd2e6c92f5df98758b","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import empty ODCS file from test-data shows error","durationMs":7416,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-bf1bae508168e3d1e634","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with missing kind shows error","durationMs":8843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-c0fa5a97a138476da251","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Replace mode - replaces existing contract completely and verifies export","durationMs":10131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-cdde1df839425a25a0a1","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import basic ODCS contract from JSON file","durationMs":6204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-d6cd55a44daa5b90e276","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with team owner","durationMs":8452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-d811f2d3334254dcd9ed","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with team - contract created successfully","durationMs":8537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-d9eb674411099336a31c","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with description and verify OpenMetadata export","durationMs":8764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-e2b3327bc7912c609caf","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS contract with SLA properties from test-data file","durationMs":7219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-e6894a820e4c2bd0b240","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Multi-object ODCS contract - object selector shows all schema objects","durationMs":8847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-ed87d9c194896f26bca4","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import and Export round trip preserves data","durationMs":9131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-f28fe520f971d27d8446","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import modal shows merge/replace options for existing contract","durationMs":9096,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-fd4e6a08a2e6352429e4","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Schema validation passes for contract without schema definition","durationMs":8769,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-fd4fe81957752c4ec749","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with markdown description and verify proper rendering","durationMs":8198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-ff3c5fa9f1add6937c34","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Multi-object ODCS contract shows object selector","durationMs":8624,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9c7a600ef426de5ea159-ffaf98193d721452ffae","project":"ImportExport","file":"Pages/ODCSImportExport.spec.ts","title":"Import ODCS with mustBeBetween quality rules","durationMs":8721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-18e907f752a27b9fd8f4","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should remove color style from term via API","durationMs":5339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-2e06e5f79b5342eb895b","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle slow network gracefully","durationMs":6619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-4be98a038f7f6d90544c","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should toggle right panel if available","durationMs":11794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-60f3a3a6f980a1710221","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should maintain session during normal operations","durationMs":12234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-71c925d8cc7e6e9e0f84","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle multiple rapid API calls","durationMs":4683,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-76908643a0ccaaad6346","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle concurrent edits gracefully","durationMs":5725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-878af780737d76e41560","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should show error state when navigating to non-existent term","durationMs":9328,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-8a7c4e91436fda6d3935","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle back/forward browser navigation","durationMs":8799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-924d084a3f4444d723a0","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should show error state when navigating to non-existent glossary","durationMs":13279,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-965c8728bc5707ff2891","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should display vote count correctly","durationMs":9765,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-9c0db9327f0f692940cb","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle rapid UI interactions","durationMs":8644,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-9ef033615f0c8e9adaba","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should access activity feed for comment deletion","durationMs":10319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-a80bbe7b29b7f5294127","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should create glossary with unicode characters in name","durationMs":7814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-cfc97af221ec552f6cea","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should navigate to activity feed for potential reply","durationMs":10503,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-d637d349d549b264ba20","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should show loading state during navigation","durationMs":7596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-db81d92799b0260ba3e1","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle deep nesting","durationMs":7605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-dd0193b528ac0cc08e96","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle special characters in search","durationMs":9148,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-ddf92ab2430d94cef427","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should validate reference URL requires http/https prefix when creating term","durationMs":10702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-e1d992484f80ae957313","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should access activity feed for comment editing","durationMs":10468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-ecb9d2b60fc9eca2443a","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle unicode and emoji in description","durationMs":5124,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-ed70fc607bee136a3107","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should remove icon style from term via API","durationMs":6249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-f43f9cd9f7fbd515d485","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should validate reference URL requires http/https prefix when editing term","durationMs":9918,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9cc140ad818dd8f839cb-f8941f3c4da10be24228","project":"chromium","file":"Features/Glossary/GlossaryP3Tests.spec.ts","title":"should handle special characters in term fields","durationMs":5512,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-07574f3b25dc8f46c484","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"changing filter triggers feed reload","durationMs":14586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-1173de139d4490806e45","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"thread drawer opens from reply count and allows posting a reply","durationMs":11966,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-1335947fa4b03d96813f","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"emoji reactions can be added and toggled off on a feed card","durationMs":21708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-31479e975ac3666e1eb9","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Activity is NOT fetched on the Tasks tab","durationMs":22282,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-35c570d98d2467d720f3","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"All tab shows BOTH the change-event activity and the conversation","durationMs":13414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-46b3850bbde88dd8310d","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"clicking title navigates to explore page","durationMs":12930,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-4ac140c63ccab4a5c05b","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"emoji reactions can be added when feed messages exist","durationMs":13115,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-4d4b4e89a4ca2e98410f","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"A change-event activity is read-only (no comment editor)","durationMs":13819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-5244da4b0aa29bf0630b","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"feed cards render with proper structure when available","durationMs":14346,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-604a1c44e103c45d9f70","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"footer shows view more link when applicable","durationMs":12780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-61bc9c12ef74eb4cf8a2","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"feed body renders seeded activity and no empty state","durationMs":10735,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-64596f97a3fbdf51e660","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Auto-selects the first (newest) item on load","durationMs":16854,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-68489d3f1d6a2809b41b","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Mention notification shows correct user details in Notification box","durationMs":53792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-68f33945efb071cc7b3c","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"All badge, header and rendered list agree on the count","durationMs":14770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-7473d2f630419808009a","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"feed body renders content or empty state","durationMs":14296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-83cf6e6b868810252caa","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Should encode the chinese character while mentioning api endpoint","durationMs":28053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-a51da9cec73635e3f956","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Reacting to an activity updates its reactions in the right panel","durationMs":16819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-b34a388652104d9c2adf","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"renders widget wrapper and header with sort dropdown","durationMs":13301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-b7a79cfd6d332ab6a9ef","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"feed cards render header text and timestamp","durationMs":15249,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-b917a15ff5b8cef9a210","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"activity cards expose no thread affordances on the landing widget","durationMs":11975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-cad6a5c4e6a065a22382","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"Replying to a conversation stays isolated to that thread","durationMs":17849,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-e3bfaac1e8763ed104e3","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"changing the filter refetches from that filter endpoint","durationMs":17401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9de335d5f17b18a6dcce-fe5f04441aa37dd7e33b","project":"chromium","file":"Features/ActivityFeed.spec.ts","title":"footer view more navigates to the user activity feed","durationMs":17528,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-0c3742a13b407ddb1cc3","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"graph edges contain all four expected relation types","durationMs":34348,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-11da3b1b11d4cae1a880","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"toggling edge labels off and back on leaves the graph and cardinality map intact","durationMs":35063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-2c64f9ac27a0e6010ad6","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"stats show 3 terms and 6 relations","durationMs":36986,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-43cd026e798dfe71575e","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"PNG export triggers a file download","durationMs":37505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-5067aff399736bcb7da0","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"built-in relations show M:M cardinality in the cardinality map","durationMs":34003,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-5b4c575ee1cc48ba3948","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"entity panel closes via the close button","durationMs":37473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-92754c72121d1b93fe6b","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"Cross Glossary mode renders without errors","durationMs":34467,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-9db862bed037d672ee13","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"Hierarchy mode renders without empty state","durationMs":35894,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-a00f8f40b48cecafa66e","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"returning to Model mode re-enables view-mode select","durationMs":34748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-a99cd08047b8f9afb2a0","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"searching for a term shows it and its neighbours","durationMs":34448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-b68c65e3513929234dfe","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"Data mode loads and view-mode select becomes disabled","durationMs":35020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-c11307fd1bd24709d052","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"clicking a node opens the entity summary panel","durationMs":38033,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-c42263c10ae09f8a3ea8","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"canvas renders without empty or error state","durationMs":36474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-c7e0428ae7480131220b","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"custom ONE_TO_MANY relation shows \"1\" at source and \"M\" at target","durationMs":34344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-d2abab3f25ffe02ebbfc","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"switching back from Hierarchy to Overview restores stats","durationMs":35093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-d5824faedafcf985cdd1","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"all three term nodes have canvas positions","durationMs":36002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e275bb0f002b384c76f-f429e28f07d3c109d0dc","project":"chromium","file":"Features/OntologyExplorerE2E.spec.ts","title":"searching for a non-existent term shows the empty state","durationMs":34391,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-11140668a17507e05e02","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should decline suggested tags for a container column","durationMs":21111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-3fba22fa292eaa50e22d","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should add and accept requested tags for a topic schema field","durationMs":18751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-9dc22a9af80b1fa9cfae","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should edit and accept suggested tags for an api endpoint response schema field","durationMs":20504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-9fed25271f4f186bfcc7","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should add and accept requested tags for an api endpoint request schema field","durationMs":19759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-ba77fe27b9c8b69516b3","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should decline requested tags for an api endpoint request schema field","durationMs":19926,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-d0551ac8b9f8301ca2c4","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should add and accept requested tags for a table asset","durationMs":21357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9e4e0cfd329faf10614f-d531746745c03d1762f1","project":"Basic","file":"Features/TagsSuggestion.spec.ts","title":"should edit and accept suggested tags for a table column","durationMs":20585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9ed17cc140d9dae5cefa-915b82974cf126a20c07","project":"Basic","file":"Pages/SearchIndexApplication.spec.ts","title":"Search Index Application","durationMs":94456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f4a33ecae6044b97b31-397a31ef612a9cd22653","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":24529,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f4a33ecae6044b97b31-39f179a759a52a3cf6bf","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":23537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-0c77063b075cd2218b64","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Add multiple assets to domain at once","durationMs":23815,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-150901c3f10832888634","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Domain expert can edit domain description and tags","durationMs":10740,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-15e005f1d34e3a6e91bb","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User can access subdomain details page","durationMs":9937,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-1fd742df39877e21d187","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Create domain with Consumer-aligned type","durationMs":5868,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-282c644961afe61e396f","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User with domain policy is restricted by policy rules","durationMs":7321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-324394d635553ef6bbd9","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Move assets between data products","durationMs":16504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-32f02b57703f0fd30474","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Remove multiple assets from domain at once","durationMs":26583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-4dcdd2eebb877744a5c5","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"cancel on remove warning modal keeps the asset in the domain","durationMs":15493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-56b6436ccda2c8b73c52","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Domain expert can manage data products","durationMs":9876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-666ba1d32392604cd1bc","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User with domain access can view subdomains","durationMs":10119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-819313d6cecc45fab023","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Search for domain by name","durationMs":6707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-8dc0507b83acfc53b208","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"bulk remove with linked data product shows preview and commits on Remove Anyway","durationMs":16006,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-8e3f81f3f90e64078015","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Domain version history shows changes","durationMs":6603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-955a8dbabb161a4beaa0","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Move table from one domain to another via API","durationMs":15621,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-ab211f09d5811053d09e","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Data product version history shows changes","durationMs":6190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-adaeb2de85e70d54ae8b","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"User can access assets in their domain","durationMs":6612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-c69dc92b1359a41fe17a","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Admin can edit domain description","durationMs":8665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-ce0ffa999074479a54bc","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Filter assets by domain from explore page","durationMs":10057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-d37104457e75884f3713","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Create domain with Source System type","durationMs":7384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-d9bf6730027f5b915dd3","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Move asset from domain to subdomain via API","durationMs":9619,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-de11d803d3ba43723914","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"single-asset remove with linked data product shows preview and commits on Remove Anyway","durationMs":15973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9f8cc763c44230911948-e563dc0fe24a7af54e2e","project":"chromium","file":"Pages/DomainAdvanced.spec.ts","title":"Admin can edit data product description","durationMs":8909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"9fe7868e0725fd08d542-2a33bc057bd25c30e0df","project":"chromium","file":"Features/GlobalSearchSuggestions.spec.ts","title":"Navigate to column from column suggestion","durationMs":10511,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a0186dbcfd84f2af2f9f-a40369a24b242b3392ec","project":"Ingestion","file":"Features/SchemaSearch.spec.ts","title":"Search schema in database page","durationMs":5189,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-0ae2bb3733d624c024dd","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"unchecking a section removes it from the save payload","durationMs":8333,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-128faf764b2094a1dd47","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"blocks saving a rule whose name already exists","durationMs":6858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-13f15301823fa7fc290e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"fully-completed Service Is condition allows save","durationMs":9213,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-165117ac5003f66952d3","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"reverts the enabled toggle when the settings update fails","durationMs":6763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-181d99405195b5be8571","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"measures the large-document preview render cost","durationMs":8905,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-1b2cccd7ba58f5524ae5","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"View in Explore link href reflects the selected entity type","durationMs":8767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-25e888b3698832fb24e1","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"preview modal closes via the Close button","durationMs":7544,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-40a176725b94f0690dfe","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"saves a rule that has no filter conditions entered","durationMs":7976,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-415ad87de311a2b1b6a4","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"closing the edit drawer without saving leaves the rule card unchanged","durationMs":7298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-4480787c897bd9dc2248","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"blocks saving a rule whose condition has no value entered","durationMs":8888,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-6a82cd78885e2806d215","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"builds real version history and restores an earlier version","durationMs":7861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-8090445d856b4d0cd9e8","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"configures every entity type, behavior, section, filter, and setting","durationMs":13793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-828ef3dceb665f378f3e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"links View in Explore to the entity-type explore tab","durationMs":7094,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-8dfdf276499f70900418","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"rule card displays the matched asset count returned by the server","durationMs":6103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-98bada33ef80e6d7e279","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"Custom Properties filter sub-fields load instead of showing No data","durationMs":6167,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-9aaf50b5db8b4df00c5c","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"previews one byte-consistent document in rendered and raw modes","durationMs":9602,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-9c68cfb1faff12a1f1c0","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"compound OR conditions are serialized into the save payload","durationMs":10794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-a4b6b4cc72eb7ef6e32b","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"retries the preview after a failed document load","durationMs":7832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-b7fd2e2cd7de95d73f93","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"round-trips real configuration, rule CRUD, and preview endpoints","durationMs":320,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-b96d656abfc8d38d7e1e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"shows the empty version history state","durationMs":6552,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-c7732c7d2e3075a25bfa","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"clears the filter error once the unfinished condition is removed","durationMs":8469,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-cdf1397a75540445ad46","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"clears and persists the character budget and cache TTL","durationMs":6934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-ce5988a4f5195a6025f0","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"edits and deletes a persisted rule and returns to the empty state","durationMs":9952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-cfcd775ce0067edae694","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"rolls back the optimistic rule and toasts when the save fails","durationMs":7349,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d03dca810159c545c5e5","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"failed cache state shows the failed badge and the compilation error","durationMs":6257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d5681daa733b359d418e","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"stale cache state shows the stale badge on the settings card","durationMs":6289,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d800895fca74449be850","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"shows the truncated count in the preview stats","durationMs":7247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-d966f6ff2e1a264ff9dd","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"rule description is included in the save payload","durationMs":7715,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a086ff365d23930bad47-ee53f7c7d6fb560349ca","project":"chromium","file":"Features/PersonaAIContext.spec.ts","title":"surfaces the generating cache state and settles to fresh","durationMs":9847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-12ea21bc43a14aa83acc","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Certification field","durationMs":11702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-246e661506d36a1825dc","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Domains field","durationMs":10971,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-28f6e412ffc6df40796a","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Tags field","durationMs":8880,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-6741225215bb41e46a05","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Database field","durationMs":13603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-91cd076c579f49087395","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for API Collection field","durationMs":10188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-9e5984c4da4bd77a035b","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Database Schema field","durationMs":11953,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-b66659cc52783fdf9373","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Glossary field","durationMs":9572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-d47b5c11bf1fb831cc62","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Data Product field","durationMs":10707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a1c320a71d0296319943-e22c85dbbb620fba80b6","project":"chromium","file":"Features/AdvancedSearchSuggestions.spec.ts","title":"Verify suggestions for Tier field","durationMs":10496,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-009d9c01a74b2fc9aee4","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Verify columns are visible in explore tree hierarchy","durationMs":8362,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-020e72fabdce33d085db","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link button should copy the field URL to clipboard for SearchIndex","durationMs":13882,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-17559e58aad3ece85d94","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Check listing of entities when index is all","durationMs":5220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-237705007de3a03c4b7b","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link button should copy the field URL to clipboard for APIEndpoint","durationMs":13780,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-363cdb367cd5173de8de","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Explore Tree","durationMs":9911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-39d0a4ec826f84977548","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Check the listing of tags","durationMs":8735,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-3ce419b0b546761dee81","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Verify Database and Database schema after rename","durationMs":15290,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-4ebd5bf5ff4dfe3d77ef","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Check listing of entities when index is dataAsset","durationMs":5653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-6b458a8502d75fbed179","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link should have valid URL format for APIEndpoint","durationMs":16919,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-95045ebebe3be165bea5","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Copy field link should have valid URL format for SearchIndex","durationMs":18190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-99044d1988ae10656e86","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Verify charts are visible in explore tree","durationMs":12813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-990a0328aaf5e714a575","project":"chromium","file":"Pages/ExploreTree.spec.ts","title":"Clicking Columns node filters search results to show only columns","durationMs":9656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-d04d62e4248018c26b48","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Verify Database and Database Schema available in explore tree","durationMs":8266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a24eabae69a0c8504400-da2efa16e6d48290a45c","project":"Basic","file":"Pages/ExploreTree.spec.ts","title":"Verify Tags navigation via Governance tree and breadcrumb renders page correctly","durationMs":7005,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-10b386b2aacc3b6d727e","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only VIEW cannot PATCH results","durationMs":16748,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-142636b5255a95e79080","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TABLE.VIEW_TESTS can view test case and results in UI (alternative)","durationMs":22020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-3963fdcac9489a95ffa4","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only TABLE.DELETE (no TEST_CASE.DELETE) cannot DELETE results","durationMs":26442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-44ca4292889113c47191","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only VIEW cannot see edit action and cannot POST results","durationMs":16989,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-458487367c118e1442da","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view test case and results in UI","durationMs":21442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-461ccb242873c7e52186","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TEST_CASE.EDIT_ALL can see edit action on test case","durationMs":17771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-6a3dcd200430fdb22666","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TABLE.DELETE + TEST_CASE.DELETE can see delete option for test case","durationMs":18278,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-87ff09dffe6df7343c00","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TABLE.EDIT_TESTS can see edit action on test case (alternative)","durationMs":19476,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-a7bebf9b05558d999a1b","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only TABLE.EDIT_TESTS (no TEST_CASE.VIEW_ALL) can still view results in UI via TABLE.VIEW_TESTS","durationMs":9952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-c1ce7eca2ef10ed65ea3","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with only TEST_CASE.DELETE (no TABLE.DELETE) cannot DELETE results","durationMs":25861,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a26f0a1569990dd07672-e8a653dfadd848daaadd","project":"chromium","file":"Features/DataQuality/TestCaseResultPermissions.spec.ts","title":"User with TEST_CASE.VIEW_ALL can view test RESULT CONTENT in UI","durationMs":11549,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a45d1fef427e51507f17-4849e68d9f25db425e8f","project":"chromium","file":"Features/LanguageOverride.spec.ts","title":"App language should override browser language on landing page and user dropdown","durationMs":9749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-4bc0e6edaa3ee5e42269","project":"chromium","file":"Features/Topic.spec.ts","title":"Copy field link should have valid URL format","durationMs":15875,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-5f9f332c0569746f0158","project":"chromium","file":"Features/Topic.spec.ts","title":"Copy nested field link should include full hierarchical path","durationMs":15939,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-72ed26bcb15b71c6c253","project":"chromium","file":"Features/Topic.spec.ts","title":"Copy field link button should copy the field URL to clipboard","durationMs":11538,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a4ae799e0b6b8a382617-fbfc851a2c0e73a5f14d","project":"chromium","file":"Features/Topic.spec.ts","title":"Topic page should show schema tab with count","durationMs":8995,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a59d6b7c9ea22f8d26d1-93579c51cbed397e9691","project":"Reindex","file":"Features/SearchSeparation/DomainRenamePrefixCascade.spec.ts","title":"domain prefix rename keeps linked asset domain reference consistent","durationMs":978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a6994b74a6f977f55289-e72f2d4a951041c36cef","project":"Basic","file":"Features/DataQuality/TableTestCasePagination.spec.ts","title":"renders pagination and navigates when test cases exceed the page size","durationMs":7414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-09775213f3613c59416b","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display test definitions table with columns","durationMs":9133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-253b00b0981e1e2a783f","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should handle external test definitions with read-only fields","durationMs":14431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-28bcc3dbcea1ef961645","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display pagination when test definitions exceed page size","durationMs":8577,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-3dde97e966710259e666","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should not show edit and delete buttons for system test definitions","durationMs":7913,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-3dfa7d5d186ea5d05eda","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display test platform badges correctly","durationMs":7790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-4c71c4955b660cfea637","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should disable toggle for external test definitions","durationMs":8103,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-815b9cf7d82eb0cb5f0d","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should navigate to Test Library page","durationMs":8283,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-8c170a06fbda932dbf49","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should display system test definitions","durationMs":8357,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-8c3c478a7ed4dc0b0d82","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should handle supported services field correctly","durationMs":18428,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-a6f857458ffc3102916c","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should require supported data types only when OpenMetadata platform is selected","durationMs":11171,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-ae3d0ee4a3aa7eb16c12","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should maintain page on edit and reset to first page on delete","durationMs":16960,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-b19e61f67023bc106e0c","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should cancel form and close drawer","durationMs":9136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-cf4dbef040a07d52aa1f","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should create, edit, and delete a test definition","durationMs":15049,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-d0b196e35b293eca54cf","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should allow enabling/disabling system test definitions","durationMs":8622,"attempts":1,"retries":0,"outcome":"expected"},{"id":"a782df52becf097a078d-df06e19168d3f9683dcb","project":"chromium","file":"Features/DataQuality/TestLibrary.spec.ts","title":"should validate required fields in create form","durationMs":9266,"attempts":1,"retries":0,"outcome":"expected"},{"id":"acc5d0eeb3cee45912c8-eec5f01af3a022ae6d87","project":"chromium","file":"Flow/IngestionBot.spec.ts","title":"Ingestion bot should be able to access domain specific domain","durationMs":99221,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ad818a91d010e372c30f-6defd7b1cd04246cf88b","project":"Basic","file":"Flow/Tour.spec.ts","title":"Tour should work from welcome screen","durationMs":7725,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ad818a91d010e372c30f-9a8d36386767ad693933","project":"Basic","file":"Flow/Tour.spec.ts","title":"Tour should work from URL directly","durationMs":11886,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ad818a91d010e372c30f-dc6831d44a4eda4a1911","project":"Basic","file":"Flow/Tour.spec.ts","title":"Tour should work from help section","durationMs":32434,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-0d2a8343f2a5a121cb1f","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should render entity title section with link","durationMs":7154,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-0f78279b7cd0d2ea968f","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for dashboardDataModel","durationMs":6326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-18c7d8658b0b67febc27","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should edit display name from entity summary panel","durationMs":11202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-299bab0048d02d5a1ac1","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for databaseSchema","durationMs":6723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-4ccfbac3fd35b05b41ae","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display domain section","durationMs":6675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-4cd6a15a5a4f8e5fa548","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for table","durationMs":7718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-5974da0a98d9ff41bfef","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for database","durationMs":6771,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-6e96b7009731b3128a6c","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display owners section","durationMs":6654,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-71b91d4510ddc05ada9d","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for dashboard","durationMs":6973,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-9ee466321a0f343c2ebf","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display tags section","durationMs":6358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-b551fb9cd1206bb59afa","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for container","durationMs":7665,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-bb37fdee3aa482bb760f","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for pipeline","durationMs":6678,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-c20815e6048903c01440","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should cancel edit display name modal","durationMs":10716,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-de6f03d218c62993258e","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display description section","durationMs":6485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-e46c0fa6f29410cb4325","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should navigate between tabs","durationMs":5692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-e9ea0b76744be28bb3a9","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for tableColumn","durationMs":5361,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-ec7d85f516045c6b6e83","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for searchIndex","durationMs":7383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-ee23b3ba8289eba1fc99","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for topic","durationMs":7466,"attempts":1,"retries":0,"outcome":"expected"},{"id":"af04d0115b12876333a4-f6ec16f78eaf97f57e33","project":"chromium","file":"Features/EntitySummaryPanel.spec.ts","title":"should display summary panel for mlmodel","durationMs":7303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afb2f5a0d4a7b4e36b1b-300bb01fd40e114637cf","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":24593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afb2f5a0d4a7b4e36b1b-45178ac7f9360cca1780","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":23645,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-1b2fe4c0f4b3e40c68aa","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit description for knowledgeCenter","durationMs":8282,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-200ecb1a398820cba8d1","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Consumer to edit glossary terms for knowledgeCenter","durationMs":10068,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2219de8dbcf16282e851","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Consumer to edit description for knowledgeCenter","durationMs":10107,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2adde21732850322e910","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update/edit tags for knowledgeCenter","durationMs":9925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2ce281911970fdcbad04","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"validates visible/hidden tabs and tab content for knowledgeCenter","durationMs":6296,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-2f0073a8f865128ed4f0","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should remove glossary term for knowledgeCenter","durationMs":14083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-431e80d685d3040a591e","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should verify deleted user not visible in owner selection for knowledgeCenter","durationMs":17980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-61dfa16835a0fc53a710","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should add multiple tags simultaneously for knowledgeCenter","durationMs":15592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-62c2c0de67ca104c110b","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should clear description for knowledgeCenter","durationMs":18378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-63aa7ba27f3e16c0b541","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update description for knowledgeCenter","durationMs":10612,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-655098bd2e2891f71af6","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should verify deleted glossary term not visible in selection for knowledgeCenter","durationMs":14917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-77c03226c16367ca687a","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should remove user owner for knowledgeCenter","durationMs":96715,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"afc48ed87f02c4253cb9-7c35b7b765009e454966","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should NOT show restricted edit buttons for Data Steward for knowledgeCenter","durationMs":6235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-b20ba9df57bb0bbeb9e5","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Consumer to edit tags for knowledgeCenter","durationMs":8925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-befd9930c632eef22c86","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit glossary terms for knowledgeCenter","durationMs":6420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-d3e2270239e49f6934d0","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit tags for knowledgeCenter","durationMs":9125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e39b2e3c5774cb85f940","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update owners for knowledgeCenter","durationMs":10453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e55d1d3c57e57a116537","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should allow Data Steward to edit owners for knowledgeCenter","durationMs":9898,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e5b2e0783f40c95ca366","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should update/edit glossary terms for knowledgeCenter","durationMs":10618,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-e5dcf26ca9b2cb634758","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should verify deleted tag not visible in tag selection for knowledgeCenter","durationMs":16441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-edf1487a938c1cea5168","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should follow Data Consumer role policies for ownerless knowledgeCenter","durationMs":19316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"afc48ed87f02c4253cb9-f603a841c789bd2d4743","project":"chromium","file":"Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts","title":"Should remove tag for knowledgeCenter","durationMs":15091,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-08f24e3da77cd21ce3b3","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edits only selected metric rows","durationMs":7028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-178e2b77ae6556aa3efc","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Adding a new metric row shows CREATE badge once name is filled","durationMs":6783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-2777402b380093228942","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Custom metric editor role can import export and bulk edit metrics","durationMs":15914,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-2af739fb696d58987e61","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin can cancel a metric import mid-flight and cancel API is called","durationMs":8909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-591a014ecb6929685d23","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage unchecking header checkbox clears the selection bar","durationMs":5444,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-6b17e53c8020ed09e983","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"New metric row without a name shows error pill and SKIP badge","durationMs":6301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-6c741b436f4e5a01b0ad","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edits filtered metrics from the listing API without export jobs","durationMs":19609,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-76711958c8d3b0e576ea","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Cancel from metric bulk edit returns to the metrics listing","durationMs":7917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-7daeb1a73fe3cc3529a7","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin imports a metric CSV through preview and async apply","durationMs":19623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-85ed20b16efbca3760aa","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Restricted roles cannot access metric import or bulk edit","durationMs":41097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-a3f990ae4c749a36d952","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edit renders complex fields from listing hydration","durationMs":6640,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-b003905d27f3c841d948","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Bulk edit grid shows NO_CHANGE badge on unmodified rows","durationMs":6553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-b42b25528f0bc555a130","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Clearing the bulk edit search box restores all rows","durationMs":4961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-baa952ede54ac2d44a2d","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage header checkbox selects all visible metrics","durationMs":6342,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-c9058e368b41cced0d25","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin imports a CSV update for an existing metric","durationMs":20312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-d618b90203504b6eb375","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage clicking the row checkbox selects without navigating","durationMs":5193,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e593eda82739e1962b02","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edit keeps text edits on blur and can revert to no changes","durationMs":5183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e73a3bbef909ec39ca07","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin bulk edit hydrates filtered metrics across cursor pages","durationMs":5668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e7724451b74703d8bd55","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin starts exactly one async export job from the metrics listing","durationMs":6307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e7fecf7152863cfba0d2","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Bulk edit grid search filters rows to match the search term","durationMs":5616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-e96615940597b28ada02","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"MetricListPage clicking anywhere in a row navigates to metric details","durationMs":5125,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-ebb437f18124523e7ce3","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Removing a newly added metric row restores the grid state","durationMs":5801,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-ef81d70712fff3b3f5d7","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Admin sees metric CSV validation failures for missing names and invalid references","durationMs":10224,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b059cce5e81de1c3d6bf-ff1aaa2410e296101d5d","project":"ImportExport","file":"Features/MetricBulkImportExportEdit.spec.ts","title":"Bulk edit grid shows UPDATE badge and increments summary after editing a cell","durationMs":5908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b1b675f17c811fa8c75f-2df47237b83960fcce36","project":"chromium","file":"Features/DataProductDomainMigration.spec.ts","title":"Data product remains visible after moving domains and deleting the original domain","durationMs":15083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b1b675f17c811fa8c75f-5843ab60a742af1caac8","project":"chromium","file":"Features/DataProductDomainMigration.spec.ts","title":"Data product with no assets can change domain without confirmation","durationMs":15751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b1b675f17c811fa8c75f-82e7f9a502c188f6f02d","project":"chromium","file":"Features/DataProductDomainMigration.spec.ts","title":"Changing data product domain via API migrates assets to new domain","durationMs":29024,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-023d22dc39c48e8d53f4","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.VIEW_BASIC can view test case in UI","durationMs":15526,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-225d15df6f71e5d6038d","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.CREATE cannot delete test cases","durationMs":16506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-2344f0d9500623421fb8","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer cannot create or delete test suites","durationMs":8721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-36d66c70ea2381068e2d","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer can VIEW test cases but sees no edit controls in UI","durationMs":16369,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-3b2675937f5dccd75d2f","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.DELETE can see delete option for test case","durationMs":15731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-41cfeb97e29ffcfe25f5","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.VIEW_ALL can view test suite CONTENT but cannot add test case","durationMs":10629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-505fe28532602c99aab7","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer cannot edit test case","durationMs":15250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-597de0139daf1d0e4d01","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Steward cannot create or delete test cases (default)","durationMs":17303,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-7805715b82208927b353","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Admin can see Data Quality UI controls (add test case, add test suite)","durationMs":16876,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-7a64848a6500dadc0c80","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.DELETE cannot create test cases","durationMs":16789,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-7a85c789b019754693f6","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.CREATE can see Add test suite button","durationMs":11173,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-867f3068db9da0d14660","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.EDIT_ALL can see edit action on test case","durationMs":16111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-8d4b1e27cb6ab75b49f4","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.VIEW_BASIC cannot edit test cases","durationMs":17036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-9d7d81e12e2bea1146ad","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.CREATE can see Add button for test case","durationMs":16620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-a12338af018616a5c43d","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.VIEW_ALL can view test suites page and list suites","durationMs":10970,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-bf3ff4cd06cdb0ec6934","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_CASE.VIEW_BASIC can view test case CONTENT details in UI","durationMs":20844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-c53bcbe763c0939caa91","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TEST_SUITE.EDIT_ALL can see add test case button on suite details","durationMs":11301,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-cfbd7e7f4484702c01f0","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TABLE.VIEW_TESTS can view test suites page (alternative permission)","durationMs":10456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-cfbe5dcb809fce114ce5","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with VIEW_BASIC cannot see edit action in UI","durationMs":15593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-d7319bc5b90ed2cb0a11","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User without TEST_SUITE.EDIT cannot add test case to logical suite","durationMs":11575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-e280555757f349c72854","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"Data Consumer cannot create or delete test cases","durationMs":16914,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-e4e1a2ebe615aae2117c","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TABLE.EDIT_TESTS can see edit action on test case","durationMs":16332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-eae7b64629c9d1a12de2","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User without TEST_SUITE.DELETE cannot delete test suites","durationMs":10821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-f34cdcd4f8d4edd4cdfe","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User without TEST_SUITE.CREATE cannot create test suites","durationMs":9818,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b2111489ddf56841564e-ffe3f0d85ac3d552eb09","project":"chromium","file":"Features/DataQuality/DataQualityPermissions.spec.ts","title":"User with TABLE.CREATE_TESTS can see Add button (Table Permission)","durationMs":16041,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-07c6afb9a23ebfeb2a6b","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Data product linked to subdomain","durationMs":6218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-0921be7b13e4f8bb54b9","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Navigate between sibling subdomains","durationMs":9431,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-1b8348aa29026ad058d3","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Search data products by name","durationMs":7721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-22b7e17ead94a9522c35","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Search data products by name","durationMs":6400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-474ca9f2afe893e8b7ac","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Create nested subdomain (subdomain of subdomain)","durationMs":9226,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-5783990ffbdcaeb86ef5","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Entity name cell shows both display name and name","durationMs":7829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-6dbb46279d8e346845b4","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Filter data products by domain in global selector","durationMs":12470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-720615fe1fb8b4168b26","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Assign assets to different subdomains","durationMs":14130,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-73dc3ed8540a79ec973c","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Delete subdomain with data products shows proper cleanup","durationMs":10689,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-7d6b5a8d9596aebe56a3","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add expert to data product via UI","durationMs":8754,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-81165f95ed1499970253","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add tags to data product via UI","durationMs":8086,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-91793eae76cc059f0892","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add assets to data product and verify count","durationMs":9440,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-adf89ee01b3fc4f97129","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Add-Assets drawer quick filter - behaviour matrix","durationMs":13043,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-b492800937e43dace798","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Edit data product description via UI","durationMs":8036,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-c0f886b6be5ebe890a69","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Create multiple sibling subdomains under a domain","durationMs":7063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-c332ba9a2b88fe69b9cd","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Create data product via UI with description","durationMs":9343,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-cb1344fd55e961f79574","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Data products under different subdomains","durationMs":10572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b211ed4e71c38f212b54-ffec821644fa472c4af7","project":"chromium","file":"Pages/DataProductAndSubdomains.spec.ts","title":"Subdomain assets count reflects in parent domain","durationMs":12192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-197763039c01ba157836","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Owners filter for Lineage","durationMs":12479,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-2c56f77f0afe01f5283e","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage service filter selection","durationMs":37822,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-5901fe256dc6d4261268","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Tag filter for Lineage","durationMs":12767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-60b7003c6bf6f5744f3f","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage schema filter selection","durationMs":11048,"attempts":2,"retries":1,"outcome":"flaky"},{"id":"b239f9808ff1b1045021-6e20bd657decc40af6c7","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify LineageSearchSelect in lineage mode","durationMs":12348,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b239f9808ff1b1045021-70762ee7ffaf711b90f6","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Tier filter for Lineage","durationMs":13272,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-76596bc125ee10098e5c","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Impact Analysis service type filter selection","durationMs":16085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-7ae9968177c8c6307df6","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage filter panel toggle","durationMs":6596,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-886f4edb739677df5421","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Domains filter for Lineage","durationMs":14074,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-ba38e82802a16ac8b3c2","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"verify upstream count for all the entities","durationMs":104905,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b239f9808ff1b1045021-e36a3455bccfbb250aa8","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify Impact Analysis service filter selection","durationMs":23908,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-e781b4dbfe0117c8e731","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage database filter selection","durationMs":10071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-eb93467a60001bf9c40c","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage service type filter selection","durationMs":40702,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b239f9808ff1b1045021-faeb0eea7f413d0942a1","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"Verify lineage column filter selection","durationMs":10402,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b239f9808ff1b1045021-ffd6ada4fc4adecb41b8","project":"chromium","file":"Pages/Lineage/LineageFilters.spec.ts","title":"verify downstream count for all the entities","durationMs":127066,"attempts":2,"retries":1,"outcome":"expected"},{"id":"b4b9aac556686af843f1-1ee660123e4e2cf43b3d","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should create term with all optional fields populated","durationMs":13677,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-63880e3b520f38fa0e1c","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should add and remove related terms from glossary term","durationMs":8302,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-87e39a7c7fc3fd2476a4","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should keep multiple relation types for the same related term across reload","durationMs":12254,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-c2f9db0d41f956eccc6b","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should add and remove synonyms from glossary term","durationMs":7793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-c368857de9562394274c","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should edit term via pencil icon in table row","durationMs":7502,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-d58ed71b3e1a1f7f3079","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should verify bidirectional related term link","durationMs":8666,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b4b9aac556686af843f1-f5dc38dfffc509f2dc8e","project":"chromium","file":"Features/Glossary/GlossaryTermDetails.spec.ts","title":"should add and remove references from glossary term","durationMs":8819,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-1eb38a10ca22dc7e41b9","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab is not visible for other applications","durationMs":6201,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-8c55296c911ed9b878fe","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab shows empty state when no records","durationMs":6492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-bccbe41b46287af5da95","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab displays records with correct status badges","durationMs":5615,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b51bfa93bcf51a3af79c-f6f19e89bc91d7bbaef2","project":"chromium","file":"Pages/LiveIndexingTab.spec.ts","title":"Live Indexing tab is visible and loads data","durationMs":6240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b5ac74643fe7ba2d8fe3-ce9f73536f00a5d45e01","project":"Reindex","file":"Features/DataQuality/TestSuiteSummaryAfterReindex.spec.ts","title":"Test suite lastResultTimestamp survives a full entity reindex","durationMs":1183,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-0548815eb142c00104e1","project":"chromium","file":"Features/Table.spec.ts","title":"Tags term should be consistent for search","durationMs":18010,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-12dbdff48f072e317aba","project":"chromium","file":"Features/Table.spec.ts","title":"Search for column, copy link, and verify side panel behavior","durationMs":28002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-1778f18ede2a1820b4d5","project":"chromium","file":"Features/Table.spec.ts","title":"Table filter with sorting should work","durationMs":7245,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-17efa24eeee45d8e3bef","project":"chromium","file":"Features/Table.spec.ts","title":"expand / collapse should not appear after updating nested fields table","durationMs":28790,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-2fb31f7270b5a3caefb9","project":"chromium","file":"Features/Table.spec.ts","title":"should persist current page","durationMs":10575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-55f37c83b82714bc44fe","project":"chromium","file":"Features/Table.spec.ts","title":"Table search with sorting should work","durationMs":7152,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-5faa0ca4d02a0d62d909","project":"chromium","file":"Features/Table.spec.ts","title":"Table page should show schema tab with count","durationMs":6738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-66a209a1e3b6ada95aa1","project":"chromium","file":"Features/Table.spec.ts","title":"Glossary term should be consistent for search","durationMs":13075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-930ae77b2adf34892aed","project":"chromium","file":"Features/Table.spec.ts","title":"should persist page size","durationMs":9764,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-9a7b47c6d7d4c115c405","project":"chromium","file":"Features/Table.spec.ts","title":"Table pagination with sorting should works","durationMs":6781,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-b44fe1be53d0f0e7e757","project":"chromium","file":"Features/Table.spec.ts","title":"open-task stat shows the count and links to the Tasks tab","durationMs":6894,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-bc1c352c1584708aae20","project":"chromium","file":"Features/Table.spec.ts","title":"expand collapse should only visible for nested columns","durationMs":9429,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-bf9aa70f500df59e999a","project":"chromium","file":"Features/Table.spec.ts","title":"source URL button links to the configured source","durationMs":7463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-d5b31f77c93ec1b8e2b9","project":"chromium","file":"Features/Table.spec.ts","title":"should show dbt tab if only path is present","durationMs":9650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b63caa6d5c82a89c01d9-fd7508676be39f5779fc","project":"chromium","file":"Features/Table.spec.ts","title":"should show dbt tab if only source project is present","durationMs":9910,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-067f93c6eeb260535c41","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Editor operations","durationMs":12404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-15e9f69ba626aec0884b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Quick link lifecycle validates, creates, edits, and deletes from card","durationMs":32083,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-1a8244c504b33bd9537b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"displayName: switching articles does not bleed unsaved title into next article","durationMs":19456,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-204381832cab1ede446d","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Editor operations","durationMs":12258,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-24dc340d8dafc3a9667e","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Slash commands and basic blocks","durationMs":16899,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-26157f59f7cb7332dc0b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Nested lists","durationMs":14095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-2ac62df99361241c8ae1","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article listing search filters, clears, and shows empty state","durationMs":15029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-2ba8f331893d4140692d","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Slash commands and basic blocks","durationMs":13676,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-30e867f4c2cb533197c0","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Content persistence","durationMs":15783,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-33312fa3fcba8fd1eb7f","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Global search and Explore Knowledge Center filter navigate to articles","durationMs":12533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-3b4001e65d812e269530","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Nested lists","durationMs":13775,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-3d7c9dc3feed478080fe","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Content persistence","durationMs":21185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-3e336ce29aecac2276b5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article copy, delete, sidebar delete, and same-name recreate do not preserve stale metadata","durationMs":32857,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-44141f0094dacc65fb03","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Advanced blocks","durationMs":16721,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-4651a3d8ca18fd5978a8","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article detail layout, drawer, activity tab, and version page work","durationMs":27015,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-51e828109a715ff2b402","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Advanced blocks","durationMs":16404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5caea89669fac360aeb4","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Left hierarchy pagination and expand collapse actions work","durationMs":23053,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5d349d5ef24e6a752ff0","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article edit persistence and unsaved title behavior are correct","durationMs":50553,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5e7ba62f70111436e4bb","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article card metadata, widgets, and listing search update from UI edits","durationMs":57697,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5f9b4fb91211a9239460","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Text formatting","durationMs":15202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-5fe7c1a8b26384d38c3a","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Slash commands and basic blocks","durationMs":14909,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-68a6c0a93ff080139c4b","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article tags added on the article page are visible in the Explore right-panel summary","durationMs":22133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-69f43bc4beb330d729a2","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Editor operations","durationMs":11990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-729476f400ca746921b3","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Empty article can be deleted immediately without polluting the list","durationMs":15810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-76e359fc969880358083","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Expanding a multi-level hierarchy does not throw and renders no duplicate nodes","durationMs":12111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-7c113e606a888c1f3f14","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Advanced blocks","durationMs":19282,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-81c3fb7f005013a8c26d","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Quick link created from API can be opened and deleted from hierarchy","durationMs":14978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-93a7f2bbd8e1b2c406fe","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"multiple articles hold independent drafts simultaneously","durationMs":26097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-9c5563ee05c5f3483575","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article list basics and creation entrypoints","durationMs":25662,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-b641a2040579b23d75c5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Related assets, activity feed, user mentions, and article mentions work","durationMs":46223,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-bb081fd8a6faef23cf41","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"draft cleared from localStorage when article is deleted","durationMs":26949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-cb1726ba98fa649c2682","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Nested lists","durationMs":12505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-d35e8e76a8cbb00b80cf","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Text formatting","durationMs":14527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-dafef3bc55c97adddca2","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"no spurious sync when content is already saved — no PATCH on clean reload","durationMs":19114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-e0fab1039a57c80c069c","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Article list cards, recently viewed widget, and pagination work","durationMs":22383,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-e4dd3c0f394f33812eb5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"draft syncs on page reload — skeleton shown, content saved","durationMs":13518,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-ecee0ea08bf9947064c5","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Content persistence","durationMs":21550,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-efefa0a8bc5fbc7f29ae","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Quick link card opens the configured url in a new tab","durationMs":11145,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-fa401e6d00626065b924","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"description: switching articles does not bleed unsaved content into next article","durationMs":23340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-faf8bd343ccd2da9f03f","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Text formatting","durationMs":14406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b76310c94a1ee56387bf-feeaee8a079d7e5adfca","project":"chromium","file":"Features/ContextCenterArticles.spec.ts","title":"Other user editing is visible in the article header editor list","durationMs":22261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-53ee56c1e5fef5ae703b","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"keeps the full Russian severity label reachable when the chip is truncated","durationMs":22000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-55282d41804a711d18ad","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"leaves a short severity label sized to its content, with the nav expanded","durationMs":21000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-8920f0ec33c9ca9955ab","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"bounds the Russian severity chip regardless of its column, with the nav collapsed","durationMs":30000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-982d99e87fec992b640c","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"never truncates a status chip, whose labels are longest in Russian","durationMs":21000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-9fb88b89adb2374cf977","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"leaves a short severity label sized to its content, with the nav collapsed","durationMs":21000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-af868572f1b5280abf4d","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"keeps the Assignee column on screen when the Russian severity placeholder is rendered","durationMs":31000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b799ec5b24dae9d75994-dc07ec68eea589c12b0e","project":"chromium","file":"Features/DataQuality/IncidentManagerLocaleLayout.spec.ts","title":"bounds the Russian severity chip regardless of its column, with the nav expanded","durationMs":31000,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b833d1df0ed59e353274-cfcdbc6fef10b7352962","project":"chromium","file":"Flow/GlobalSearch.spec.ts","title":"searching for longer description should work","durationMs":9661,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-0d0894d0eff588acbda5","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify tag filter for column level impact analysis","durationMs":10063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-0e2a39039601d66193f7","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify search functionality filters table results","durationMs":8437,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-14ffe4f55cb631cf8053","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column level table has correct columns","durationMs":10106,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-17e3e557dc5d7daf0a70","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify table columns visibility and content","durationMs":8706,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-45988883f9736aa212aa","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify impact analysis requests include entityType and explicit depth bounds","durationMs":9354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-4ab0e07a210458f91a36","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify glossary term filter for column level impact analysis","durationMs":11187,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-5c9c089589d1b6546ae9","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify node depth display in table level impact analysis","durationMs":9075,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-5d1a8029ecad9ed2f200","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify upstream/downstream counts for column level","durationMs":17448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-6eb1d52223d4236a9d5e","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column mode switches direction with directional lineage requests","durationMs":15668,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-a21ab6be616ec8d2b646","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"validate upstream/ downstream counts","durationMs":9203,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-b6bc96b8f727cbe93b20","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"verify domain for Asset level impact analysis","durationMs":10879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-bd2f8536c50f80a40c78","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column level upstream connections","durationMs":15709,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-c5e909fa0bda66087277","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"verify tier for Asset level impact analysis","durationMs":10263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-c9f25440f3b28869b7f1","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column search in column level impact analysis","durationMs":11571,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-de731b18c2794ea1d269","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify Upstream connections","durationMs":15313,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-dee5fc58e2ec8e454aea","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify service type filter for Asset level impact analysis","durationMs":9281,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-e501b68bc994f0c9a2a0","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"verify owner filter for Asset level impact analysis","durationMs":9188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-e9b173ac180a81ce4678","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify upstream downstream toggle persists pagination","durationMs":10904,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-e9d899efa5a5e8c7852b","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify column level downstream connections","durationMs":9085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-efe35888f94fa46c4770","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify depth configuration changes impact analysis results","durationMs":11671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-f938981feaa7b431fef5","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify entity popover card appears on asset hover in lineage-card-table","durationMs":9595,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-fa91fe5a25c3405e9b2b","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify Downstream connections","durationMs":15216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b84e977256cf1f379750-fe838344992277ee44da","project":"chromium","file":"Features/ImpactAnalysis.spec.ts","title":"Verify switching between table and column level clears filters","durationMs":10340,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-04a0fecced207a315556","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"partitions the listing into roots and immediate children","durationMs":59,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-1932f747684ae98fb8a8","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"paginates top-level hierarchy results","durationMs":1419,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-26969935852785ad910e","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"establishes a parent-child relationship without changing names","durationMs":39,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-4a2d5288422399812ba6","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"creates a group, root, and child from the UI and completes the Overview edit flow","durationMs":3768,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-4b65fd8b5d2c5599a005","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"creates an In Review metric through the UI when a reviewer is selected","durationMs":3411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-57bbec44efc23131ed1c","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"switches list layouts and exercises group, search, filter, columns, and bulk controls","durationMs":3792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-6a107850b2505678de81","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"keeps Overview metadata visible while hiding edits from read-only users","durationMs":1945,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-8e0438b8bac6d8b45cde","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"refuses to delete a parent without recursive, then succeeds with it","durationMs":64,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-91ca22c3fbca12053f5c","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"moves the edge on reparent and keeps the fully qualified name","durationMs":90,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-cb9779c0d09834e9ef01","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"lists roots and reveals children on expand in the list page","durationMs":2110,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-deb70e0b7b03053644b3","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"rejects a cycle when reparenting","durationMs":33,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b98ad857feeb1039461f-ea8d14903c465c61337d","project":"Basic","file":"Features/MetricHierarchy.spec.ts","title":"executes bulk edit and bulk delete for selected metrics","durationMs":16731,"attempts":1,"retries":0,"outcome":"expected"},{"id":"b9d345b1f0052cfce4e3-50adca26c4f0573f2431","project":"chromium","file":"Features/ServiceAgentsRefresh.spec.ts","title":"should refetch the agents list and nothing else","durationMs":6962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"baaea988202fec9da880-ce88b9d90ae9ffa0b5c6","project":"Ingestion","file":"Features/DataQuality/Dimensionality.spec.ts","title":"Dimensionality Tests","durationMs":8404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"bca4445f78bc23d9198a-2d3e5bd59f9abf98d8d0","project":"Basic","file":"Pages/Bots.spec.ts","title":"Bots Page should work properly","durationMs":36038,"attempts":1,"retries":0,"outcome":"expected"},{"id":"be1908fe012aeef38284-23b97f41f72ab99a4a7a","project":"chromium","file":"Flow/PlatformLineage.spec.ts","title":"Verify Platform Lineage View","durationMs":83738,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-112f974de894495fbe0f","project":"chromium","file":"Pages/Tag.spec.ts","title":"Tag toggle should be disabled for user without EditAll permission","durationMs":11624,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-21b333b8ba624e722147","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets for Data Consumer","durationMs":40556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-26de7b0bca5c04a95283","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Owner Add Delete","durationMs":23902,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-36fa997930433fb32eb8","project":"chromium","file":"Pages/Tag.spec.ts","title":"Restyle Tag","durationMs":17620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-43a3e97741d61e4e08ed","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets","durationMs":34072,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-4996201f40fba2b4706b","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets and Check Restricted Entity","durationMs":41944,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-5529639e695d00eba7e3","project":"chromium","file":"Pages/Tag.spec.ts","title":"Certification Page should not have Asset button","durationMs":14892,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-5d78f990ea88fe859e6d","project":"chromium","file":"Pages/Tag.spec.ts","title":"Edit Tag Description for Data Consumer","durationMs":14706,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-765dc0d5ad900f88800e","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Tag UI for Data Consumer","durationMs":18184,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-7781e587de258e712ab1","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Tag UI","durationMs":14652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-77fb8739144fe03d6137","project":"chromium","file":"Pages/Tag.spec.ts","title":"Certification Page should not have Asset button for Data Steward","durationMs":10730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-7c8d2d4b3a5a6b5c5885","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify tag enable/disable toggle","durationMs":13159,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-c1a6747ea2611120acd7","project":"chromium","file":"Pages/Tag.spec.ts","title":"Create tag with domain","durationMs":17141,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-c6f548dea68f98c1a019","project":"chromium","file":"Pages/Tag.spec.ts","title":"Certification Page should not have Asset button for Data Consumer","durationMs":12163,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-cba3bfab34284be22556","project":"chromium","file":"Pages/Tag.spec.ts","title":"Verify Tag UI for Data Steward","durationMs":13363,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-d0c11c5caf849cf711d3","project":"chromium","file":"Pages/Tag.spec.ts","title":"Rename Tag name","durationMs":20572,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-dbf18648002dd3ebc901","project":"chromium","file":"Pages/Tag.spec.ts","title":"Edit Tag Description for Data Steward","durationMs":14478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-e25c1fb74b2b0468a491","project":"chromium","file":"Pages/Tag.spec.ts","title":"Edit Tag Description","durationMs":16936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-e535042dd7255d039f34","project":"chromium","file":"Pages/Tag.spec.ts","title":"Delete a Tag","durationMs":17642,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-ef2d4407841e571e6b90","project":"chromium","file":"Pages/Tag.spec.ts","title":"Tag toggle should be disabled when classification is disabled","durationMs":17162,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c10ff6c79a1ef57a7565-f4c820b1962c81bd03a4","project":"chromium","file":"Pages/Tag.spec.ts","title":"Add and Remove Assets for Data Steward","durationMs":32332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-180a75d5076d96f27c9e","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"team member should be able to approve task assigned to team","durationMs":13057,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-212799dfdd593ee4c6ca","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"resolving task should require edit permission on target entity","durationMs":483,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-231982a7067ce2e93f31","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"assignee should see approve/reject buttons","durationMs":6486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-3dac766449e6b290b2c9","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"admin should be able to approve task","durationMs":7791,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-8e21f7221e157bfcee70","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"recognizer-style data quality task should reject via /tasks/{id}/resolve","durationMs":4468,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-8e4fd7cced46a3626635","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"owner/assignee with edit permission should successfully resolve task","durationMs":430,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-9aaa4c31cd0d498e6084","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"non-assignee should NOT see approve/reject buttons","durationMs":7671,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-af01b3d405099b46a381","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"non-team member should NOT see approve button for team task","durationMs":13284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c13c7be365d042dead16-f6dedc77d796ebcc1ac8","project":"chromium","file":"Features/Tasks/TaskResolution.spec.ts","title":"task creator should be able to close/reject their own task","durationMs":583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c149cc7f2afeaafc22a5-61cfff024ab316b5e7cd","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":25660,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c149cc7f2afeaafc22a5-c2d70e372af0aacb7e7a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":24983,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c2f2fb43f3574526e3cf-47ef5a94739346607a50","project":"Basic","file":"Pages/UserCreationWithPersona.spec.ts","title":"Create user with persona and verify on profile","durationMs":11450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-01fad5a002847d8d58c0","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow adding a semantic with multiple rules","durationMs":11461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-0323470366a0f662aa12","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Store Procedure","durationMs":48504,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-07cd60e8fb8b6f4d333a","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-189e36fb58340c1da0bc","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Database Schema","durationMs":43172,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-25f202a29cb96dee010f","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":26192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-26840c03b806453e7fcc","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Semantic with Contains Operator should work for Tier, Tag and Glossary","durationMs":29883,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-2d42dd2032ba827235d2","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Container","durationMs":42191,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-39d6283757ce29d63cce","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Topic","durationMs":52603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-3c0a5f962a565d161122","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for SearchIndex","durationMs":49693,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-3cb384ab3e3bfc745ae8","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33002,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-48ecd1973fefd27da4bb","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":24605,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-4acb103d01514e7c8e4c","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for File","durationMs":41804,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-5d1101e26207fbfe86fa","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":37821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6003134a749e5f980b90","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":24698,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6582ca87cba7ae106b27","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for MlModel","durationMs":45708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6a4cf3a311c440118bec","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":34806,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-6e4e567d889a4a7c6478","project":"Ingestion","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Table","durationMs":42758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-711bfe9176f5142d1380","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":29723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-72a144851856bc18e7c8","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":25131,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-7512c8036edd600f06e0","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-7ad1c8de93884df3b4fe","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Worksheet","durationMs":48119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-7d700e25a598ac302bd4","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow editing a semantic and reflect changes","durationMs":10653,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8069e46712c959e12df3","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Spreadsheet","durationMs":42216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8b603616c0839438800d","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Operation on Old Schema Columns Contract","durationMs":25659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8d0913db8fc367e458fd","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Semantic with Not_Contains Operator should work for Tier, Tag and Glossary","durationMs":41557,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-8f3a2bc034218b7f11f7","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow adding a second semantic and verify its rule","durationMs":20063,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-914f9dfd0316df153e96","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Api Collection","durationMs":48638,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-974ffe89078f5491207b","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Directory","durationMs":39810,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-99df91fb3dd32d41f319","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":32117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-a3d274cc242d5d110427","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"should allow deleting a semantic and remove it from the list","durationMs":17486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-a87bb726b61df4c7041d","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":40485,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-b331405338cbb0ab4acc","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Nested Column should not be selectable","durationMs":14652,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-b8223a97360afdf32065","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":38112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-b9d5c52175a64817de15","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Add and update Security and SLA tabs","durationMs":19532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-c4fa0bc60e2e6a8dd707","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":40341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d28de6dfa66c9a5efc16","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Chart","durationMs":46695,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d668b72a65efdcabafb1","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Pagination in Schema Tab with Selection Persistent","durationMs":26573,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d8147f11241541ff9323","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Dashboard","durationMs":38901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-d8338405b37a0779887d","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":36774,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-dbf5e444accfa300b508","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"ODCS Import Modal with Merge Mode should preserve existing contract ID","durationMs":13656,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-dc6f6a60c0682cee8023","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Database","durationMs":46240,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-df38484d393a5065dad8","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":39246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-e377248f44940da3b646","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"ODCS Import Modal with Replace Mode should overwrite all fields","durationMs":14795,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-e82f3725ee0553a9eeaf","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":33442,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-e83c33dcd2e14a49b397","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for ApiEndpoint","durationMs":43346,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-f27dd1f4ed08302ad3fa","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Contract Status badge should be visible on condition if Contract Tab is present/hidden by Persona","durationMs":48698,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-fe80e1a6b808452d5670","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for DashboardDataModel","durationMs":41275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c345246d55609214620c-fffaa929851105d619ee","project":"chromium","file":"Pages/DataContracts.spec.ts","title":"Create Data Contract and validate for Pipeline","durationMs":52843,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c39768dc6aa2e0276e68-10caaec99edb45710f85","project":"DomainIsolation","file":"Features/DomainIsolation/DomainTaskIsolation.spec.ts","title":"userA sees only their own-domain task","durationMs":3098,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c39768dc6aa2e0276e68-4f3310973531f919b5b8","project":"DomainIsolation","file":"Features/DomainIsolation/DomainTaskIsolation.spec.ts","title":"userB sees only their own-domain task","durationMs":3114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c39768dc6aa2e0276e68-da91b22f9303a7b822f0","project":"DomainIsolation","file":"Features/DomainIsolation/DomainTaskIsolation.spec.ts","title":"admin sees tasks from both domains","durationMs":4060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-2242f6cb6cab5485702b","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Widget drag and drop reordering","durationMs":15809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-6f0dbf5beb7bc3c697a2","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Cancel button should show a single confirmation modal and Discard should exit the customize landing page","durationMs":12400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-d2792ca6ac76dfdb0b60","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Check all default widget present","durationMs":8198,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c4a63a09447c00e0bfbc-e40a9d9532d26fa1fcf8","project":"Basic","file":"Flow/CustomizeLandingPage.spec.ts","title":"Add, Remove and Reset widget should work properly","durationMs":23415,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-0173c4913e3c4c2ceeac","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should support pagination and page size selection","durationMs":6166,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-02767019d7873edaa6f6","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is restored","durationMs":14630,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-029bce62073efbde0c0e","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is soft deleted","durationMs":13762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-102a6a666663aa204ff8","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should support multiple filters from different categories","durationMs":8137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-1542609facbc6309558a","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should include filters and search in export request","durationMs":6954,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-1718ce29678e9bfb5835","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should support case-insensitive search","durationMs":6869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-2c47025e103ba0cf18e5","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should complete export flow and trigger download","durationMs":13052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-31bc9a7d808b23935bf4","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should apply both User and EntityType filters simultaneously","durationMs":12958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-364093191ceee41ad0ef","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is hard deleted","durationMs":12422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-3761fc0928da9497c624","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should apply and clear filters","durationMs":7316,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-3ab9ba83e401655059c9","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should handle audit logs access for non-admin users","durationMs":7493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-3bcbbb77fedde5a10c87","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display audit log entry in UI after entity creation","durationMs":7614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-4777f4d3e3c3581f8b00","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display list items with profile picture and user info","durationMs":5749,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-52a0b9a9306a5955396c","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is created","durationMs":6707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-57dad4b9c1a39e25d0dd","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should verify complete audit trail for entity lifecycle","durationMs":24020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-5ff18772f15eae7292d5","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should verify search API returns proper response structure","durationMs":7133,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-6c1cf735098804c92262","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should allow searching within User filter","durationMs":5894,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-6c2cbb1a4c0ab7593cbe","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should search audit logs","durationMs":8347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-73f0cb6723ad9eb2a8b1","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display entity type in list item metadata","durationMs":6763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-8bababb17ab053dd01bf","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should remove individual filter by clicking close icon","durationMs":7807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-a22442a667f924534986","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should deny export access for non-admin users","durationMs":5820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-bc6f6e1c30715e27cfcf","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should allow searching within Entity Type filter","durationMs":6824,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-be673c6ff393f52ea948","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display page header with correct title and subtitle","durationMs":6452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-c2b2962c03fbe62d08e7","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should create audit log entry when glossary is updated","durationMs":10229,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-ded0959fe0acb519f6a6","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should validate export response structure","durationMs":6008,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-eabfd904a9633233e517","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should replace filter value when selecting new value in same category","durationMs":6341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c509981a76a2c7f60581-f01b7d7c94af12be0cc4","project":"Basic","file":"Pages/AuditLogs.spec.ts","title":"should display relative timestamp in list items","durationMs":6478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-1e1c6cc845ecf39d2205","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can include three custom properties and require one for Data Product","durationMs":6321,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-26d55d23606060e07469","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can remove included and required fields from the Domain intake form","durationMs":6685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-2a62a47a84b7cc428b4f","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting an intake form removes it from the list","durationMs":5284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-3519dafa5283f7746e3d","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"\"Data Product\" option is disabled when a form already exists","durationMs":4767,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-58d8629ab3c486f2924f","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"required intake fields are submitted on create and omitted on edit","durationMs":6272,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-5d1a4b14949b0f9586c9","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can include three custom properties and require one for Glossary Term","durationMs":5368,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-5f404feff62948446f45","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting a required custom property prunes it from the Glossary Term intake form","durationMs":4773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-6289854265d95dec9d0d","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can remove included and required fields from the Glossary Term intake form","durationMs":6741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-6dac8417d0d497aaac00","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting a required custom property prunes it from the Data Product intake form","durationMs":4730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-745ad2dbeb0baf7b89c9","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"Domain uses the shared reference and hyperlink intake fields","durationMs":5577,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-7a224ded94f3d9482d6d","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can open the Intake Forms settings page","durationMs":4540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-7ba93be75799bd8bb941","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"intake form — toggling enabled flips enforcement in listing","durationMs":4758,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-a604d8c398d1b3c9e897","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can remove included and required fields from the Data Product intake form","durationMs":7271,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-aa15a66e0739e3407915","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"custom property required via intake form renders in Data Product create form","durationMs":6047,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-ab8fd64d057f8b4e104b","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"admin can include three custom properties and require one for Domain","durationMs":6209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-b83a4150530f02e4de1e","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"deleting a required custom property prunes it from the Domain intake form","durationMs":4546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-b94a856ca3586b5fc175","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"designer does not list schema-required fields","durationMs":4542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-c1893bc7c79b8a2c6792","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"pick admin user → DP create succeeds with correct extension payload","durationMs":7921,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-cc65a75585a345725083","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"intake form with required field blocks Data Product create when missing","durationMs":6830,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-e7165978ff4c41277836","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"delete popconfirm cancel keeps the intake form intact","durationMs":5319,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c660778f663f6ec6ca7d-fb3de0f6b91c1640f58e","project":"IntakeForm","file":"Pages/IntakeForm.spec.ts","title":"Data Product serializes each custom-property type for the create API","durationMs":9759,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c701921c8f8a6352b747-1d0279d918ed98fbd853","project":"chromium","file":"Features/Glossary/GlossaryPersonaCustomization.spec.ts","title":"Saving a persona Glossary Term customization keeps Relations Graph visible on the term page","durationMs":26565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c701921c8f8a6352b747-3e4cbd0d17abcacbd4ae","project":"chromium","file":"Features/Glossary/GlossaryPersonaCustomization.spec.ts","title":"Customize UI lists every documented Glossary Term tab including Relations Graph","durationMs":8222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c701921c8f8a6352b747-6b7c8374eaa7bfc7561b","project":"chromium","file":"Features/Glossary/GlossaryPersonaCustomization.spec.ts","title":"Customize UI lists Relations Graph at the Glossary parent level","durationMs":9839,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-0324d60b6dbd8f8464f8","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Date picker shows placeholder by default on Incident Manager page","durationMs":5967,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-0e4423b59bb3b0def9f6","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should switch back to \"Created at\" and call API with dateField=timestamp","durationMs":6524,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-125027e4b32a62c75284","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should show \"Created At\" as the default sort field label","durationMs":5814,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-32d7e88cbf346af3509b","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Date picker shows placeholder when no date is selected","durationMs":8667,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-4cdd71db2b45b447c142","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should switch to \"Updated At\" and call API with dateField=updatedAt","durationMs":6312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-7070354043463bf443d1","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should open sort field dropdown on click","durationMs":5895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-79b5270c77a649310404","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Select preset date range","durationMs":9584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-7c786efc5cc1d9524a5a","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Clear selected date range","durationMs":9307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-80618b8599611058eab3","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"should close sort dropdown after selecting an option","durationMs":6080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-849cf580e259e941a478","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Select and clear date range on Incident Manager page","durationMs":7723,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7a81e901cc82329b06c-f84790313494695fc98e","project":"chromium","file":"Features/DataQuality/IncidentManagerDateFilter.spec.ts","title":"Date filter persists on page reload","durationMs":12845,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-501f5e15e901e7595667","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should count a run once when every step reports the same rows","durationMs":3743,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-80f30314e037b61caf57","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should not treat a queued agent as complete","durationMs":4309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-aa3bafb435a4775d0dcf","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should open the run history drawer oldest-first with the newest run selected","durationMs":4680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-d7e791516d91072c1764","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should render the card run dots oldest-first with the latest one highlighted","durationMs":4687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c7ade81c61ee28f6ce8e-d9252481963da7628280","project":"chromium","file":"Features/ServiceAgentsDeploymentSummary.spec.ts","title":"should report the newest Metadata run rather than the sum of both agents","durationMs":3760,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-23c1b9c19b77e1fc296f","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"exports a data product to a valid ODPS YAML document","durationMs":127,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-2d68245dcb607af8c0af","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"merge preserves the existing product domain and owners","durationMs":259,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-31ec80fca2a586fb193f","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"imports an ODPS document onto an existing data product via the modal","durationMs":10772,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-43821278f0e90b25159f","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"rejects an invalid ODPS document on validation","durationMs":15,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-77e3363f6dbe1ec9bec0","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"exports ODPS YAML from the data product manage menu","durationMs":7962,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-89d478c0ae8f83c66123","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"name guard blocks a YAML whose product name targets a different product","durationMs":10247,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-8a42f9aa131de5003d2b","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"edits data product metadata (type, visibility, priority) via the modal","durationMs":11863,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-a9c2fd5fb6c0b42a6b96","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"name guard blocks a YAML with no readable product name","durationMs":10895,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-bab6dc59de12de6a2338","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"validates an exported ODPS document as valid","durationMs":140,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c85025e5f4661de2eb9f-c475de5d3a03ed61c517","project":"chromium","file":"Pages/DataProductODPS.spec.ts","title":"round-trips an exported ODPS document into a new data product","durationMs":292,"attempts":1,"retries":0,"outcome":"expected"},{"id":"c86397fc7242347df33b-dc47567d7f4a93925962","project":"chromium","file":"VersionPages/TestCaseVersionPage.spec.ts","title":"should show the test case version page","durationMs":10954,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-1744342f23a91efe2ac9","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display terms matching multiple selected statuses","durationMs":5453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-17aa0807877786e6d2a1","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should revert changes when Cancel is clicked","durationMs":5862,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-290c0b0873f5187f1fe3","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Deprecated terms when filtered","durationMs":9242,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-2e04698b958b1f4e22b9","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should return matching terms for search query","durationMs":4192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-497fd1b32f9258b6cdcf","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should maintain search when status filter is changed","durationMs":5358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-5988bf438e2f39e4958e","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only In Review terms when filtered","durationMs":8773,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-5c5d66935a2f20a348b2","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Rejected terms when filtered","durationMs":8576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-71684791e23a0abe70af","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should paginate through search results","durationMs":6756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-7939c6042ce0adcaac14","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should maintain status filter when search is cleared","durationMs":5629,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-81598be60b1e8ceceb18","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should restore all terms when search is cleared","durationMs":5275,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-8388ea65928d980767ca","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should show no results for non-matching query","durationMs":4729,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-9332080e850ab8fb8fd7","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display all terms when All is selected","durationMs":6513,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-9c52dee2717033c6e708","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should apply status filter within acceptable time","durationMs":5060,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-9fa4a97d5d3f5ab0ac59","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Draft terms when filtered","durationMs":9586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-c8d59fcb5e7f1932a6a5","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should reset pagination when filter changes","durationMs":8016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-dc48d37df803beca4aac","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should display only Approved terms when filtered","durationMs":9325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-e4e0242ef9806b0b92bb","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should maintain filter state across pagination","durationMs":5204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-ea41c0a0b7941de733e5","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should filter search results by selected status","durationMs":5211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ca2a80a6d2122ad97ca6-fcff743587908a5e53e7","project":"chromium","file":"Features/Glossary/GlossaryStatusFilterLargeDataset.spec.ts","title":"should paginate combined search and status results","durationMs":7911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-1dbd614d29e180690a85","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should search for multiple values along with null filters","durationMs":17334,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-259e61db1c16d9ad2c56","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"sort order is preserved in URL when explore tree node is clicked after applying a top dropdown filter","durationMs":8095,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-3c750142c90fdc4d2ea3","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"search dropdown should work properly for quick filters","durationMs":9422,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-41d7cc4f62d5990c09ec","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"tier with assigned asset appears in dropdown, tier without asset does not","durationMs":8880,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-440fb6c33a860d6545a3","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should persist quick filter on global search","durationMs":10016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-6779cdbcc9be1e4ce757","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"tier filter option label uses original casing from _source","durationMs":9581,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-6a16b691836f9597267b","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"service filter option label uses original casing from _source","durationMs":8020,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-7ac27f96d42f8e47da96","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"selecting a tier filter shows only assets tagged with that tier","durationMs":8459,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-7eae1a0879cfe84f3664","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"explore tree sidebar selection is not cleared when a top dropdown filter is applied","durationMs":8794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-848cdf4243eb28f21ee1","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"domain filter option label uses original casing from _source","durationMs":8507,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-8d58a7be6a15f6cea337","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"tag filter option label uses original casing from _source","durationMs":6860,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-b210b47079c7e8e1b96c","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"Filter by column entity type shows only column results","durationMs":6260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-c33910a88a1d9ed52dda","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"owner filter option label uses original casing from _source","durationMs":8284,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-d8b943596fe73627a88c","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should search for empty or null filters","durationMs":19009,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-dd2ed41905ade0359cc9","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"should show correct count for tier filter options from aggregation","durationMs":7386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caebfb61a8a7d76a7401-dd9f678b3ba6fdaee2cc","project":"chromium","file":"Features/ExploreQuickFilters.spec.ts","title":"breadcrumb shows the entity category and display name header should have highlighted terms","durationMs":6650,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-54366d53e73519025581","project":"chromium","file":"Pages/Tags.spec.ts","title":"Classification Page","durationMs":37455,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-584eb3fb0a38160ba39b","project":"chromium","file":"Pages/Tags.spec.ts","title":"Adds one tag and removes another in the same save preserves appliedBy on the kept tag","durationMs":10934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-816f4c77f914a4a50b2e","project":"chromium","file":"Pages/Tags.spec.ts","title":"Search tag using classification display name should work","durationMs":10570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-b188ae54e303d89cddb7","project":"chromium","file":"Pages/Tags.spec.ts","title":"Verify system classification term counts","durationMs":5347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-f2107feebb5f4a23b7cf","project":"chromium","file":"Pages/Tags.spec.ts","title":"Disabled tag should not allow adding assets from Assets tab","durationMs":13269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"caff76ae7fa460759ade-ffaf7183a75f1eb38486","project":"chromium","file":"Pages/Tags.spec.ts","title":"Verify Owner Add Delete","durationMs":11982,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-1eb1b3406ab1523f2de6","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Pipeline Services with the tag","durationMs":17703,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-22c58402d71610571ef9","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Mlmodel Services","durationMs":13583,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-2bf7f552e5db3d18b8ca","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Container with the tag","durationMs":15253,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-315faad65c8ba4786093","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Messaging Services with the tag","durationMs":13837,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-42713439b68b86645f59","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Storage Services with the tag","durationMs":17325,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-63da70180686ef526abb","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Api Services","durationMs":8675,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-6f451e1ed0db30ada664","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Messaging Services","durationMs":15248,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-73757c787b1e891e4942","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Dashboard Services","durationMs":18406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-80ec08540ad5cea8b4bb","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Database Services with the tag","durationMs":10807,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-84c48a5cf550dc52c755","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Database Services","durationMs":14718,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-9933c0dcae522f034354","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Storage Services","durationMs":16122,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-ac002e6c6d6ef1577d60","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Database Schema with the tag","durationMs":12204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-b103417ab8c8c1e51644","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Database Schema","durationMs":14464,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-b602604bfc080aa12682","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Database with the tag","durationMs":16911,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-bc1209cc5597e98ef443","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Mlmodel Services with the tag","durationMs":11344,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-bd75914d1b83464a8474","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Search Services","durationMs":17204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-d153874b1daabe75e2c9","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Api Services with the tag","durationMs":17543,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-d52c7043aa0749c2f533","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Pipeline Services","durationMs":12381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-e55cee40e3dc00883adc","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Database","durationMs":15991,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-ee63ecc5cd12d5f14e65","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with owner permission can only view owned Container","durationMs":18025,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-f299fb8782d3bc530837","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Dashboard Services with the tag","durationMs":12897,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cba1a86e45b2c609241f-f9fe927671719a4618d6","project":"chromium","file":"Flow/ConditionalPermissions.spec.ts","title":"User with matchAnyTag permission can only view Search Services with the tag","durationMs":11499,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-05cc587e9bcc4ffc92a5","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should show correct last activity format","durationMs":4389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-185ba09a3ff40aadfbe2","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should show user displayName in online users table","durationMs":17585,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-38ca992a32ea90db749c","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Non-admin users should not see Online Users page","durationMs":4796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-60029151e6f114b7185b","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should update user activity time when user navigates","durationMs":17066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-9635dbc86785af16b680","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should not show bots in online users list","durationMs":4786,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-b0a8e448e4aef58b283f","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should filter users by time window","durationMs":4793,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cc971de94aebfef8f0e8-e0123993246421502cb5","project":"Basic","file":"Features/OnlineUsers.spec.ts","title":"Should show online users under Settings > Members > Online Users for admins","durationMs":4813,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-0b48b047051e780992f2","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"an edge with the correct relationType exists between the term and its related term","durationMs":9341,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-23f4dd06dfefb5daf1e5","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"the directly related term appears as a node in the Relations Graph","durationMs":9165,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-40326bcc58edf3800037","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"search in the term Relations Graph returns empty state when no term matches","durationMs":9686,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-42b334d07c7288f87fb7","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"Relations Graph tab renders the ontology explorer for a term with a same-glossary relation","durationMs":10136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-58f0495abfd1f627c778","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"all relation types from the same term appear as separate edges","durationMs":9938,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-8446918a7f96b8df7a01","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"search in the Relations Graph filters to matching node and its neighbours","durationMs":9548,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-93c4b3dab6eb63fdc804","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"cross-glossary related term has an edge to the viewed term","durationMs":9326,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-ab0d405c8cc01c4864f2","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"the term itself appears as a node in the Relations Graph","durationMs":9378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-bb529b7f961d4f4e8a9a","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"unrelated term from the same glossary is NOT shown in the Relations Graph","durationMs":9427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-c656cbb70e6b22b42ae1","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"cross-glossary related term appears as a node in the Relations Graph","durationMs":9930,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-d160269e303147685186","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"clicking a node in the Relations Graph opens the entity summary panel","durationMs":9496,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cd1d8c8117a5902261ce-dbe5441e2495e4497f75","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraph.spec.ts","title":"a term with no relations shows only itself as a node with no edges","durationMs":10608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cdd6b2b4fe4563ae6f55-bc4aa4f69f836af1efe2","project":"Basic","file":"Features/Markdown.spec.ts","title":"should render markdown","durationMs":7423,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ce9a0dc862be823369ca-a412c4cd2b7d78e6c991","project":"chromium","file":"Features/ArticleReviewerWorkflow.spec.ts","title":"Context Center article reviewer approval flow","durationMs":97851,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-1ad99eb42c6a6c2096a1","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Search popover dismisses when input is cleared","durationMs":4742,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-2d0a0e7a0f4fed90f146","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Search returns results and clicking navigates to entity","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"cf5327dbf8787c8b5a98-2d178a12793a8b05209e","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"View All links navigate correctly","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"cf5327dbf8787c8b5a98-495f6d8a33cb34d89da5","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Widget card click navigates to entity detail page","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"cf5327dbf8787c8b5a98-976fa9972540355a732f","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Page renders with greeting, search, and default widgets","durationMs":4744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-ac16f93f70cd16752560","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Search with no results shows empty state","durationMs":4853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-adf188e977cee75f20a1","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Admin can create a domain via marketplace drawer","durationMs":5584,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5327dbf8787c8b5a98-c74336c0b248b65ccc9f","project":"Basic","file":"Pages/DataMarketplace.spec.ts","title":"Admin can create a data product via marketplace drawer","durationMs":6317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-1bae42cb06598b17b7fa","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"SearchIndex Service","durationMs":19097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-2597a651b0fd7aa710b6","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Api Collection","durationMs":19473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-5df1b00d3538afc3fa45","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Api Service","durationMs":19799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-5e6cd82cadd8b98f7f63","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Database","durationMs":20287,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-6554bce0546a1f330453","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Database Service","durationMs":19489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-6e4bf15cd073001e79cd","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Messaging Service","durationMs":19101,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-8ff37410faada701752e","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Mlmodel Service","durationMs":18645,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-9459bfdca9bc51b4e6e3","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Storage Service","durationMs":19222,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-d311a09902e6d3b6232d","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Drive Service","durationMs":19085,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-e3a737a636c50d641ee8","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Dashboard Service","durationMs":18636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-e88d4ed4325a35faf927","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Database Schema","durationMs":20478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5c5df849d9fa29e074-ec14d67dcd8f2fff65e6","project":"chromium","file":"VersionPages/ServiceEntityVersionPage.spec.ts","title":"Pipeline Service","durationMs":19129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5e7fcfd64428f1fc30-b5b1e23a960dc4431ef0","project":"chromium","file":"Features/Announcements/EntityHeaderAnnouncements.spec.ts","title":"shows announcements one at a time and pages through them with the counter","durationMs":14896,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5e7fcfd64428f1fc30-d1e3929c06f470275dc0","project":"chromium","file":"Features/Announcements/EntityHeaderAnnouncements.spec.ts","title":"opens the announcement drawer from the View all button","durationMs":10699,"attempts":1,"retries":0,"outcome":"expected"},{"id":"cf5e7fcfd64428f1fc30-e7fa692cbffac1b4f868","project":"chromium","file":"Features/Announcements/EntityHeaderAnnouncements.spec.ts","title":"hides the counter when a single announcement is active","durationMs":12347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-0844eeb3c8f64dcebe8f","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"delete-node-button absent in node config sidebar (structural edit blocked)","durationMs":10175,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-08877a68185e63ad1c70","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"save, cancel, and validate buttons visible; delete absent in edit mode","durationMs":9380,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-0b801c2b82a82d70400b","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"save-workflow-button fires PUT API and returns to view mode","durationMs":9927,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-150069a8255116907ea7","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"cancel workflow opens confirmation modal; close-without-saving returns to view mode","durationMs":10537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-18b487d25856aa924680","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"data-asset selector is disabled in OSS","durationMs":10031,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-2abad226603f3454795f","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"edit-workflow-button visible; delete-workflow-button and run-workflow-button absent","durationMs":9121,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-2bfb42a91f8a9136c462","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"add-event-filter-button is enabled in OSS","durationMs":9949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-412275bb43efcecd6fcc","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"include-fields-select is enabled in OSS","durationMs":10864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-41c9d3565357573bcecf","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"batch-size-input is enabled in OSS","durationMs":10118,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-4467d61b5a65f3cd8bc4","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"graph canvas contains workflow nodes","durationMs":9901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-4470c11ebbf089c50e17","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"save-node-configuration-button closes sidebar (local state update)","durationMs":10312,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-67ca6377f9ff6be4639b","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"clicking a node in view mode opens read-only config sidebar (no save or delete buttons)","durationMs":10331,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-783c6d9cebc65323299e","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"create-workflow-button absent on OSS","durationMs":8409,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-8745ccab715b20fcb20f","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"editing a form field and saving node config then workflow fires PUT API with updated data","durationMs":11014,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-9723cd69d43bc54d2eb1","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"workflow-name-input is disabled in OSS","durationMs":10139,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-9f41bef4230cdec8bde6","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"workflow-node-sidebar (node palette) not rendered in edit mode","durationMs":9798,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-baef39c5b1e533c7ce7a","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"trigger-type-select is disabled in OSS","durationMs":10269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-c71f895d70c3ecd5dc4c","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"event-type-select is disabled in OSS","durationMs":10707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-c7fea7d29c8d8403489a","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"workflow-description-input is enabled in OSS","durationMs":10243,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-cf2b0237655a0ceb88f4","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"execution history tab loads and API call succeeds","durationMs":8990,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-d93adb831434700a4faf","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"task node config sidebar opens and save button is enabled","durationMs":10400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-f0673f264fa79c7dd7ee","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"schedule-type-select is disabled in OSS","durationMs":10268,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d00abd619255ff3a0fce-fe7465f17d878dccc48d","project":"chromium","file":"Features/Workflows/WorkflowOssRestrictions.spec.ts","title":"exclude-fields-select is enabled in OSS","durationMs":10925,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-2e6774898e81ffe4c017","project":"Basic","file":"Pages/Login.spec.ts","title":"accessing app with expired token should do auto renew token","durationMs":142116,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-82c5ddfb9ec2446b9149","project":"Basic","file":"Pages/Login.spec.ts","title":"Signup and Login with signed up credentials","durationMs":8332,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-99d8d08a1bca0dfb45e7","project":"Basic","file":"Pages/Login.spec.ts","title":"Forgot password and login with new password","durationMs":5338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-d5d492b6a1719fc4c6bb","project":"Basic","file":"Pages/Login.spec.ts","title":"Signin using invalid credentials","durationMs":5620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d04c4b1fcaf773ee8b96-db2809b113bd2372c8c0","project":"Basic","file":"Pages/Login.spec.ts","title":"Refresh should work","durationMs":146336,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d0ed2e2518dfce56f3f7-055a575d29a60700f8c8","project":"chromium","file":"Flow/MetricListSearch.spec.ts","title":"typing in the search box filters the metric list server-side","durationMs":7308,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d279ac61280d1069feb3-b65e7f64e44f953e7467","project":"chromium","file":"Features/LandingPageWidgets/DomainWidgetFilter.spec.ts","title":"Domains widget should show only selected domain when domain filter is active","durationMs":16217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d279ac61280d1069feb3-e750f41ca4fc19634b37","project":"chromium","file":"Features/LandingPageWidgets/DomainWidgetFilter.spec.ts","title":"Setup Domains widget on landing page","durationMs":22934,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-3d5d145448d6f5cc90ae","project":"chromium","file":"Features/DataQuality/Profiler.spec.ts","title":"Update profiler setting modal","durationMs":14958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-54c0be66359a8c228744","project":"Ingestion","file":"Features/DataQuality/Profiler.spec.ts","title":"Data consumer role can access profiler and view test case graphs","durationMs":6623,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-b7926c0bc21906aa28a2","project":"Ingestion","file":"Features/DataQuality/Profiler.spec.ts","title":"Data steward role can access profiler and view test case graphs","durationMs":6565,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d2e3961af28bb907f482-e16c120deba5eb61a549","project":"Ingestion","file":"Features/DataQuality/Profiler.spec.ts","title":"Admin role can access profiler and view test case graphs","durationMs":6460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-2566c24a9ad53d85fb1e","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Export button opens scope modal with correct options","durationMs":6401,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-2acfadf8c9ab00eada55","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Filtered search visible export downloads CSV with the filtered record count","durationMs":21028,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-3b304a2ec3fc30ef4837","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Export queues a background job and downloads from the jobs tray","durationMs":17433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-414a8700c9cff70dc984","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Browse mode visible export downloads CSV with current page row count","durationMs":9405,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-6a546d5a8d744f5ab628","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Search mode visible export downloads CSV with tab-specific row count","durationMs":13250,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-9d106ae4569c23f8ea2d","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Search mode visible export count matches the first result tab count","durationMs":8570,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d423ec06c2369a4f0dbb-f159c7c0ad1b30a309b2","project":"ImportExport","file":"Features/SearchExport.spec.ts","title":"Export is disabled when all matching assets exceed 200k","durationMs":4762,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-209be753cb89befd2d8a","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"navigating to /table/TASK-XXXXX should show 404 (invalid URL pattern)","durationMs":7500,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-3cc2fe9e766015abfde3","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task in home feed widget should navigate to entity page","durationMs":7023,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-67253f2989896bce72d9","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"task link should contain correct entity FQN, not task ID","durationMs":8576,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-743cfd99537261dac3ad","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"task count badge should match actual task count","durationMs":8986,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-77ce1295765dba2968f2","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"two sessions: admin on Columns tab creates task, assignee sees refresh on notification click","durationMs":22439,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-7a2ad0726345cbc5accd","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task notification while on entity task tab refreshes the task list","durationMs":13820,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-8744e779751df9e9d0f9","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"assignee should see task in notification box","durationMs":9080,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-950d31f80797a93a58bf","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"task detail page with valid task ID should work","durationMs":8809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-a9ff5c396c0e2d45a234","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task notification should navigate correctly","durationMs":11276,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-ad4029189d87e59c6334","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"should display tasks in entity activity feed tab","durationMs":8901,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d4666ffb52311929304c-c12de98dc82239c7b83c","project":"chromium","file":"Features/Tasks/TaskNavigation.spec.ts","title":"clicking task card should open task detail drawer","durationMs":9537,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d517907dd258f94ebf35-0b8d134d4ce3b9e64ac8","project":"Basic","file":"Pages/DataMarketplaceAnnouncements.spec.ts","title":"Clicking announcement navigates to entity page","durationMs":0,"attempts":1,"retries":0,"outcome":"skipped"},{"id":"d517907dd258f94ebf35-2be67f3cc73b940823e9","project":"Basic","file":"Pages/DataMarketplaceAnnouncements.spec.ts","title":"Announcements widget renders with active announcements","durationMs":4202,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d5279e73c9dec6bec83c-4b950d2a14ba444c8c16","project":"chromium","file":"Features/RTL.spec.ts","title":"Verify DataAssets widget functionality","durationMs":12917,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d5279e73c9dec6bec83c-e61689c57f31e674f9b1","project":"chromium","file":"Features/RTL.spec.ts","title":"Verify Following widget functionality","durationMs":15964,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d68b190d81ed6f17e858-5baf6073a2435d76d5d0","project":"chromium","file":"Features/OntologyStudioIsolatedToggle.spec.ts","title":"isolated term is visible by default (showIsolatedNodes = true)","durationMs":36037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d68b190d81ed6f17e858-9550a9c338775c5f3796","project":"chromium","file":"Features/OntologyStudioIsolatedToggle.spec.ts","title":"toggling isolated nodes back ON restores the isolated term","durationMs":34690,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d68b190d81ed6f17e858-9971d291ad13253ddda2","project":"chromium","file":"Features/OntologyStudioIsolatedToggle.spec.ts","title":"toggling isolated nodes OFF hides the isolated term","durationMs":34470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d6fb355c03fdea638db7-305911a4b7881aaba0c1","project":"chromium","file":"Features/GlobalPageSize.spec.ts","title":"Page size should persist across different pages","durationMs":22751,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-0e1e2fb3daa2a1e6a51e","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"edits the Metric definition from Overview","durationMs":6633,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-0f2c9419d4dc153705df","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"filters, summarizes, selects, and unlinks Assets in bulk","durationMs":7829,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-24f7657b69904c89d7a5","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"lets the assigned reviewer approve a real Metric workflow in the UI","durationMs":3999,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-2633efd2499ffc50c3af","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"renders the generic lineage graph and hides editing from read-only users","durationMs":8323,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-3625b91a50b51a60e3ae","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"shows the approval status pill on the approval tab","durationMs":6001,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-58403b5dd25cf8299124","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"uses real workflows for rejection, rollback, and reverse-chronological history","durationMs":9539,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-6bc6d320db6666edfd89","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"reports Unknown health with a reason when nothing is linked","durationMs":36,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-7f52746cf88180c33007","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"creates a conversation and a task from the Activity tab","durationMs":6809,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-93d583042b14b6c5e0c6","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"shows the health pill and rollup reason on the observability tab","durationMs":5975,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-a1728b908facf5548686","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"renders the dedicated governance tabs and narrow assets state","durationMs":6506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-b146c4db39242757fbc9","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"a complete non-reviewer change enters review automatically","durationMs":1441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-b176476f838c8e177feb","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"a metric with no reviewers is approved on creation","durationMs":36,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-b27ed54e30c739637022","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"keeps Assets visible but hides relationship mutations for read-only users","durationMs":1958,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-b66805a4c9e9aa313731","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"scores only direct upstream table and column tests using their latest results","durationMs":4474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-f27e8e86db58b28a7c01","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"renders scored observability from upstream tests and incidents","durationMs":6185,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77aef94d4399f93856f-ffcc916ba4ddaa69276c","project":"Basic","file":"Features/MetricGovernance.spec.ts","title":"a reviewer-authored metric change is auto-approved","durationMs":2339,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77ba6914f7f6fb2fca4-98403d78db095df17303","project":"chromium","file":"Features/Workflows/NoOpWorkflowNodeConfig.spec.ts","title":"schema fields for runAppTask node are read-only","durationMs":8659,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d77ba6914f7f6fb2fca4-bceee39b29e98183822f","project":"chromium","file":"Features/Workflows/NoOpWorkflowNodeConfig.spec.ts","title":"schema fields for runAppTask node render with correct labels and values","durationMs":9692,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-03c031e4678082b99897","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Metric Entity Action items after rules is Enabled","durationMs":21117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-066a9ef811dff65e4cb6","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the MlModel Service Entity Action items after rules is Enabled","durationMs":14491,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-08a76fefd534a2c8a6a3","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Worksheet Entity Action items after rules is Enabled","durationMs":14470,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-0aac07ed470b079b032f","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Dashboard Service Entity Action items after rules is Enabled","durationMs":8982,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-130fbc8e073e46ded214","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Chart Entity Action items after rules is Enabled","durationMs":15663,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-279a27c38018c01b5a0f","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Database Entity Action items after rules is Enabled","durationMs":14505,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-2985a21f038abaa38e2b","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Pipeline Entity Action items after rules is Enabled","durationMs":14741,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-3d6a300eada29abc2ffd","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Table Entity Action items after rules is Enabled","durationMs":22445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-41f3fa56ebc98ef754ce","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Storage Service Entity Action items after rules is Enabled","durationMs":12004,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-572437ea2ab3f7320552","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Api Service Entity Action items after rules is Enabled","durationMs":10217,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-6473d71db2c0b882f00d","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"should enforce single domain selection for glossary term when entity rules are enabled","durationMs":10078,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-6d220edd7b3bfd3fe138","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the DashboardDataModel Entity Action items after rules is Enabled","durationMs":8207,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-759333f24dee762aea40","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the MlModel Entity Action items after rules is Enabled","durationMs":12841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-78e2dbbd9c1c1db98900","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the SearchIndex Entity Action items after rules is Enabled","durationMs":9864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-962838d6f4759abd09a2","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Database Service Entity Action items after rules is Enabled","durationMs":9062,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-aa332cfa334fdbc32d77","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Database Schema Entity Action items after rules is Enabled","durationMs":15216,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b0cc34f925752dfb14e5","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Messaging Service Entity Action items after rules is Enabled","durationMs":17976,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b11b9a17326398be8da7","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Topic Entity Action items after rules is Enabled","durationMs":13835,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b3308e67ec8457e0dee9","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Directory Entity Action items after rules is Enabled","durationMs":14869,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b7df5538066c06db4364","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the SearchIndex Service Entity Action items after rules is Enabled","durationMs":12090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-b9fb2556af6f3008e225","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Dashboard Entity Action items after rules is Enabled","durationMs":13607,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-ba8a638ac27ae4f109bd","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the File Entity Action items after rules is Enabled","durationMs":13953,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-bfeb0bcea2e0396acdd3","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Container Entity Action items after rules is Enabled","durationMs":11853,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-ccf02cb9cfd7b194ec16","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Drive Service Entity Action items after rules is Enabled","durationMs":10669,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-cec8b7118f5a613d3132","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Pipeline Service Entity Action items after rules is Enabled","durationMs":11906,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-d444bfd28e07070c2777","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the ApiEndpoint Entity Action items after rules is Enabled","durationMs":21399,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-dd030b4671b685a60fc8","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Spreadsheet Entity Action items after rules is Enabled","durationMs":13097,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-e435bf4efd3242cc32d8","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Api Collection Entity Action items after rules is Enabled","durationMs":14307,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d8f8caeb6165f1ef1fcd-ff33cabf88b06ecbd0b9","project":"DataAssetRulesEnabled","file":"Features/DataAssetRulesEnabled.spec.ts","title":"Verify the Store Procedure Entity Action items after rules is Enabled","durationMs":15314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"d9f997795c80930b24d6-bf921a12f0124551e220","project":"Reindex","file":"Features/SearchSeparation/GlossaryRenameCascade.spec.ts","title":"glossary-term rename cascade keeps tags[] + glossaryTags + tier + cert consistent","durationMs":1552,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-06b8c08d4cabd6603635","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"DQ dashboard API carries tag filter","durationMs":6129,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-2af86017b01f6bdc2b71","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"clicking Data Observability tab loads DQ dashboard widgets","durationMs":6209,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-2f9a9790171a0d23ecbe","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"Data Observability tab absent in version history view","durationMs":3980,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-3ed728877ac6a48879de","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"clicking Data Observability tab loads DQ dashboard widgets","durationMs":6620,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-673ae7c8b7ec3c3affc3","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"clicking Data Observability tab loads DQ dashboard widgets","durationMs":4493,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-73606198210a4d7ca076","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"glossaryTerms filter is hidden on GlossaryTerm Data Observability tab","durationMs":3879,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-7645dbf4af3497d08343","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"Data Observability tab absent in version history view","durationMs":4214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-76ec8ab8ce8ce2b149c2","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"DQ dashboard API carries glossaryTerms filter","durationMs":4730,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-805007763e0ee5d5ec82","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"standalone DQ dashboard still shows the filter bar","durationMs":7112,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-83f5755364b2bb6d8713","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"DQ dashboard API carries domainFqn filter","durationMs":4093,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-954f5e30a09edbd7462a","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"switching back to Overview tab hides the DQ dashboard","durationMs":6417,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-b4092a35d4098fe815c1","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"filter bar is visible on Domain Data Observability tab","durationMs":3968,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-bd8ebaa0e4d04266e712","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"tag filter is hidden on Tag Data Observability tab","durationMs":6187,"attempts":1,"retries":0,"outcome":"expected"},{"id":"daa3a37536228573ce51-f9c38769f3ba40a03d59","project":"chromium","file":"Features/DataQuality/DataObservabilityGovernanceTab.spec.ts","title":"applying tag filter returns a successful DQ API response","durationMs":8130,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-879aff3f25587ae15c61","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"Data Steward is blocked from every bulk edit and import page","durationMs":18042,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-cc9be6afc1f0a8405f38","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"Editor with EditAll can access every bulk edit and import page","durationMs":70949,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-e2134863425ccaa50016","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"Data Consumer is blocked from every bulk edit and import page","durationMs":17441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db1daaef72d72e2312ab-ee37951858f3d500023e","project":"ImportExport","file":"Features/BulkEditImportPermissions.spec.ts","title":"View-only user is blocked from every bulk edit and import page","durationMs":20137,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db7911e8ad1498312207-6e5c70587b89b9de795f","project":"chromium","file":"Features/ActivityFeedTabBadge.spec.ts","title":"badge reflects openTaskCount in Open filter and closedTaskCount in Closed filter","durationMs":24478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db7911e8ad1498312207-bd810da56c5dbdd7767b","project":"chromium","file":"Features/ActivityFeedTabBadge.spec.ts","title":"entity tab count equals the sum of the All and Tasks badges","durationMs":14176,"attempts":1,"retries":0,"outcome":"expected"},{"id":"db7911e8ad1498312207-dccdb1943a15a38f4471","project":"chromium","file":"Features/ActivityFeedTabBadge.spec.ts","title":"placeholder shows the correct message per filter state","durationMs":14420,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-0517bed5a24d15a2ba7f","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should handle multiple items being hidden at once","durationMs":15708,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-2fe0ce861993b8034264","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should handle reset functionality and prevent navigation blocker after save","durationMs":14616,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-311db8180f2642a6a095","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should save changes and navigate when \"Save changes\" is clicked in blocker","durationMs":19197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-37062c9a70d1d97f2f9e","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should support drag and drop reordering of navigation items","durationMs":12059,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-3f83c3e394f2f9d87301","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should reflect a sub-item moved to another group in the sidebar after applying the persona","durationMs":19593,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-7a54741073907c77c8ac","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should show navigation blocker when leaving with unsaved changes","durationMs":15104,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-d7fe854a3fe31f16df34","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should update navigation sidebar","durationMs":19100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dca77550792490d323d6-df0e4058a5ba929c6f8d","project":"chromium","file":"Features/SettingsNavigationPage.spec.ts","title":"should persist a reordered sub-item after reload","durationMs":19673,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dd642ff9f3c87efa9c10-dba5285969e2c24eec98","project":"ImportExport","file":"Pages/CSVImportWithQuotesAndCommas.spec.ts","title":"Create glossary with CSV, export it, create new glossary and import exported data","durationMs":73534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-17f0abe122865c573a49","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"ViewBasic permission shows read-only access","durationMs":22756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-1f0be66ac1cb6ab2b83d","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Team-based permissions work correctly","durationMs":21100,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-2b6740212b2249e5cc01","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Glossary deny operations","durationMs":22763,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-3188a2dc2a31bdee3d75","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"EditOwners only permission","durationMs":24111,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-33796de90ddf3f62b1f2","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Delete only permission","durationMs":23855,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-450caad10c6db1648382","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Create only permission","durationMs":23687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-4d14e53f4d7b0b15aaed","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"EditTags only permission","durationMs":22547,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-e72e8a08ee837b49f474","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"EditDescription only permission","durationMs":22144,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df0772b93fcf032846ae-f6f497a28461c645595b","project":"chromium","file":"Features/Permissions/GlossaryPermissions.spec.ts","title":"Glossary allow operations","durationMs":13037,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-3007293d39fd27b73cad","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Stored Procedure Table should have sorting on name column","durationMs":8634,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-35e294a729e304ae5ecb","project":"chromium","file":"Features/TableSorting.spec.ts","title":"API Endpoint page should have sorting on name column","durationMs":7489,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-417e1899c674ba056816","project":"chromium","file":"Features/TableSorting.spec.ts","title":"should have sorting on name column","durationMs":7269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-897fd6be8d196093945f","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Topics Table should have sorting on name column","durationMs":7446,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-8df3b2994395a9dcc5f5","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Drives Service Spreadsheets Table should have sorting on name column","durationMs":8453,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-934f69ec265bfc985585","project":"Ingestion","file":"Features/TableSorting.spec.ts","title":"should have sorting on name column","durationMs":3998,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-a54e163ad0d6ada016a4","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Database Schema Tables tab should have sorting on name column","durationMs":8234,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-b40a460170ea3e12c7e1","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Services page should have sorting on name column","durationMs":6574,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-bdfb9efa450fc8d6224b","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Database Schema page should have sorting on name column","durationMs":7761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-ca3d2db60a7a4385e32b","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Data Models Table should have sorting on name column","durationMs":7778,"attempts":1,"retries":0,"outcome":"expected"},{"id":"df23f6ad1ee603a6ae65-e2cc6fb3ceccaeb1a09c","project":"chromium","file":"Features/TableSorting.spec.ts","title":"Drives Service Files Table should have sorting on name column","durationMs":7941,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-2321814453e125b66353","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should move term with children to different glossary","durationMs":21794,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-6b80fdb91ed3204a5d79","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should cancel drag and drop operation","durationMs":11184,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-b00abfec58cbc6f25ba5","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should cancel move operation","durationMs":19952,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-bdba8a60b71c0b075dae","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should move term to root of different glossary","durationMs":20073,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-e65e5779dd8c704d0ab2","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should move nested term to root level of same glossary","durationMs":20486,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-e7b4a28ff6323e173bb5","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should navigate 5+ levels deep in hierarchy","durationMs":12186,"attempts":1,"retries":0,"outcome":"expected"},{"id":"dfe16293eef39cdaf975-eb3d35861683904e3e32","project":"chromium","file":"Features/Glossary/GlossaryHierarchy.spec.ts","title":"should drag nested term to root level of same glossary","durationMs":21412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e13cf584214701b07f57-1afee2626234d27ccae5","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":30878,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e13cf584214701b07f57-4ab3e6f02d449cca814a","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":27370,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e2d639d408792a06975c-7a6c81a675faa6254493","project":"Basic","file":"Flow/UsersPagination.spec.ts","title":"Testing user API calls and pagination","durationMs":5608,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e35d7dd71e822f3001e7-3cfbb66ae88e3514c5b2","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":16220,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e35d7dd71e822f3001e7-432b8cb5b927d6df6807","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":17823,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-7154f830ca4d55756208","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"a browse-location deep link highlights the tree and clears on chip removal","durationMs":15463,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-759bee3eb0181dc15eae","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"reloading the page preserves composed filters","durationMs":14887,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-9da821fade89f083f3ed","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"an impossible filter combination shows the no-results placeholder and recovers on clear","durationMs":18586,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-9ec4db1c07256b4bbde6","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"applying a filter from a deep page preserves pagination params","durationMs":17223,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-adbb03bd2ffa82ca5802","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"selecting an asset type grays out and collapses incompatible categories","durationMs":8961,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-b871193e778bd381ca8d","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"a deep-linked filter URL restores chips and filtered results","durationMs":19594,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e552adcc6ce8fb46c729-f2ce25709e1201e3797f","project":"chromium","file":"Features/ExploreUrlState.spec.ts","title":"owner filter spans asset types and ANDs with an asset-type filter","durationMs":16784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-0942d72a0198995838ac","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Metric","durationMs":354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-147633f9a3cb97439f47","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for GlossaryTerm","durationMs":414,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-20324ac8b868e83321ef","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Table","durationMs":377,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-2b8226ae0f295584a097","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for MLModel","durationMs":404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-2c5fcdbed087327ee250","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Metric","durationMs":452,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-3a95a887039194a669b6","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Table","durationMs":309,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-431dd35d48f6c5bcdc40","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Table","durationMs":487,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-43cfe0395336c7874d2d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Glossary","durationMs":404,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-52e0dd99e1c1dcda9296","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Metric","durationMs":381,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-590d64ea0d6d3432312d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Pipeline","durationMs":732,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-6076582e5142165747b7","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for File","durationMs":233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-60b6f2e8e65c4a1d9316","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Container","durationMs":1412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-62f33d5a7ba6afa42c5b","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Pipeline","durationMs":603,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-65977a8e252c1884495f","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Topic","durationMs":687,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-72ca55efac5e37216621","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for MLModel","durationMs":354,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-7475dc44973d9389678c","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for DataProduct","durationMs":427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-76375b057ea4b8a3a914","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for MLModel","durationMs":400,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-79a962dcb0d2df39591f","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Glossary","durationMs":317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-7ca8750db292c6811fab","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for SearchIndex","durationMs":358,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-8462d9dafd86d4cb7a24","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Dashboard","durationMs":407,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-87349bc4da359d33210e","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Container","durationMs":877,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-8b624e5fee37ea1427cb","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for SearchIndex","durationMs":479,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-8ea1a343c7b62f387879","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Dashboard","durationMs":461,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-9017945823aea8c31e65","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Topic","durationMs":492,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-92f1ec834cf376a73ae6","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for File","durationMs":204,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-9676563ef902c007c998","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Dashboard","durationMs":445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-9724e6857c64f0c5f6fb","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Directory","durationMs":614,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-a19e745a80175cd48c5f","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Topic","durationMs":540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-a45bbfe31b09ade0e947","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Container","durationMs":680,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-a9bd3aaaf359e0f5e01e","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for DataProduct","durationMs":674,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-b05d36b597ce8e148023","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for SearchIndex","durationMs":517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-becea4046545cedb234c","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Pipeline","durationMs":398,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-c5d58d76277e5a4a1fa8","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Dashboard","durationMs":427,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-c9d917883dbfefee36a7","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Table","durationMs":338,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-ce553d1c2da64d450d17","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for Pipeline","durationMs":389,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-cea3022de30e27291656","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for GlossaryTerm","durationMs":350,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-e17b4094c0f9dbdd345c","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for File","durationMs":260,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-eba55dd6b22bb101f65d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"OwnershipUpdate task for GlossaryTerm","durationMs":707,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-ebffb46a0650e1e63b25","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Metric","durationMs":395,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-efdd01ba42a7838ececc","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Container","durationMs":1066,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f1cdb4d14559b84e7e90","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DomainUpdate task for Directory","durationMs":509,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f577090e7c0c2c6d1672","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for Topic","durationMs":450,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f7241889791483b397a1","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"TierUpdate task for MLModel","durationMs":252,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-f7f3a5872d0f5075a31d","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Glossary","durationMs":478,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-fbf598a3f758d45a8e87","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for SearchIndex","durationMs":1214,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e6106fb403b25b398095-ff39d1cbf073725e11f9","project":"chromium","file":"Features/Tasks/TaskAllEntities.spec.ts","title":"DescriptionUpdate task for Directory","durationMs":817,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-27bf83ebb148b83122c8","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Database service","durationMs":52300,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-393e6fb3b55e026c5927","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Database","durationMs":50230,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-80d244c353a9b5239063","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Table","durationMs":28761,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-864b2325f77eb8ef0979","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Database Schema","durationMs":59959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-8b088f9fd4352335f186","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Glossary Term (Nested)","durationMs":50210,"attempts":1,"retries":0,"outcome":"expected"},{"id":"e91c95e3d77f8c0bc288-afada82cd2191181328b","project":"chromium","file":"Features/BulkEditEntity.spec.ts","title":"Glossary","durationMs":57347,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-991e22827d785d044de8","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing a child term: parent appears as a 1-hop neighbour via parentOf edge","durationMs":12556,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-9a9e5f8ec1ab595d1664","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing a child term: parentOf edge is rendered between parent and child","durationMs":10847,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-cb3f581754b8a14c9209","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing the parent term: parentOf edge is rendered between parent and child","durationMs":8770,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eaaf55fe056d7976bbf2-ea60b9272f2de2cae5c9","project":"chromium","file":"Features/Glossary/GlossaryTermRelationsGraphNested.spec.ts","title":"viewing the parent term: child appears as a 1-hop neighbour via parentOf edge","durationMs":11378,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-0872d0c75b5f4a1eea22","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Bulk edit existing entity with dot in service name","durationMs":31756,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-11b6b2822f5d1e76a451","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Import at database level with dot in service name","durationMs":39858,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-2b628617654ecf4bdd25","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Import at schema level with dot in service name","durationMs":28396,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-4ae957d1d4bc40c66b27","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Service name with multiple dots","durationMs":27777,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-61e520c2d24c8cb303be","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"CSV with quoted FQN loads correctly in import grid","durationMs":27717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-8640e5baa9623705571d","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Column with dot in name under service with dot","durationMs":20311,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-9831613d51f1f5074fcd","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Full import cycle with dot in service name","durationMs":32379,"attempts":1,"retries":0,"outcome":"expected"},{"id":"eb9d2258e81ed2ed488c-adf1fb39ffb44f305718","project":"ImportExport","file":"Features/BulkImportWithDotInName.spec.ts","title":"Database service with dot in name - export and reimport","durationMs":30967,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-451958641a79328fe77b","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Install application","durationMs":4935,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-a3a1e60b3e20e393c2f1","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Edit application","durationMs":5821,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-b0cd1177775297960d65","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Uninstall application","durationMs":5251,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ecc55bb88d5bb5b0e830-d65f3bc388f55deee256","project":"chromium","file":"Pages/DataInsightReportApplication.spec.ts","title":"Run application","durationMs":7070,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-00727756ed54b11d9d66","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify fullscreen toggle","durationMs":6238,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-0de408c32267fb067d06","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify DQ layer toggle activation","durationMs":8519,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-2fd3d671fe79e7aa79e6","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify DQ layer toggle off removes highlights","durationMs":10270,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-61f864881a368270e9b4","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify minimap toggle functionality","durationMs":8691,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-a50f5062bdbb068e2796","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify invalid entity search handling","durationMs":5532,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-b82c3c1c96ccc2c41e8d","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify lineage tab with no lineage data","durationMs":10545,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-f67f93500d58072add25","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify zoom in and zoom out controls","durationMs":8542,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ed4b297649681930e242-fa08f156b0ba6e20421a","project":"Basic","file":"Pages/Lineage/LineageControls.spec.ts","title":"Verify fit view options menu","durationMs":8117,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f04fe376fb0432d1a2bc-409b7ba941e62aadeeab","project":"Basic","file":"Features/MetricActivityTasks.spec.ts","title":"opens an approval request from Tasks in the Approval Workflow tab","durationMs":3433,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f04fe376fb0432d1a2bc-d587fcce31d7abfcaac5","project":"Basic","file":"Features/MetricActivityTasks.spec.ts","title":"creates a mentioned conversation and completes a description task","durationMs":8207,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-3acaa880cb4773e73f12","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk cancel operation","durationMs":190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-3d3e2def8f2e96897376","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should handle partial failures in bulk operations","durationMs":496,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-4a32405d0d74df2c5db6","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk approve on multiple tasks","durationMs":744,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-94ecf2bb50f9c561671f","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should reject non-suggestion task via apply endpoint","durationMs":136,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-95ba2888711a203eb077","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk reject on multiple tasks","durationMs":799,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-c46ffd4656a5fdf657cc","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should perform bulk assign operation","durationMs":841,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f13fd72ccbb76b94fb18-febb592c17f5eea5e817","project":"chromium","file":"Features/Tasks/TaskSuggestionAPIs.spec.ts","title":"should apply suggestion via PUT /api/v1/tasks/{id}/suggestion/apply","durationMs":533,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f424f0b2de2b8353168d-3a71a044adebef3ad89e","project":"chromium","file":"Features/ContextCenterArchive.spec.ts","title":"full document lifecycle: folder expand icon, upload, delete, restore, and permanent delete","durationMs":31065,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f424f0b2de2b8353168d-82b0e753e7d46cd9890c","project":"chromium","file":"Features/ContextCenterArchive.spec.ts","title":"archive page lazy-loads more rows on scroll within its own scroll container","durationMs":8955,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f424f0b2de2b8353168d-99117e03aa3c5b328397","project":"chromium","file":"Features/ContextCenterArchive.spec.ts","title":"file in deleted folder is absent from search and not added to archive","durationMs":13114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-075d5e867770cf289c8d","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"data steward cannot edit team subscriptions","durationMs":12977,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-233b01cc9bf79b6f3f4b","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should disable endpoint input when webhook type is None","durationMs":10233,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-388f9f7a9983f83d39d1","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should update existing subscription to different webhook type","durationMs":10784,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-4089f84abb290168ef0c","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should validate endpoint URL format","durationMs":10473,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-54a2d04779b87540a00d","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure Slack webhook subscription","durationMs":9016,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-5c2b44855ea7aac27a3f","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should remove subscription by setting webhook to None","durationMs":10314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-67f33babda3fdf4febf5","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"team member without owner role cannot edit subscriptions","durationMs":15435,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-842a1076b8d1906ba450","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"admin can edit subscriptions for any team","durationMs":11592,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-8609b568b701057602c0","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"data consumer cannot edit team subscriptions","durationMs":13959,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-86d32d813fc943a78e43","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should display subscription as None when no subscription configured","durationMs":9267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-8d2d31841b63ddf340ff","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure Google Chat webhook subscription","durationMs":9090,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-a27b2e53b3221dbc8290","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should require endpoint when webhook type is selected","durationMs":9837,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-a9d0c9c4799698417f3d","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should open and close subscription edit modal","durationMs":10445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-b4f94192f34e07d52e1e","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure MS Teams webhook subscription","durationMs":10501,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-bff65aca6ff47e244d26","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should persist subscription after page reload","durationMs":14192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-fca848d6346f22013a7f","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"should configure Generic webhook subscription","durationMs":11346,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f44c58dbc6674b565498-ff289db727fd13098421","project":"chromium","file":"Features/TeamSubscriptions.spec.ts","title":"team owner can manage subscriptions","durationMs":21599,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-249f2e80e1ed07c92f7e","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should rename data product and verify assets are still associated","durationMs":18957,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-600e291c7d231e7f82c1","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should show error when renaming to a name that already exists","durationMs":11324,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-6edae00094cd060fc0a5","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should handle multiple consecutive renames and preserve assets","durationMs":24936,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4b9c2f714eeb699f610-90803266ddfc79e89669","project":"chromium","file":"Features/DataProductRename.spec.ts","title":"should update only display name without changing the actual name","durationMs":13314,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4cae74b06fda076f0a1-b770428f72ba5b0a9d85","project":"chromium","file":"Features/BlockEditorEmbedLink.spec.ts","title":"entering an invalid URL shows validation error and does not crash the editor","durationMs":9298,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-0462ac71e8c91afbbf6c","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Stored Procedure - customization should work","durationMs":24460,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-0702a83ca7d8b8bbd8c0","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"customize navigation should work","durationMs":31317,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-25846c7a65b11a89cff2","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Container - customization should work","durationMs":30050,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-37449f25e978be1788be","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Glossary - customization should work","durationMs":24375,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-41d0a892fca6d9343808","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Data Product - customization should work","durationMs":29527,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-455659b2d17f62c06d8e","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Domain - customize tab label should only render if it's customized by user","durationMs":22197,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-59a82d5c1ea5278c7323","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Search Index - customization should work","durationMs":25579,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-59f9c9ce01e8f4c75fa9","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Validate Glossary Term details page after customization of tabs","durationMs":23219,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-658ea4555cba25bb9b09","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Ml Model - customization should work","durationMs":26190,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-729b695acd411ed7fcb8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Dashboard - customization should work","durationMs":25269,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-75c1ec0b785dfbe2e9f8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Pipeline - customization should work","durationMs":24942,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-81ab6a13446be00d2236","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Topic - customization should work","durationMs":22792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-a1007d349e35f17016eb","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Database Schema - customization should work","durationMs":27114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-b83e17354b58f3885232","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Database - customization should work","durationMs":24257,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-b86710bce42df069ca07","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Dashboard Data Model - customization should work","durationMs":25625,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-bccd2187cd76d2275312","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Table - customization should work","durationMs":24717,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-c23463689b6a02ae53e8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"customize tab label should only render if it's customize by user","durationMs":27575,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-c77322af934d1f2cf284","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"should show all the customize options","durationMs":11432,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-ca3857c050b462ada785","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"should show all the governance customize options","durationMs":11448,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-cda13e1a745c6788e3ed","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"API Endpoint - customization should work","durationMs":24546,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-dc93b1114afcda98e4d8","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Navigation check default state","durationMs":11372,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-df1705426fee23699c44","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Glossary Term - customization should work","durationMs":25540,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-f36a44fc5a95e395227f","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"Domain - customization should work","durationMs":22720,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-f67ada2b0e7642366d4c","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"should show all the data assets customize options","durationMs":10844,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4edbfb1b6fddb316551-f6f733b3ac3589b9dfd1","project":"Basic","file":"Features/CustomizeDetailPage.spec.ts","title":"API Collection - customization should work","durationMs":22552,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-0205ffdfc585cab01ddf","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Database Schema","durationMs":359636,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-169d67f201cb81f89740","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Table","durationMs":158261,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-642237d4a41dc49da1dd","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Database","durationMs":330408,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-95b213492138666fe484","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Keyboard Delete selection","durationMs":137441,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-bb8bb17e2fefc0c05203","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Range selection","durationMs":26965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4ee211d44d440f1499f-f582fd9991e819296458","project":"ImportExport","file":"Features/BulkImport.spec.ts","title":"Database service","durationMs":455007,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f4f25d988842201e6c20-ae24e2a0aae5144bba18","project":"chromium","file":"Flow/ExploreAggregationCountsMatching.spec.ts","title":"should verify left panel counts and tab search results for normal search","durationMs":5978,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f63edb310b70898c32ef-404b1e6d790711af858c","project":"DomainIsolation","file":"Features/DomainIsolation/DomainLineageIsolation.spec.ts","title":"userA sees tableA but not the cross-tenant tableB node","durationMs":8648,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f63edb310b70898c32ef-80db248d069981e2eab0","project":"DomainIsolation","file":"Features/DomainIsolation/DomainLineageIsolation.spec.ts","title":"admin sees both nodes in the lineage graph","durationMs":6971,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f63edb310b70898c32ef-9807ba0d848bcddb4727","project":"DomainIsolation","file":"Features/DomainIsolation/DomainLineageIsolation.spec.ts","title":"userB sees tableB but not the cross-tenant tableA node","durationMs":6582,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-059206e1428a5297d108","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create TierUpdate task for Topic","durationMs":143,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-408ca4feecc6e89950e5","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create OwnershipUpdate task for Topic","durationMs":610,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-448a9a33c07636db1183","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create and approve schema field description task for Topic","durationMs":211,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-9833d1f4ad179adb98f1","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create DomainUpdate task for Topic","durationMs":246,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f79bc63730b3a4ab9a09-c54d52f5c5aeaa552192","project":"chromium","file":"Features/Tasks/TaskTopicEntity.spec.ts","title":"should create and approve entity-level description task for Topic","durationMs":218,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c386facc843a14ec19-6a408855f47e7887f923","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"live indexing produces searchable separation for all four facets","durationMs":28119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c386facc843a14ec19-ed35b4deecb9ca47009d","project":"Reindex","file":"Features/SearchSeparation/SearchSeparationSuite.ts","title":"SearchIndexApp recreate reindex preserves searchable separation","durationMs":28113,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-0a44a983974730b89f64","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-H01: ME glossary (top level) children render Radio with ME behavior","durationMs":10012,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-3fcaec003ed89f7e3e4c","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-S02: Can select multiple children under non-ME parent","durationMs":11293,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-5651fb4202fceb9735a1","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-R02: Children of non-ME parent should render Checkboxes","durationMs":9832,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-5cb89ffa42856f160ca8","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-R01: Children of ME parent should render Radio buttons","durationMs":10476,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-9b44f296c9a6d33e51fb","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-T01: Apply single ME glossary term and save Data Product","durationMs":10796,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-9c2585c3aa05ec0e24c0","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-S03: Can deselect currently selected ME term","durationMs":10370,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f7c7d30f69242f500c7d-efa1868c007a3e6cbd21","project":"chromium","file":"Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts","title":"ME-S01: Selecting ME child should auto-deselect siblings","durationMs":11641,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-0dbac478b849946a6c3c","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"Tag - should handle multiple consecutive renames","durationMs":15386,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-17c1918984f0172bbbe9","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"GlossaryTerm - should handle multiple consecutive renames","durationMs":22039,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-725c0e89e0d163df757d","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"Glossary - should handle multiple consecutive renames","durationMs":19787,"attempts":1,"retries":0,"outcome":"expected"},{"id":"f81c31bc13c7bff34728-8c9a6934d3b95c2c1d12","project":"Basic","file":"Features/MultipleRename.spec.ts","title":"Classification - should handle multiple consecutive renames","durationMs":19406,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa42a344a1491728c88c-ca790fdf6e37164c48c6","project":"Basic","file":"Features/MutuallyExclusiveColumnTags.spec.ts","title":"Should show error toast when adding mutually exclusive tags to column","durationMs":10506,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-1658d542d353f5e8537c","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"success state shows Done button and hides Edit Connection and Retry Test","durationMs":12069,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-168f03efee35ec66edfb","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"failure state shows remediation card with error content","durationMs":12119,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-2c7d4ad226db72ac9f82","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"changing a form field after a successful test resets the connection badge","durationMs":12522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-4b58db22ce037337317f","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"raw log toggle shows and hides connection log","durationMs":12792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-8cc727200eac97c77b66","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"Edit Connection click dismisses the modal","durationMs":12263,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-8e06fc7c08d9ab043ed2","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"validation shows RJSF field errors on first click when only service name is filled","durationMs":8590,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-b2346dfc921ce5e28a27","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"failure state shows Edit Connection button and Retry Test button","durationMs":12232,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-e8d2f77fc5c536d510c7","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"validation shows all required field errors on first click when all fields are empty","durationMs":8384,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fa5f79ecd04956bda88a-f124d2edb8c14295a059","project":"Basic","file":"Flow/TestConnectionModal.spec.ts","title":"modal opens with gate card and capability checks sections","durationMs":10264,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-35df4cdd13ee89a8d38d","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"Different user can view but cannot modify service owned by another user","durationMs":12672,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-3c28749487fae15018ac","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User with service creation permission can create a new database service","durationMs":10206,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-7e5ca4567f5a88b8e298","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"Owner can update description of their service","durationMs":6965,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-8e6d87b24ddeccf497e7","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User can view but cannot modify services they do not own","durationMs":6029,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-955a42cfe4f501beb1ab","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"Owner can delete their own service","durationMs":7235,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-a51b62db11ad9675f612","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User with EditAll but not Trigger cannot run a pipeline","durationMs":6838,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-c733a081bb38e4e8f7e8","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User with Trigger permission can run an ingestion pipeline without EditAll","durationMs":6704,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fac4eb6fec988313873a-f200b75084f8b2928afc","project":"Ingestion","file":"Flow/ServiceCreationPermissions.spec.ts","title":"User can update connection details of their own service","durationMs":6534,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-00b4b832ff041854728c","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"renders a description-updated activity item in the feed","durationMs":18670,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-264131b8e9c311797619","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"displays feed content in the Activity Feed widget","durationMs":7685,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-2cc7490b8f2a552d8433","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"adds a comment to a feed item","durationMs":14559,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-38913b446c5ece4b7589","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"adds a reaction to a feed item","durationMs":17865,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-6dae248f6b6f0c87dc65","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows the activity detail layout, read-only","durationMs":14786,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-8501761be150a7ac4fe9","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows the activity detail layout","durationMs":14947,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-b23432aca7892b48a5e2","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"routes each Activity Feed widget filter to its own endpoint","durationMs":19891,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-ce699d538b116cbec69b","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"removes an existing reaction from a feed item","durationMs":17714,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-d48cfc9fae2794bc1d35","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows Activity Feed widget filter options","durationMs":9628,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fb7cce549039f779ebf8-ffbf0a15623c2f20aed0","project":"chromium","file":"Features/ActivityAPI.spec.ts","title":"shows the followed entity activity under the Following filter","durationMs":8322,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc426d31c2c6443c1be6-05800e3a4ea5b64d3da3","project":"DomainIsolation","file":"Features/DomainIsolation/DomainListingIsolation.spec.ts","title":"userA sees only tenantA on the domains listing page","durationMs":6412,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc426d31c2c6443c1be6-4518202e8a9e1f36a215","project":"DomainIsolation","file":"Features/DomainIsolation/DomainListingIsolation.spec.ts","title":"userB sees only tenantB on the domains listing page","durationMs":6114,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc426d31c2c6443c1be6-d5d4bf170dffa3f33a63","project":"DomainIsolation","file":"Features/DomainIsolation/DomainListingIsolation.spec.ts","title":"admin sees both tenants on the domains listing page","durationMs":7597,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc6611f5f281a4e45f8c-75cb78dafb20bfb5e68f","project":"Reindex","file":"Features/DataQuality/TestSuiteListAfterReindex.spec.ts","title":"Basic test suite stays listed on the table-suites page after a full reindex","durationMs":1188,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-29eff01a200d84238a47","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should create glossary with special characters in name","durationMs":9828,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-2fe6a9452e85458797d7","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should show history popover on status badge hover","durationMs":11445,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-3f4b2313c27eb62355cd","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should show column settings with custom properties option","durationMs":10536,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-439407dfe7f6467e411a","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should create term with Draft status when no reviewers","durationMs":13052,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fc98c2ae1ba121e6dceb-fb8b4435543932423ab6","project":"chromium","file":"Features/Glossary/GlossaryP2Tests.spec.ts","title":"should view workflow history on term","durationMs":12522,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fdb594bf91641dcfe81f-97569a3fda3bc1af5014","project":"chromium","file":"Pages/AppRunsHistoryLogs.spec.ts","title":"External app run logs open in the LogViewerModal","durationMs":6403,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-109f244e567c8e05b18a","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"switching to different domain triggers new feed API call","durationMs":6792,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-1112ad59f3cbc8039e17","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"entity page activity feed refetches when domain is switched","durationMs":14517,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-4957bdf2b1993328fb92","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"switching domain triggers feed API refetch on entity page","durationMs":6739,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-5fb1a3cba94644d690fe","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"selecting All Domains removes domain filter from feed API call","durationMs":6118,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-66bc79b3489af009bdb4","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"GET /tasks returns 200","durationMs":45,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-6ecf643f1978bd72b573","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"task count API returns counts for created tasks","durationMs":14,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-ccf80dfe3a0f263a9e03","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"entity page shows task cards for entity in selected domain","durationMs":4864,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fe0f7d2a273d6b11a284-db696b7c8e033f4adfa0","project":"chromium","file":"Features/Tasks/DomainFiltering.spec.ts","title":"GET /tasks/count returns task counts","durationMs":15,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-46426b05e7ad5d6e5c55","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should perform case-insensitive search","durationMs":18212,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-55947400922d9b46072b","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should check for nested glossary term search","durationMs":13696,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-5afd99790393d19e9894","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should check for glossary term search","durationMs":14474,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-749f411c6ea7761e557a","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should filter by InReview status","durationMs":9411,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-8995fbfedb67c22e25be","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should show empty state when search returns no results","durationMs":11177,"attempts":1,"retries":0,"outcome":"expected"},{"id":"fed0153cfc145e829673-c161bb5dadfd704c3625","project":"Basic","file":"Features/Glossary/GlossaryPagination.spec.ts","title":"should filter by multiple statuses","durationMs":9071,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-0da857d629e3f435c6d4","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove reviewer from glossary","durationMs":15873,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-40c7edf6cee7c9c38346","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove tags from glossary term","durationMs":17436,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-4fb8c23497a80dd2fc28","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove tags from glossary","durationMs":13775,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-753d73bb076239505f28","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove reviewer from glossary term","durationMs":16902,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-9679675e187bc293844e","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove owner from glossary term","durationMs":18192,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ff7bd61b9b375efcce56-ace8963a89d7b007752c","project":"chromium","file":"Features/Glossary/GlossaryRemoveOperations.spec.ts","title":"should add and remove owner from glossary","durationMs":16267,"attempts":1,"retries":0,"outcome":"expected"},{"id":"ffa6959dc235a6a5b1d7-28b5728ddddb5976c831","project":"data-insight-application","file":"dataInsightApp.ts","title":"Run Data Insight application and wait until success","durationMs":51225,"attempts":2,"retries":0,"outcome":"expected"}]} diff --git a/.github/scripts/build_playwright_shards.py b/.github/scripts/build_playwright_shards.py index 880ab5c8463a..06865999cb3c 100755 --- a/.github/scripts/build_playwright_shards.py +++ b/.github/scripts/build_playwright_shards.py @@ -94,6 +94,9 @@ # suite. 30 s preserves a reasonable margin so the first plan after re-enable # does not silently over-pack the shard. FALLBACK_TEST_MS = 30_000 +CHECKED_IN_TIMING_BASELINE = ( + Path(__file__).resolve().parents[1] / "playwright/timing-baseline.json" +) AUDITED_PARALLEL_SUITES = { ("Features/AdvancedSearch.spec.ts", "Advanced Search"), # Six long-running tests (each 5-10 min per test.setTimeout) inside one @@ -364,6 +367,22 @@ def load_history( return weights, identity_weights +def load_history_with_baseline( + paths: list[Path], baseline: Path = CHECKED_IN_TIMING_BASELINE +) -> tuple[dict[str, int], dict[tuple[str, str], int]]: + """Use seeded timings only when downloaded history has no matching evidence.""" + resolved_baseline = baseline.resolve() + weights, identity_weights = load_history( + [path for path in paths if path.resolve() != resolved_baseline] + ) + baseline_weights, baseline_identity_weights = load_history([baseline]) + for test_id, weight in baseline_weights.items(): + weights.setdefault(test_id, weight) + for identity, weight in baseline_identity_weights.items(): + identity_weights.setdefault(identity, weight) + return weights, identity_weights + + def apply_history_weights( units: list[Unit], test_weights: dict[str, int], @@ -663,46 +682,11 @@ def write_plan( } -# The workflow passes one `--history` per downloaded full-run artifact and only -# falls back to the checked-in baseline when *no* artifact could be downloaded -# (see the `history_args` block in playwright-e2e-reusable.yml). A newly added -# spec file exists in the baseline -- its author seeds the durations there, as -# the stale-baseline gate below instructs -- but in no artifact yet, so a single -# successful download silently dropped those seeded timings and the gate fired -# on a file that *does* have history. Fold the baseline in at the lowest -# precedence instead: an artifact weight always wins where one exists, and the -# baseline only backfills tests no artifact has ever observed. -CHECKED_IN_BASELINE = Path(".github/playwright/timing-baseline.json") - - -def backfill_from_checked_in_baseline( - paths: list[Path], - weights: dict[str, int], - identity_weights: dict[tuple[str, str], int], -) -> None: - baseline = next( - ( - candidate - for candidate in (root / CHECKED_IN_BASELINE for root in SPEC_ROOT_CANDIDATES) - if candidate.is_file() - ), - None, - ) - if baseline is None or any(path.resolve() == baseline.resolve() for path in paths): - return - fallback_weights, fallback_identity = load_history([baseline]) - for test_id, weight in fallback_weights.items(): - weights.setdefault(test_id, weight) - for identity, weight in fallback_identity.items(): - identity_weights.setdefault(identity, weight) - - def main() -> None: args = parse_args() report = json.loads(args.test_list.read_text(encoding="utf-8")) selection = json.loads(args.selection.read_text(encoding="utf-8")) - test_weights, identity_weights = load_history(args.history) - backfill_from_checked_in_baseline(args.history, test_weights, identity_weights) + test_weights, identity_weights = load_history_with_baseline(args.history) discovered_units = discover_units(report) unmatched_selectors = [ selector["spec"] diff --git a/.github/scripts/tests/test_playwright_ci_planning.py b/.github/scripts/tests/test_playwright_ci_planning.py index ef92992197dc..4573ea972780 100644 --- a/.github/scripts/tests/test_playwright_ci_planning.py +++ b/.github/scripts/tests/test_playwright_ci_planning.py @@ -193,14 +193,66 @@ def test_history_uses_p75_and_leaf_identity_fallback(tmp_path): assert identity_weights[("Features/Ingestion.spec.ts", "runs ingestion")] == 250 +def test_checked_in_baseline_augments_downloaded_history(tmp_path): + planner = load_script("build_playwright_shards") + downloaded = tmp_path / "downloaded.json" + baseline = tmp_path / "timing-baseline.json" + downloaded.write_text( + json.dumps( + { + "mode": "full", + "tests": [ + { + "id": "existing-test", + "file": "Features/Existing.spec.ts", + "title": "existing test", + "durationMs": 100, + } + ], + } + ) + ) + baseline.write_text( + json.dumps( + { + "mode": "full", + "tests": [ + { + "id": "existing-test", + "file": "Features/Existing.spec.ts", + "title": "existing test", + "durationMs": 900, + }, + { + "id": "new-test", + "file": "Features/New.spec.ts", + "title": "new test", + "durationMs": 200, + } + ], + } + ) + ) + + weights, identity_weights = planner.load_history_with_baseline( + [downloaded], baseline + ) + + assert weights == {"existing-test": 100, "new-test": 200} + assert identity_weights[("Features/Existing.spec.ts", "existing test")] == 100 + assert identity_weights[("Features/New.spec.ts", "new test")] == 200 + assert planner.load_history_with_baseline([downloaded, baseline], baseline) == ( + weights, + identity_weights, + ) + + def test_versioned_baseline_fills_gaps_without_overriding_downloaded_history( - tmp_path, monkeypatch + tmp_path, ): planner = load_script("build_playwright_shards") history = tmp_path / "history.json" - baseline = tmp_path / planner.CHECKED_IN_BASELINE - baseline.parent.mkdir(parents=True) - monkeypatch.setattr(planner, "SPEC_ROOT_CANDIDATES", (tmp_path,)) + baseline = tmp_path / "timing-baseline.json" history.write_text( json.dumps( { @@ -238,9 +290,8 @@ def test_versioned_baseline_fills_gaps_without_overriding_downloaded_history( ) ) - weights, identity_weights = planner.load_history([history]) - planner.backfill_from_checked_in_baseline( - [history], weights, identity_weights + weights, identity_weights = planner.load_history_with_baseline( + [history], baseline ) assert weights == {"existing-test": 200, "new-test": 700} diff --git a/bootstrap/sql/migrations/native/2.1.0/mysql/postDataMigrationSQLScript.sql b/bootstrap/sql/migrations/native/2.1.0/mysql/postDataMigrationSQLScript.sql index 19e1483f4afc..c3f441c1d3ab 100644 --- a/bootstrap/sql/migrations/native/2.1.0/mysql/postDataMigrationSQLScript.sql +++ b/bootstrap/sql/migrations/native/2.1.0/mysql/postDataMigrationSQLScript.sql @@ -27,6 +27,14 @@ ON DUPLICATE KEY UPDATE updatedAt = VALUES(updatedAt), latestRecordId = VALUES(latestRecordId); +-- Existing metrics predate the approval workflow and must remain usable. Explicit +-- workflow statuses are preserved, and this update is idempotent. +UPDATE metric_entity +SET json = JSON_SET(json, '$.entityStatus', 'Approved') +WHERE JSON_EXTRACT(json, '$.entityStatus') IS NULL + OR JSON_TYPE(JSON_EXTRACT(json, '$.entityStatus')) = 'NULL' + OR JSON_UNQUOTE(JSON_EXTRACT(json, '$.entityStatus')) = 'Unprocessed'; + -- Invalidate pre-2.1 projection success records. RDF status remains REBUILDING until a new -- RdfIndexApp run succeeds, and the applications page exposes that Search indexing must be run. DELETE FROM apps_extension_time_series diff --git a/bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql b/bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql index 18f12401b2c9..bb64eabbb1ed 100644 --- a/bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql +++ b/bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql @@ -3,7 +3,20 @@ -- UNIQUE (id, usageDate), which is unusable for that predicate, so every run full-scans -- the table once per subquery. A composite (entityType, usageDate) index turns the -- percentile subqueries into range scans. -CREATE INDEX idx_entity_usage_entitytype_usagedate ON entity_usage (entityType, usageDate); +SET @entity_usage_percentile_index_ddl = ( + SELECT IF( + COUNT(*) = 0, + 'CREATE INDEX idx_entity_usage_entitytype_usagedate ON entity_usage (entityType, usageDate)', + 'SELECT 1' + ) + FROM information_schema.statistics + WHERE table_schema = DATABASE() + AND table_name = 'entity_usage' + AND index_name = 'idx_entity_usage_entitytype_usagedate' +); +PREPARE entity_usage_percentile_index_stmt FROM @entity_usage_percentile_index_ddl; +EXECUTE entity_usage_percentile_index_stmt; +DEALLOCATE PREPARE entity_usage_percentile_index_stmt; -- Incident Manager grouped incidents - OpenMetadata 2.1.0 -- Index the stateId partition used by the incident grouping endpoint (/testCaseIncidentStatus/incidentGroups) @@ -42,6 +55,26 @@ CREATE TABLE IF NOT EXISTS test_case_incident ( INDEX idx_tci_updated (updatedAt) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +-- Metric hierarchy is stored as CONTAINS rows in entity_relationship. Metric Group +-- membership is stored as HAS relationships so deleting a group leaves metrics intact. +CREATE TABLE IF NOT EXISTS metric_group_entity ( + id VARCHAR(36) GENERATED ALWAYS AS (json_unquote(json_extract(`json`, '$.id'))) STORED NOT NULL, + json JSON NOT NULL, + updatedAt BIGINT UNSIGNED GENERATED ALWAYS AS (json_unquote(json_extract(`json`, '$.updatedAt'))) VIRTUAL NOT NULL, + updatedBy VARCHAR(256) GENERATED ALWAYS AS (json_unquote(json_extract(`json`, '$.updatedBy'))) VIRTUAL NOT NULL, + deleted TINYINT(1) GENERATED ALWAYS AS (json_extract(`json`, '$.deleted')) VIRTUAL, + fqnHash VARCHAR(768) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL, + name VARCHAR(256) GENERATED ALWAYS AS (json_unquote(json_extract(`json`, '$.name'))) VIRTUAL NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY metric_group_entity_fqn_hash (fqnHash), + KEY metric_group_entity_name_index (name), + KEY idx_metric_group_entity_deleted_name_id (deleted, name, id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- A Metric can belong to only one Metric Group. The generated key is NULL for every other +-- relationship shape, so the unique index constrains only metricGroup --HAS--> metric rows. +-- Guard both operations because MySQL 8.0 versions do not consistently support IF NOT EXISTS +-- for ADD COLUMN and ADD INDEX. -- Ontology Studio: governed relationship types, OWL annex, drafts, and edit locks. CREATE TABLE IF NOT EXISTS relationship_type_entity ( id varchar(36) GENERATED ALWAYS AS (json_unquote(json_extract(json, '$.id'))) STORED NOT NULL, @@ -240,6 +273,41 @@ PREPARE drop_conversation_activity_timestamp_stmt FROM @drop_conversation_activity_timestamp_ddl; EXECUTE drop_conversation_activity_timestamp_stmt; DEALLOCATE PREPARE drop_conversation_activity_timestamp_stmt; + +SET @metric_group_membership_column_ddl = ( + SELECT IF( + EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = 'entity_relationship' + AND column_name = 'metricGroupMetricId' + ), + 'SELECT 1', + 'ALTER TABLE entity_relationship ADD COLUMN metricGroupMetricId VARCHAR(36) GENERATED ALWAYS AS (CASE WHEN fromEntity = ''metricGroup'' AND toEntity = ''metric'' AND relation = 10 THEN toId ELSE NULL END) STORED' + ) +); +PREPARE metric_group_membership_column_stmt FROM @metric_group_membership_column_ddl; +EXECUTE metric_group_membership_column_stmt; +DEALLOCATE PREPARE metric_group_membership_column_stmt; + +SET @metric_group_membership_index_ddl = ( + SELECT IF( + EXISTS ( + SELECT 1 + FROM information_schema.statistics + WHERE table_schema = DATABASE() + AND table_name = 'entity_relationship' + AND index_name = 'uq_metric_group_single_membership' + ), + 'SELECT 1', + 'ALTER TABLE entity_relationship ADD UNIQUE INDEX uq_metric_group_single_membership (metricGroupMetricId)' + ) +); +PREPARE metric_group_membership_index_stmt FROM @metric_group_membership_index_ddl; +EXECUTE metric_group_membership_index_stmt; +DEALLOCATE PREPARE metric_group_membership_index_stmt; + -- Pipeline-backed lineage is the only relationship lookup whose selective identifier lives in JSON. -- Pairing it with relation serves every pipeline lineage path without widening the generic table schema. CREATE INDEX idx_entity_relationship_pipeline_relation diff --git a/bootstrap/sql/migrations/native/2.1.0/postgres/postDataMigrationSQLScript.sql b/bootstrap/sql/migrations/native/2.1.0/postgres/postDataMigrationSQLScript.sql index 307a46fa68b1..900c839b29cd 100644 --- a/bootstrap/sql/migrations/native/2.1.0/postgres/postDataMigrationSQLScript.sql +++ b/bootstrap/sql/migrations/native/2.1.0/postgres/postDataMigrationSQLScript.sql @@ -27,6 +27,13 @@ ON CONFLICT (stateId) DO UPDATE SET updatedAt = EXCLUDED.updatedAt, latestRecordId = EXCLUDED.latestRecordId; +-- Existing metrics predate the approval workflow and must remain usable. Explicit +-- workflow statuses are preserved, and this update is idempotent. +UPDATE metric_entity +SET json = jsonb_set(json::jsonb, '{entityStatus}', '"Approved"'::jsonb) +WHERE json->>'entityStatus' IS NULL + OR json->>'entityStatus' = 'Unprocessed'; + -- Invalidate pre-2.1 projection success records. RDF status remains REBUILDING until a new -- RdfIndexApp run succeeds, and the applications page exposes that Search indexing must be run. DELETE FROM apps_extension_time_series diff --git a/bootstrap/sql/migrations/native/2.1.0/postgres/schemaChanges.sql b/bootstrap/sql/migrations/native/2.1.0/postgres/schemaChanges.sql index 6591c9edc0d8..de82a7578af2 100644 --- a/bootstrap/sql/migrations/native/2.1.0/postgres/schemaChanges.sql +++ b/bootstrap/sql/migrations/native/2.1.0/postgres/schemaChanges.sql @@ -61,6 +61,28 @@ CREATE INDEX IF NOT EXISTS idx_tci_fqn ON test_case_incident (entityFQNHash); CREATE INDEX IF NOT EXISTS idx_tci_assignee ON test_case_incident (assignee, testCaseResolutionStatusType); CREATE INDEX IF NOT EXISTS idx_tci_updated ON test_case_incident (updatedAt); +-- Metric hierarchy is stored as CONTAINS rows in entity_relationship. Metric Group +-- membership is stored as HAS relationships so deleting a group leaves metrics intact. +CREATE TABLE IF NOT EXISTS metric_group_entity ( + id VARCHAR(36) GENERATED ALWAYS AS (json ->> 'id') STORED NOT NULL, + json JSONB NOT NULL, + updatedAt BIGINT GENERATED ALWAYS AS ((json ->> 'updatedAt')::bigint) STORED NOT NULL, + updatedBy VARCHAR(256) GENERATED ALWAYS AS (json ->> 'updatedBy') STORED NOT NULL, + deleted BOOLEAN GENERATED ALWAYS AS ((json ->> 'deleted')::boolean) STORED, + fqnHash VARCHAR(768) DEFAULT NULL, + name VARCHAR(256) GENERATED ALWAYS AS (json ->> 'name') STORED NOT NULL, + PRIMARY KEY (id), + UNIQUE (fqnHash) +); + +CREATE INDEX IF NOT EXISTS metric_group_entity_name_index ON metric_group_entity (name); +CREATE INDEX IF NOT EXISTS idx_metric_group_entity_deleted_name_id ON metric_group_entity (deleted, name, id); + +-- A Metric can belong to only one Metric Group while every other HAS relationship remains +-- unconstrained by this partial index. +CREATE UNIQUE INDEX IF NOT EXISTS uq_metric_group_single_membership + ON entity_relationship (toId) + WHERE fromEntity = 'metricGroup' AND toEntity = 'metric' AND relation = 10; -- Ontology Studio: governed relationship types, OWL annex, drafts, and edit locks. CREATE TABLE IF NOT EXISTS relationship_type_entity ( id VARCHAR(36) GENERATED ALWAYS AS (json ->> 'id') STORED NOT NULL, @@ -255,6 +277,7 @@ CREATE INDEX IF NOT EXISTS idx_conversation_domain_lookup ON conversation_domain (domainId, conversationId); ALTER TABLE conversation_entity DROP COLUMN IF EXISTS activityTimestamp; + -- Pipeline-backed lineage is the only relationship lookup whose selective identifier lives in JSON. -- The partial index avoids write amplification for relationships that have no pipeline metadata. CREATE INDEX IF NOT EXISTS idx_entity_relationship_pipeline_relation diff --git a/docs/generated/api-reference.md b/docs/generated/api-reference.md index 71264861e486..4d72cdc74655 100644 --- a/docs/generated/api-reference.md +++ b/docs/generated/api-reference.md @@ -13,7 +13,7 @@ hand-edit; run `make generate-api-reference` (or `make generate-reference-docs`) - Source is the annotations, **not** `openapi.yml` (a config stub with no endpoints; the full spec is assembled at runtime by Dropwizard). -**1862 endpoints** across 75 resource packages · 1852 carry a summary. +**1882 endpoints** across 75 resource packages · 1872 carry a summary. ## (root) @@ -1242,6 +1242,20 @@ hand-edit; run `make generate-api-reference` (or `make generate-reference-docs`) | Method | Path | Purpose | |---|---|---| +| `GET` | `/v1/metricGroups` | List metric groups | +| `POST` | `/v1/metricGroups` | Create a metric group | +| `PUT` | `/v1/metricGroups` | Create or update a metric group | +| `DELETE` | `/v1/metricGroups/name/{fqn}` | Delete a metric group by fully qualified name | +| `GET` | `/v1/metricGroups/name/{fqn}` | Get a metric group by fully qualified name | +| `PUT` | `/v1/metricGroups/restore` | Restore a soft deleted metric group | +| `DELETE` | `/v1/metricGroups/{id}` | Delete a metric group by Id | +| `GET` | `/v1/metricGroups/{id}` | Get a metric group by Id | +| `PATCH` | `/v1/metricGroups/{id}` | Update a metric group | +| `GET` | `/v1/metricGroups/{id}/metrics` | List Metrics in a Metric Group | +| `GET` | `/v1/metricGroups/{id}/versions` | List metric group versions | +| `GET` | `/v1/metricGroups/{id}/versions/{version}` | Get a version of the metric group | +| `PUT` | `/v1/metricGroups/{name}/metrics/add` | Add metrics to a group | +| `PUT` | `/v1/metricGroups/{name}/metrics/remove` | Remove metrics from a group | | `GET` | `/v1/metrics` | List metrics | | `POST` | `/v1/metrics` | Create a Metric | | `PUT` | `/v1/metrics` | Create or update a metric | @@ -1249,6 +1263,7 @@ hand-edit; run `make generate-api-reference` (or `make generate-reference-docs`) | `PUT` | `/v1/metrics/bulk` | Bulk create or update metrics | | `GET` | `/v1/metrics/customUnits` | Get list of custom units of measurement | | `GET` | `/v1/metrics/documentation/csv` | Get CSV documentation for metric import/export | +| `GET` | `/v1/metrics/hierarchy` | List top-level Metric hierarchy entries | | `DELETE` | `/v1/metrics/name/{fqn}` | Delete a Metric by fully qualified name | | `GET` | `/v1/metrics/name/{fqn}` | Get a Metric by fully qualified name. | | `PATCH` | `/v1/metrics/name/{fqn}` | Update a Metric using name. | @@ -1260,11 +1275,16 @@ hand-edit; run `make generate-api-reference` (or `make generate-reference-docs`) | `DELETE` | `/v1/metrics/{id}` | Delete a Metric by id | | `GET` | `/v1/metrics/{id}` | Get a metric by Id | | `PATCH` | `/v1/metrics/{id}` | Update a Metric | +| `GET` | `/v1/metrics/{id}/assets` | List a metric's linked assets with their lineage direction | | `PUT` | `/v1/metrics/{id}/followers` | Add a follower | | `DELETE` | `/v1/metrics/{id}/followers/{userId}` | Remove a follower | +| `GET` | `/v1/metrics/{id}/hierarchy` | Get the hierarchy context for one Metric | +| `GET` | `/v1/metrics/{id}/observability` | Get a metric's health rollup | | `GET` | `/v1/metrics/{id}/versions` | List Metric versions | | `GET` | `/v1/metrics/{id}/versions/{version}` | Get a version of the Metric | | `PUT` | `/v1/metrics/{id}/vote` | Update Vote for a Metric | +| `PUT` | `/v1/metrics/{name}/assets/add` | Link data assets to a metric | +| `PUT` | `/v1/metrics/{name}/assets/remove` | Unlink data assets from a metric | ## mlmodels diff --git a/docs/generated/entity-index.md b/docs/generated/entity-index.md index 87943e29eebf..46a04bf4c5ec 100644 --- a/docs/generated/entity-index.md +++ b/docs/generated/entity-index.md @@ -14,7 +14,7 @@ hand-edit; run `make generate-entity-index` (or `make generate-reference-docs`). - **REST resource** is joined from `extends EntityResource`; `—` means no dedicated `EntityResource` was found (the entity may be exposed via a shared or non-`EntityResource` route). -**86 entities** · 61 with a dedicated `EntityResource`. +**87 entities** · 62 with a dedicated `EntityResource`. ## entity/(root) @@ -92,6 +92,7 @@ hand-edit; run `make generate-entity-index` (or `make generate-reference-docs`). | Glossary | `openmetadata-spec/src/main/resources/json/schema/entity/data/glossary.json` | `org.openmetadata.schema.entity.data.Glossary` | `metadata.generated.schema.entity.data.glossary` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/glossary.ts` | `org.openmetadata.service.resources.glossary.GlossaryResource` | | GlossaryTerm | `openmetadata-spec/src/main/resources/json/schema/entity/data/glossaryTerm.json` | `org.openmetadata.schema.entity.data.GlossaryTerm` | `metadata.generated.schema.entity.data.glossaryTerm` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/glossaryTerm.ts` | `org.openmetadata.service.resources.glossary.GlossaryTermResource` | | Metric | `openmetadata-spec/src/main/resources/json/schema/entity/data/metric.json` | `org.openmetadata.schema.entity.data.Metric` | `metadata.generated.schema.entity.data.metric` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/metric.ts` | `org.openmetadata.service.resources.metrics.MetricResource` | +| MetricGroup | `openmetadata-spec/src/main/resources/json/schema/entity/data/metricGroup.json` | `org.openmetadata.schema.entity.data.MetricGroup` | `metadata.generated.schema.entity.data.metricGroup` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/metricGroup.ts` | `org.openmetadata.service.resources.metrics.MetricGroupResource` | | MlModel | `openmetadata-spec/src/main/resources/json/schema/entity/data/mlmodel.json` | `org.openmetadata.schema.entity.data.MlModel` | `metadata.generated.schema.entity.data.mlmodel` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/mlmodel.ts` | `org.openmetadata.service.resources.mlmodels.MlModelResource` | | OntologyAxiom | `openmetadata-spec/src/main/resources/json/schema/entity/data/ontologyAxiom.json` | `org.openmetadata.schema.entity.data.OntologyAxiom` | `metadata.generated.schema.entity.data.ontologyAxiom` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/ontologyAxiom.ts` | `org.openmetadata.service.resources.ontology.OntologyAxiomResource` | | OntologyChangeSet | `openmetadata-spec/src/main/resources/json/schema/entity/data/ontologyChangeSet.json` | `org.openmetadata.schema.entity.data.OntologyChangeSet` | `metadata.generated.schema.entity.data.ontologyChangeSet` | `openmetadata-ui/src/main/resources/ui/src/generated/entity/data/ontologyChangeSet.ts` | `org.openmetadata.service.resources.ontology.OntologyChangeSetResource` | diff --git a/ingestion/src/metadata/ingestion/source/database/snowflake/metadata.py b/ingestion/src/metadata/ingestion/source/database/snowflake/metadata.py index bdf144bf2fe9..c1e20215a6b4 100644 --- a/ingestion/src/metadata/ingestion/source/database/snowflake/metadata.py +++ b/ingestion/src/metadata/ingestion/source/database/snowflake/metadata.py @@ -59,13 +59,11 @@ EntityName, SourceUrl, ) -from metadata.generated.schema.type.entityReference import EntityReference from metadata.generated.schema.type.entityReferenceList import EntityReferenceList from metadata.generated.schema.type.tagLabel import TagLabel from metadata.ingestion.api.delete import delete_entity_by_name from metadata.ingestion.api.models import Either from metadata.ingestion.api.steps import InvalidSourceException -from metadata.ingestion.models.barrier import Barrier from metadata.ingestion.models.ometa_classification import OMetaTagAndClassification from metadata.ingestion.ometa.ometa_api import OpenMetadata from metadata.ingestion.source.database.column_type_parser import create_sqlalchemy_type @@ -1190,14 +1188,6 @@ def _semantic_rows(self, catalog_view: str, schema: str, view: str) -> List[tupl ) return self._execute_semantic_query(query) - def _semantic_view_reference(self, database: str, schema: str, view: str) -> Optional[EntityReference]: # noqa: UP045 - view_fqn = fqn._build(self.context.get().database_service, database, schema, view) # pyright: ignore[reportAttributeAccessIssue] - entity = self.metadata.get_by_name(entity=Table, fqn=view_fqn) - reference = None - if entity is not None: - reference = EntityReference(id=entity.id.root, type="table") # pyright: ignore[reportCallIssue] - return reference - def yield_table_metrics( self, table_name_and_type: Tuple[str, TableType], # noqa: UP006 @@ -1220,14 +1210,6 @@ def yield_table_metrics( ) if not metric_rows: return - # This view's own CreateTableRequest is still in the sink's bulk buffer - # (Metric requests are written immediately, Table requests batch), so - # without a flush the lookup below 404s on every first run and the - # metrics lose their assets[] back-reference. Gated on metric_rows: the - # stage runs for every table, and flushing per table would negate the - # bulk sink for every connector. - yield Either(right=Barrier(reason=f"semantic_view_metrics:{schema}.{view}")) # pyright: ignore[reportCallIssue] - view_ref = self._semantic_view_reference(database, schema, view) for metric_row in metric_rows: yield Either( # pyright: ignore[reportCallIssue] right=build_metric_request( @@ -1238,7 +1220,6 @@ def yield_table_metrics( metric_row, dimension_rows, fact_rows, - view_ref, ) ) except Exception as exc: # pylint: disable=broad-except diff --git a/ingestion/src/metadata/ingestion/source/database/snowflake/semantic_view_metrics.py b/ingestion/src/metadata/ingestion/source/database/snowflake/semantic_view_metrics.py index e23ef6d2c632..a6e5d63fa576 100644 --- a/ingestion/src/metadata/ingestion/source/database/snowflake/semantic_view_metrics.py +++ b/ingestion/src/metadata/ingestion/source/database/snowflake/semantic_view_metrics.py @@ -14,9 +14,10 @@ A Snowflake semantic view's METRICS are aggregations (``SUM(...)``, ``COUNT(...)``) over the view's FACTS/DIMENSIONS. Each becomes a first-class OpenMetadata ``Metric`` -carrying its expression, inferred type, the view's dimensions/facts, and an -``assets`` link back to the semantic-view table. Metric names are fully qualified -because the ``Metric`` namespace is global (FQN == name). +carrying its expression, inferred type, and the view's dimensions/facts. The +semantic-view lineage stage links the view to the metric after both entities exist. +Metric names are fully qualified because the ``Metric`` namespace is global +(FQN == name). """ import hashlib @@ -32,8 +33,6 @@ Type, ) from metadata.generated.schema.type.basic import EntityName -from metadata.generated.schema.type.entityReference import EntityReference -from metadata.generated.schema.type.entityReferenceList import EntityReferenceList # Column layout of INFORMATION_SCHEMA.SEMANTIC_{DIMENSIONS,FACTS,METRICS}: # (TABLE_NAME, NAME, DATA_TYPE, EXPRESSION, COMMENT, SYNONYMS) @@ -192,7 +191,6 @@ def build_metric_request( metric_row, dimension_rows: List[tuple], # noqa: UP006 fact_rows: List[tuple], # noqa: UP006 - view_ref: Optional[EntityReference], # noqa: UP045 ) -> CreateMetricRequest: """Assemble a CreateMetricRequest for a single Snowflake metric row.""" metric = metric_row[SEMANTIC_NAME_IDX] @@ -201,7 +199,6 @@ def build_metric_request( dimensions = [_dimension(row) for row in dimension_rows] or None measures = [_measure(row) for row in fact_rows] or None metric_expression = MetricExpression(language=Language.SQL, code=expression) if expression else None - assets = EntityReferenceList(root=[view_ref]) if view_ref is not None else None return CreateMetricRequest( # pyright: ignore[reportCallIssue] name=EntityName(build_metric_name(service, database, schema, view, table, metric)), displayName=metric, @@ -210,5 +207,4 @@ def build_metric_request( metricExpression=metric_expression, dimensions=dimensions, measures=measures, - assets=assets, ) diff --git a/ingestion/tests/unit/topology/database/test_snowflake_semantic_view_metrics.py b/ingestion/tests/unit/topology/database/test_snowflake_semantic_view_metrics.py index 6fdfa7f4d0cc..b09b53f6bb50 100644 --- a/ingestion/tests/unit/topology/database/test_snowflake_semantic_view_metrics.py +++ b/ingestion/tests/unit/topology/database/test_snowflake_semantic_view_metrics.py @@ -19,8 +19,6 @@ from metadata.generated.schema.entity.data.metric import Language, MetricType, Type from metadata.generated.schema.entity.data.table import TableType from metadata.generated.schema.type.basic import Uuid -from metadata.generated.schema.type.entityReference import EntityReference -from metadata.ingestion.models.barrier import Barrier from metadata.ingestion.source.database.common_db_source import CommonDbSourceService from metadata.ingestion.source.database.snowflake.semantic_view_metrics import ( SERVICE_PREFIX_MAX_LEN, @@ -128,7 +126,6 @@ def test_metric_children_are_qualified_by_logical_table(): metric_row=("ORDERS", "TOTAL", "NUMBER", "SUM(orders.amount)", None, None), dimension_rows=[orders_status, returns_status], fact_rows=[orders_amount, returns_amount], - view_ref=None, ) assert [d.name for d in request.dimensions] == ["ORDERS.STATUS", "RETURNS.STATUS"] @@ -139,9 +136,7 @@ def test_metric_child_names_preserve_dots(): """The server quotes dotted child names when appending them to the metric FQN.""" row = ('"my.table"', '"my.dim"', "VARCHAR", "t.c", None, None) - request = build_metric_request( - "svc", "DB", "S", "V", metric_row=ORDER_COUNT, dimension_rows=[row], fact_rows=[], view_ref=None - ) + request = build_metric_request("svc", "DB", "S", "V", metric_row=ORDER_COUNT, dimension_rows=[row], fact_rows=[]) assert request.dimensions[0].name == "my.table.my.dim" @@ -186,7 +181,6 @@ def test_infer_metric_type_by_prefix(): def test_build_metric_request_maps_all_fields(): - view_ref = EntityReference(id="12345678-1234-1234-1234-123456789012", type="table") request = build_metric_request( "snowflake_svc", "TEST_DB", @@ -195,7 +189,6 @@ def test_build_metric_request_maps_all_fields(): metric_row=TOTAL_REVENUE, dimension_rows=[DIM_REGION], fact_rows=[FACT_LINE_AMOUNT], - view_ref=view_ref, ) assert request.name.root == build_metric_name( "snowflake_svc", "TEST_DB", "SALES", "sales_analysis", "orders", "total_revenue" @@ -209,10 +202,9 @@ def test_build_metric_request_maps_all_fields(): assert request.dimensions[0].expression == "customers.c_region" assert [m.name for m in request.measures] == ["orders.line_amount"] assert request.measures[0].expression == "orders.o_totalprice" - assert request.assets.root[0].id.root == view_ref.id.root -def test_build_metric_request_without_comment_or_assets(): +def test_build_metric_request_without_optional_fields(): request = build_metric_request( "svc", "db", @@ -221,12 +213,10 @@ def test_build_metric_request_without_comment_or_assets(): metric_row=ORDER_COUNT, dimension_rows=[], fact_rows=[], - view_ref=None, ) assert request.description is None assert request.dimensions is None assert request.measures is None - assert request.assets is None assert request.metricType == MetricType.COUNT @@ -272,8 +262,7 @@ def _rows_for(query): def _metric_requests(records): - """The stage interleaves a sink-flush Barrier with the CreateMetricRequests.""" - return [r.right for r in records if r.right is not None and not isinstance(r.right, Barrier)] + return [record.right for record in records if record.right is not None] def test_yield_table_metrics_yields_one_per_metric(): @@ -286,31 +275,21 @@ def test_yield_table_metrics_yields_one_per_metric(): names = {r.displayName for r in requests} assert names == {"total_revenue", "order_count"} revenue = next(r for r in requests if r.displayName == "total_revenue") - assert str(revenue.assets.root[0].id.root) == "12345678-1234-1234-1234-123456789012" assert [d.name for d in revenue.dimensions] == ["customers.region"] assert [m.name for m in revenue.measures] == ["orders.line_amount"] -def test_yield_table_metrics_flushes_the_sink_before_resolving_the_view(): - """The semantic view's own Table is still sitting in the sink's bulk buffer - (CreateTableRequest batches at bulk_sink_batch_size; CreateMetricRequest is - written immediately), so resolving it by FQN first would 404 on every first - run and drop the assets[] back-reference. Yield a Barrier to flush, and only - then look the view up.""" +def test_yield_table_metrics_does_not_flush_or_resolve_the_view(): + """The lineage workflow links the semantic view after both entities exist, so + metric extraction must not flush the table sink or issue a per-view lookup.""" source = _make_source() source.connection.execute.side_effect = lambda clause: _rows_for(str(clause.text)) - records = source.yield_table_metrics((VIEW, TableType.SemanticView)) + records = list(source.yield_table_metrics((VIEW, TableType.SemanticView))) - first = next(records).right - assert isinstance(first, Barrier) - # the lookup must not have happened yet -- that is the whole point of the flush + assert [record.right.displayName for record in records] == ["total_revenue", "order_count"] source.metadata.get_by_name.assert_not_called() - remaining = [r.right for r in records] - source.metadata.get_by_name.assert_called_once() - assert [r.displayName for r in remaining] == ["total_revenue", "order_count"] - def test_yield_table_metrics_does_not_flush_when_the_view_has_no_metrics(): """The stage runs for *every* table, so an unconditional Barrier would flush @@ -428,9 +407,7 @@ def test_dimensions_carry_the_detail_stripped_from_columns(): """The view's columns no longer describe synonyms, so the Metric's dimensions must carry them or they are lost entirely.""" row = ("customers", "REGION", "VARCHAR", "customers.c_region", "Customer region", "geo, area") - request = build_metric_request( - "svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[row], fact_rows=[], view_ref=None - ) + request = build_metric_request("svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[row], fact_rows=[]) dimension = request.dimensions[0] @@ -443,9 +420,7 @@ def test_description_omits_the_logical_table(): """The owning logical table is already named by the expression, so repeating it in the description is noise.""" row = ("customers", "REGION", "VARCHAR", "customers.c_region", "Customer region", None) - request = build_metric_request( - "svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[row], fact_rows=[], view_ref=None - ) + request = build_metric_request("svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[row], fact_rows=[]) assert request.dimensions[0].description == "Customer region" @@ -457,9 +432,7 @@ def test_dimension_type_is_classified_from_the_data_type(): ("customers", "REGION", "VARCHAR", "customers.c_region", None, None), ("orders", "UNTYPED", None, "orders.x", None, None), ] - request = build_metric_request( - "svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=rows, fact_rows=[], view_ref=None - ) + request = build_metric_request("svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=rows, fact_rows=[]) by_name = {d.name: d.type for d in request.dimensions} @@ -476,9 +449,7 @@ def test_measure_aggregation_is_inferred_only_when_aggregated(): ("orders", "REVENUE", "NUMBER", "SUM(orders.o_totalprice)", None, None), ("orders", "LINE_AMOUNT", "NUMBER", "orders.o_totalprice", None, None), ] - request = build_metric_request( - "svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[], fact_rows=rows, view_ref=None - ) + request = build_metric_request("svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[], fact_rows=rows) by_name = {m.name: m.aggregation for m in request.measures} @@ -487,8 +458,6 @@ def test_measure_aggregation_is_inferred_only_when_aggregated(): def test_semantic_description_is_none_when_the_row_is_bare(): row = ("", "PLAIN", "VARCHAR", "t.c", None, None) - request = build_metric_request( - "svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[row], fact_rows=[], view_ref=None - ) + request = build_metric_request("svc", "db", "sc", "v", metric_row=TOTAL_REVENUE, dimension_rows=[row], fact_rows=[]) assert request.dimensions[0].description is None diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ConversationResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ConversationResourceIT.java index ef4199afd9ae..d931b692cc08 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ConversationResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ConversationResourceIT.java @@ -508,6 +508,9 @@ void testDomainChangesSynchronizeConversationVisibility(TestNamespace ns) throws patchTableDomains(table.getId(), List.of(allowedDomain)); Awaitility.await("conversation moves into the allowed domain") .atMost(Duration.ofSeconds(30)) + .ignoreExceptionsMatching( + error -> + error instanceof ApiException apiException && apiException.getStatusCode() == 404) .untilAsserted( () -> { Conversation visible = getConversation(domainClient, conversation.getId()); diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IncidentGroupsIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IncidentGroupsIT.java index 4b8be98eb571..f8157d62da3b 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IncidentGroupsIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IncidentGroupsIT.java @@ -10,8 +10,6 @@ import io.dropwizard.db.DataSourceFactory; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -73,7 +71,6 @@ import org.openmetadata.service.Entity; import org.openmetadata.service.jdbi3.CollectionDAO; import org.openmetadata.service.jdbi3.locator.ConnectionType; -import org.openmetadata.service.migration.utils.MigrationFile; import org.openmetadata.service.util.FullyQualifiedName; /** @@ -99,7 +96,7 @@ public class IncidentGroupsIT { private static final String GROUP_BY_TEST_DEFINITION = "testDefinition"; private static final String GROUP_BY_OWNER = "owner"; private static final String MAX_LIMIT = "1000"; - private static final String INCIDENT_SUMMARY_BACKFILL_PREFIX = "INSERT INTO test_case_incident"; + private static final String INCIDENT_BACKFILL_SQL = "INSERT INTO test_case_incident"; private OpenMetadataClient client; private Table tableA; @@ -987,34 +984,21 @@ private void insertStatusRecords(TestCase testCase, List sql.contains(INCIDENT_SUMMARY_BACKFILL_PREFIX)) + String migrationStatement = + MetricMigrationSqlFixture.readMigrationScripts(connectionType).postStatements().stream() + .filter(statement -> statement.contains(INCIDENT_BACKFILL_SQL)) .findFirst() .orElseThrow( - () -> - new IllegalStateException( - "Incident summary backfill is missing from " + resolvedMigrationFile)); + () -> new IllegalStateException("2.1.0 incident backfill statement not found")); try (Statement statement = connection.createStatement()) { - statement.executeUpdate(backfill); + statement.executeUpdate(migrationStatement); } } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationFixture.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationFixture.java new file mode 100644 index 000000000000..d37d2e502f99 --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationFixture.java @@ -0,0 +1,129 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.it.tests; + +import static org.openmetadata.it.tests.MetricMigrationTestSupport.INCIDENT_TABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MEMBERSHIP_INDEX; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_GROUP_DELETED_INDEX; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_GROUP_NAME_INDEX; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_GROUP_TABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_TABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.RELATIONSHIP_TABLE; + +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +record MergedMetricMigrationFixture(String suffix) { + private static final String RESOLUTION_STATUS_TABLE = "test_case_resolution_status_time_series"; + private static final String TEST_CASE_TABLE = "test_case"; + + static MergedMetricMigrationFixture create() { + String suffix = UUID.randomUUID().toString().replace("-", "").substring(0, 12); + return new MergedMetricMigrationFixture(suffix); + } + + String rewrite(String statement) { + String rewritten = statement; + for (Replacement replacement : replacements()) { + rewritten = rewritten.replace(replacement.source(), replacement.target()); + } + return rewritten; + } + + private List replacements() { + return List.of( + replacement("idx_test_case_resolution_status_state_id", "resolution_state_idx"), + replacement("idx_test_case_resolution_status_fqn_ts", "resolution_fqn_idx"), + replacement("idx_test_case_resolution_status_assignee", "resolution_assignee_idx"), + replacement("idx_test_case_id", "tc_id_idx"), + replacement("idx_tci_status_fqn", "incident_status_fqn_idx"), + replacement("idx_tci_fqn", "incident_fqn_idx"), + replacement("idx_tci_assignee", "incident_assignee_idx"), + replacement("idx_tci_updated", "incident_updated_idx"), + replacement(METRIC_GROUP_NAME_INDEX, "group_name_idx"), + replacement(METRIC_GROUP_DELETED_INDEX, "group_deleted_idx"), + replacement(MEMBERSHIP_INDEX, "membership_idx"), + new Replacement(RESOLUTION_STATUS_TABLE, resolutionStatusTable()), + new Replacement(INCIDENT_TABLE, incidentTable()), + new Replacement(METRIC_GROUP_TABLE, metricGroupTable()), + new Replacement(RELATIONSHIP_TABLE, relationshipTable()), + new Replacement(METRIC_TABLE, metricTable()), + new Replacement(TEST_CASE_TABLE, testCaseTable())); + } + + private Replacement replacement(String source, String targetRole) { + return new Replacement(source, identifier(targetRole)); + } + + String resolutionStatusTable() { + return identifier("resolution_status"); + } + + String testCaseTable() { + return identifier("test_case"); + } + + String incidentTable() { + return identifier("incident"); + } + + String metricGroupTable() { + return identifier("metric_group"); + } + + String relationshipTable() { + return identifier("relationship"); + } + + String metricTable() { + return identifier("metric"); + } + + String groupNameIndex() { + return identifier("group_name_idx"); + } + + String groupDeletedIndex() { + return identifier("group_deleted_idx"); + } + + String membershipIndex() { + return identifier("membership_idx"); + } + + List incidentIndexes() { + return List.of( + index(resolutionStatusTable(), "resolution_state_idx"), + index(resolutionStatusTable(), "resolution_fqn_idx"), + index(resolutionStatusTable(), "resolution_assignee_idx"), + index(testCaseTable(), "tc_id_idx"), + index(incidentTable(), "incident_status_fqn_idx"), + index(incidentTable(), "incident_fqn_idx"), + index(incidentTable(), "incident_assignee_idx"), + index(incidentTable(), "incident_updated_idx")); + } + + private IndexTarget index(String table, String indexRole) { + return new IndexTarget(table, identifier(indexRole)); + } + + private String identifier(String role) { + return ("it_mm_" + role + "_" + suffix).toLowerCase(Locale.ROOT); + } + + private record Replacement(String source, String target) {} +} + +record IndexTarget(String table, String index) {} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationTestSupport.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationTestSupport.java new file mode 100644 index 000000000000..aa8c2f39b44c --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MergedMetricMigrationTestSupport.java @@ -0,0 +1,475 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.it.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.metricSchemaStatements; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.Jdbi; +import org.jdbi.v3.core.statement.UnableToExecuteStatementException; +import org.openmetadata.it.tests.MetricMigrationSqlFixture.MigrationScripts; +import org.openmetadata.schema.tests.type.Severity; +import org.openmetadata.schema.tests.type.TestCaseResolutionStatusTypes; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +final class MergedMetricMigrationTestSupport { + private static final String CREATE_TABLE_IF_NOT_EXISTS = "CREATE TABLE IF NOT EXISTS"; + private static final String METRIC_GROUP = "metricGroup"; + private static final String METRIC = "metric"; + private static final int HAS_RELATION = 10; + private static final String INCIDENT_STATE_ID = "00000000-0000-0000-0000-000000000101"; + private static final String FIRST_RECORD_ID = "00000000-0000-0000-0000-000000000201"; + private static final String LATEST_RECORD_ID = "00000000-0000-0000-0000-000000000203"; + private static final String ENTITY_FQN_HASH = "merged-migration-test-fqn-hash"; + private static final String INITIAL_ASSIGNEE = "initial-reviewer"; + private static final String ASSIGNEE = "migration-reviewer"; + private static final long CREATED_AT = 100L; + private static final long UPDATED_AT = 200L; + private static final String JSON_SCHEMA = "testCaseResolutionStatus"; + + private MergedMetricMigrationTestSupport() {} + + static void runMergedUpgradeScenario( + Jdbi jdbi, MigrationScripts scripts, ConnectionType connectionType) { + MergedMetricMigrationFixture fixture = MergedMetricMigrationFixture.create(); + try { + jdbi.useHandle(handle -> runScenario(handle, fixture, scripts, connectionType)); + } finally { + dropFixture(jdbi, fixture); + } + } + + private static void runScenario( + Handle handle, + MergedMetricMigrationFixture fixture, + MigrationScripts scripts, + ConnectionType connectionType) { + createPriorShapeTables(handle, fixture, connectionType); + seedPriorRows(handle, fixture, connectionType); + executeMergedMigration(handle, fixture, scripts, connectionType); + assertIncidentOutcome(handle, fixture, connectionType); + assertMetricOutcome(handle, fixture, connectionType); + } + + private static void createPriorShapeTables( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + createResolutionStatusTable(handle, fixture, connectionType); + handle.execute("CREATE TABLE " + fixture.testCaseTable() + " (id VARCHAR(36) NOT NULL)"); + createRelationshipTable(handle, fixture, connectionType); + createMetricTable(handle, fixture, connectionType); + } + + private static void createResolutionStatusTable( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + String jsonType = connectionType == ConnectionType.MYSQL ? "JSON" : "JSONB"; + String hashType = + connectionType == ConnectionType.MYSQL + ? "VARCHAR(768) CHARACTER SET ascii COLLATE ascii_bin" + : "VARCHAR(768)"; + handle.execute( + "CREATE TABLE " + + fixture.resolutionStatusTable() + + " (id VARCHAR(36) NOT NULL, stateId VARCHAR(36) NOT NULL, " + + "assignee VARCHAR(256), timestamp BIGINT NOT NULL, " + + "testCaseResolutionStatusType VARCHAR(36) NOT NULL, jsonSchema VARCHAR(256) NOT NULL, " + + "json " + + jsonType + + " NOT NULL, entityFQNHash " + + hashType + + ")"); + } + + private static void createRelationshipTable( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + String jsonType = connectionType == ConnectionType.MYSQL ? "JSON" : "JSONB"; + handle.execute( + "CREATE TABLE " + + fixture.relationshipTable() + + " (fromId VARCHAR(36) NOT NULL, toId VARCHAR(36) NOT NULL, " + + "fromEntity VARCHAR(256) NOT NULL, toEntity VARCHAR(256) NOT NULL, " + + "relation SMALLINT NOT NULL, relationType VARCHAR(64) NOT NULL DEFAULT '', json " + + jsonType + + ", " + + "PRIMARY KEY (fromId, toId, relation, relationType))"); + } + + private static void createMetricTable( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + String jsonType = connectionType == ConnectionType.MYSQL ? "JSON" : "JSONB"; + handle.execute( + "CREATE TABLE " + + fixture.metricTable() + + " (id VARCHAR(36) PRIMARY KEY, json " + + jsonType + + " NOT NULL)"); + } + + private static void seedPriorRows( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + seedIncidentRows(handle, fixture, connectionType); + seedRelationshipRows(handle, fixture); + seedMetricRows(handle, fixture, connectionType); + } + + private static void seedIncidentRows( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + insertIncidentRow(handle, fixture, connectionType, firstIncidentRecord()); + insertIncidentRow(handle, fixture, connectionType, latestIncidentRecord()); + } + + private static IncidentRecord firstIncidentRecord() { + return new IncidentRecord( + FIRST_RECORD_ID, + INCIDENT_STATE_ID, + INITIAL_ASSIGNEE, + CREATED_AT, + TestCaseResolutionStatusTypes.New.value(), + Severity.Severity3.value(), + ENTITY_FQN_HASH); + } + + private static IncidentRecord latestIncidentRecord() { + return new IncidentRecord( + LATEST_RECORD_ID, + INCIDENT_STATE_ID, + ASSIGNEE, + UPDATED_AT, + TestCaseResolutionStatusTypes.Assigned.value(), + Severity.Severity1.value(), + ENTITY_FQN_HASH); + } + + private static void insertIncidentRow( + Handle handle, + MergedMetricMigrationFixture fixture, + ConnectionType connectionType, + IncidentRecord record) { + String jsonValue = connectionType == ConnectionType.MYSQL ? ":json" : "CAST(:json AS JSONB)"; + handle + .createUpdate( + "INSERT INTO " + + fixture.resolutionStatusTable() + + " (id, stateId, assignee, timestamp, testCaseResolutionStatusType, " + + "jsonSchema, json, entityFQNHash) VALUES " + + "(:id, :stateId, :assignee, :timestamp, :status, :jsonSchema, " + + jsonValue + + ", :entityFQNHash)") + .bind("id", record.id()) + .bind("stateId", record.stateId()) + .bind("assignee", record.assignee()) + .bind("timestamp", record.timestamp()) + .bind("status", record.status()) + .bind("jsonSchema", JSON_SCHEMA) + .bind("json", "{\"severity\":\"" + record.severity() + "\"}") + .bind("entityFQNHash", record.entityFQNHash()) + .execute(); + } + + private static void seedRelationshipRows(Handle handle, MergedMetricMigrationFixture fixture) { + insertRelationship(handle, fixture, "group-a", "metric-a"); + insertRelationship(handle, fixture, "group-b", "metric-b"); + } + + private static void insertRelationship( + Handle handle, MergedMetricMigrationFixture fixture, String groupId, String metricId) { + handle + .createUpdate( + "INSERT INTO " + + fixture.relationshipTable() + + " (fromId, toId, fromEntity, toEntity, relation) " + + "VALUES (:groupId, :metricId, :fromEntity, :toEntity, :relation)") + .bind("groupId", groupId) + .bind("metricId", metricId) + .bind("fromEntity", METRIC_GROUP) + .bind("toEntity", METRIC) + .bind("relation", HAS_RELATION) + .execute(); + } + + private static void seedMetricRows( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + insertMetric(handle, fixture, connectionType, "missing", "{\"name\":\"missing\"}"); + insertMetric( + handle, + fixture, + connectionType, + "unprocessed", + "{\"name\":\"unprocessed\",\"entityStatus\":\"Unprocessed\"}"); + insertMetric( + handle, + fixture, + connectionType, + "inReview", + "{\"name\":\"inReview\",\"entityStatus\":\"In Review\"}"); + } + + private static void insertMetric( + Handle handle, + MergedMetricMigrationFixture fixture, + ConnectionType connectionType, + String id, + String json) { + String jsonValue = connectionType == ConnectionType.MYSQL ? ":json" : "CAST(:json AS JSONB)"; + handle + .createUpdate( + "INSERT INTO " + fixture.metricTable() + " (id, json) VALUES (:id, " + jsonValue + ")") + .bind("id", id) + .bind("json", json) + .execute(); + } + + private static void executeMergedMigration( + Handle handle, + MergedMetricMigrationFixture fixture, + MigrationScripts scripts, + ConnectionType connectionType) { + executeStatements(handle, rewriteStatements(scripts.schemaStatements(), fixture)); + replaySupportedSchema(handle, fixture, scripts, connectionType); + List postStatements = rewriteStatements(scripts.postStatements(), fixture); + executeStatements(handle, postStatements); + executeStatements(handle, postStatements); + } + + private static void replaySupportedSchema( + Handle handle, + MergedMetricMigrationFixture fixture, + MigrationScripts scripts, + ConnectionType connectionType) { + List replayStatements = scripts.schemaStatements(); + if (connectionType == ConnectionType.MYSQL) { + Set metricStatements = Set.copyOf(metricSchemaStatements(scripts)); + replayStatements = + replayStatements.stream() + .filter( + statement -> + statement.contains(CREATE_TABLE_IF_NOT_EXISTS) + || metricStatements.contains(statement)) + .toList(); + } + executeStatements(handle, rewriteStatements(replayStatements, fixture)); + } + + private static List rewriteStatements( + List statements, MergedMetricMigrationFixture fixture) { + return statements.stream().map(fixture::rewrite).toList(); + } + + private static void executeStatements(Handle handle, List statements) { + statements.forEach(handle::execute); + } + + private static void assertIncidentOutcome( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + assertTrue(tableExists(handle, fixture.incidentTable(), connectionType)); + assertIncidentIndexes(handle, fixture, connectionType); + IncidentProjection projection = readIncident(handle, fixture); + assertEquals(INCIDENT_STATE_ID, projection.stateId()); + assertEquals(ENTITY_FQN_HASH, projection.entityFqnHash()); + assertEquals(TestCaseResolutionStatusTypes.Assigned.value(), projection.status()); + assertEquals(ASSIGNEE, projection.assignee()); + assertEquals(Severity.Severity1.value(), projection.severity()); + assertEquals(CREATED_AT, projection.createdAt()); + assertEquals(UPDATED_AT, projection.updatedAt()); + assertEquals(LATEST_RECORD_ID, projection.latestRecordId()); + } + + private static void assertIncidentIndexes( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + for (IndexTarget index : fixture.incidentIndexes()) { + assertTrue( + indexExists(handle, index.table(), index.index(), connectionType), + index.table() + "." + index.index()); + } + } + + private static IncidentProjection readIncident( + Handle handle, MergedMetricMigrationFixture fixture) { + List incidents = + handle + .createQuery( + "SELECT stateId, entityFQNHash, testCaseResolutionStatusType, assignee, severity, " + + "createdAt, updatedAt, latestRecordId FROM " + + fixture.incidentTable()) + .map( + (row, context) -> + new IncidentProjection( + row.getString("stateId"), + row.getString("entityFQNHash"), + row.getString("testCaseResolutionStatusType"), + row.getString("assignee"), + row.getString("severity"), + row.getLong("createdAt"), + row.getLong("updatedAt"), + row.getString("latestRecordId"))) + .list(); + assertEquals(1, incidents.size()); + return incidents.getFirst(); + } + + private static void assertMetricOutcome( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + assertTrue(tableExists(handle, fixture.metricGroupTable(), connectionType)); + assertTrue( + indexExists(handle, fixture.metricGroupTable(), fixture.groupNameIndex(), connectionType)); + assertTrue( + indexExists( + handle, fixture.metricGroupTable(), fixture.groupDeletedIndex(), connectionType)); + assertTrue( + indexExists( + handle, fixture.relationshipTable(), fixture.membershipIndex(), connectionType)); + assertSingleMembership(handle, fixture); + assertMetricStatuses(handle, fixture, connectionType); + assertMetricGroupPersistence(handle, fixture, connectionType); + } + + private static void assertSingleMembership(Handle handle, MergedMetricMigrationFixture fixture) { + assertThrows( + UnableToExecuteStatementException.class, + () -> insertRelationship(handle, fixture, "group-c", "metric-a")); + assertEquals( + 2, + handle + .createQuery("SELECT COUNT(*) FROM " + fixture.relationshipTable()) + .mapTo(Integer.class) + .one()); + } + + private static void assertMetricStatuses( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + String statusExpression = + connectionType == ConnectionType.MYSQL + ? "JSON_UNQUOTE(JSON_EXTRACT(json, '$.entityStatus'))" + : "json->>'entityStatus'"; + Map statuses = + handle + .createQuery( + "SELECT id, " + statusExpression + " AS status FROM " + fixture.metricTable()) + .map((row, context) -> Map.entry(row.getString("id"), row.getString("status"))) + .list() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + assertEquals("Approved", statuses.get("missing")); + assertEquals("Approved", statuses.get("unprocessed")); + assertEquals("In Review", statuses.get("inReview")); + } + + private static void assertMetricGroupPersistence( + Handle handle, MergedMetricMigrationFixture fixture, ConnectionType connectionType) { + insertMetricGroup(handle, fixture, connectionType, "group-id"); + assertThrows( + UnableToExecuteStatementException.class, + () -> insertMetricGroup(handle, fixture, connectionType, "duplicate-group-id")); + assertEquals( + 1, + handle + .createQuery("SELECT COUNT(*) FROM " + fixture.metricGroupTable()) + .mapTo(Integer.class) + .one()); + } + + private static void insertMetricGroup( + Handle handle, + MergedMetricMigrationFixture fixture, + ConnectionType connectionType, + String groupId) { + String jsonValue = connectionType == ConnectionType.MYSQL ? ":json" : "CAST(:json AS JSONB)"; + handle + .createUpdate( + "INSERT INTO " + + fixture.metricGroupTable() + + " (json, fqnHash) VALUES (" + + jsonValue + + ", :fqnHash)") + .bind("json", metricGroupJson(groupId)) + .bind("fqnHash", "merged-group-fqn-hash") + .execute(); + } + + private static String metricGroupJson(String groupId) { + return "{\"id\":\"" + + groupId + + "\",\"name\":\"merged-group\",\"updatedAt\":123," + + "\"updatedBy\":\"migration-test\",\"deleted\":false}"; + } + + private static boolean tableExists( + Handle handle, String tableName, ConnectionType connectionType) { + String query = + connectionType == ConnectionType.MYSQL + ? "SELECT COUNT(*) FROM information_schema.tables " + + "WHERE table_schema = DATABASE() AND table_name = :tableName" + : "SELECT COUNT(*) FROM information_schema.tables " + + "WHERE table_schema = current_schema() AND table_name = :tableName"; + return metadataCount(handle, query, tableName, null) == 1; + } + + private static boolean indexExists( + Handle handle, String tableName, String indexName, ConnectionType connectionType) { + String query = + connectionType == ConnectionType.MYSQL + ? "SELECT COUNT(DISTINCT index_name) FROM information_schema.statistics " + + "WHERE table_schema = DATABASE() AND table_name = :tableName " + + "AND index_name = :indexName" + : "SELECT COUNT(*) FROM pg_indexes WHERE schemaname = current_schema() " + + "AND tablename = :tableName AND indexname = :indexName"; + return metadataCount(handle, query, tableName, indexName) == 1; + } + + private static int metadataCount( + Handle handle, String query, String tableName, String indexName) { + var queryHandle = handle.createQuery(query).bind("tableName", tableName); + if (indexName != null) { + queryHandle.bind("indexName", indexName); + } + return queryHandle.mapTo(Integer.class).one(); + } + + private static void dropFixture(Jdbi jdbi, MergedMetricMigrationFixture fixture) { + jdbi.useHandle( + handle -> { + handle.execute("DROP TABLE IF EXISTS " + fixture.metricGroupTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.incidentTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.metricTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.relationshipTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.testCaseTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.resolutionStatusTable()); + }); + } + + private record IncidentRecord( + String id, + String stateId, + String assignee, + long timestamp, + String status, + String severity, + String entityFQNHash) {} + + private record IncidentProjection( + String stateId, + String entityFqnHash, + String status, + String assignee, + String severity, + long createdAt, + long updatedAt, + String latestRecordId) {} +} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricGroupResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricGroupResourceIT.java new file mode 100644 index 000000000000..f4bd2d4043b9 --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricGroupResourceIT.java @@ -0,0 +1,1420 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.it.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openmetadata.service.Entity.METRIC; +import static org.openmetadata.service.Entity.METRIC_GROUP; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import org.awaitility.Awaitility; +import org.jdbi.v3.core.Jdbi; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.api.parallel.Isolated; +import org.openmetadata.it.bootstrap.TestSuiteBootstrap; +import org.openmetadata.it.factories.ShortStackFactory; +import org.openmetadata.it.util.SdkClients; +import org.openmetadata.it.util.TestNamespace; +import org.openmetadata.it.util.TestNamespaceExtension; +import org.openmetadata.schema.api.data.CreateMetric; +import org.openmetadata.schema.api.data.CreateMetricGroup; +import org.openmetadata.schema.api.policies.CreatePolicy; +import org.openmetadata.schema.api.teams.CreateRole; +import org.openmetadata.schema.api.teams.CreateUser; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.entity.data.Table; +import org.openmetadata.schema.entity.policies.Policy; +import org.openmetadata.schema.entity.policies.accessControl.Rule; +import org.openmetadata.schema.entity.teams.Role; +import org.openmetadata.schema.entity.teams.User; +import org.openmetadata.schema.type.ApiStatus; +import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.schema.type.TagLabel; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.sdk.client.OpenMetadataClient; +import org.openmetadata.sdk.exceptions.InvalidRequestException; +import org.openmetadata.sdk.exceptions.OpenMetadataException; +import org.openmetadata.sdk.network.HttpMethod; +import org.openmetadata.sdk.network.RequestOptions; +import org.openmetadata.sdk.test.util.RestClient; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +/** + * Integration tests for the Metric Group container entity. + * + *

The load-bearing behaviour here is that a group organizes metrics without owning them: + * deleting a group must leave every member metric alive. That distinction is what makes membership + * a HAS relationship rather than CONTAINS, and it is the thing most likely to regress. + */ +@Execution(ExecutionMode.SAME_THREAD) +@Isolated("Rollback coverage temporarily installs entity_relationship CHECK constraints") +@ExtendWith(TestNamespaceExtension.class) +public class MetricGroupResourceIT { + private static final String ALL_RESOURCES = "All"; + private static final String GROUPS_PATH = "/v1/metricGroups"; + private static final String MYSQL_DATABASE_TYPE = "mysql"; + private static final String NON_METRIC_MEMBERSHIP_MESSAGE = + "Metric Group membership accepts Metric entities only"; + private static final String RESTRICTED_TAG_FQN = "PII.Sensitive"; + private static final ObjectMapper JSON = new ObjectMapper(); + + private MetricGroup createGroup(CreateMetricGroup create) { + return SdkClients.adminClient() + .getHttpClient() + .execute(HttpMethod.POST, GROUPS_PATH, create, MetricGroup.class); + } + + private MetricGroup createOrUpdateGroup(CreateMetricGroup create) { + return SdkClients.adminClient() + .getHttpClient() + .execute(HttpMethod.PUT, GROUPS_PATH, create, MetricGroup.class); + } + + private static MetricGroup getGroup(String name, String fields) { + return SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/name/" + name + "?fields=" + fields, + null, + MetricGroup.class); + } + + private Metric createMetric(TestNamespace ns, String name) { + return SdkClients.adminClient() + .metrics() + .create(new CreateMetric().withName(ns.prefix(name)).withDescription("Group member")); + } + + private Metric createChild(TestNamespace ns, String name, Metric parent) { + return SdkClients.adminClient() + .metrics() + .create( + new CreateMetric() + .withName(ns.prefix(name)) + .withDescription("Group member child") + .withParent(parent.getFullyQualifiedName())); + } + + private Metric createRestrictedChild(TestNamespace ns, String name, Metric parent) { + return SdkClients.adminClient() + .metrics() + .create( + new CreateMetric() + .withName(ns.prefix(name)) + .withDescription("Restricted group member child") + .withParent(parent.getFullyQualifiedName()) + .withTags(List.of(new TagLabel().withTagFQN(RESTRICTED_TAG_FQN)))); + } + + @Test + void post_metricGroupWithMembers_200(TestNamespace ns) { + Metric first = createMetric(ns, "grp_member_one"); + Metric second = createMetric(ns, "grp_member_two"); + + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("profitability")) + .withDescription("Margin, profit, and revenue-quality metrics") + .withMetrics( + List.of(first.getFullyQualifiedName(), second.getFullyQualifiedName()))); + + assertNotNull(group.getId()); + assertNull(group.getMetrics(), "Generic create responses must not embed group membership"); + + MetricGroup fetched = getGroup(group.getName(), "metricCount"); + JsonNode members = getGroupMembers(group, 10, 0); + + assertEquals(2, fetched.getMetricCount()); + assertEquals(2, members.path("paging").path("total").asInt()); + assertEquals(2, members.path("data").size()); + } + + @Test + void put_createAndUpdatePersistsMembershipAndSupportsFilteredReindexSearch(TestNamespace ns) + throws Exception { + OpenMetadataClient client = SdkClients.adminClient(); + Metric originalRoot = createMetric(ns, "put_original_root"); + Metric originalChild = createChild(ns, "put_original_child", originalRoot); + Metric replacement = createMetric(ns, "put_replacement"); + String groupName = ns.prefix("put_group"); + + MetricGroup created = + createOrUpdateGroup( + new CreateMetricGroup() + .withName(groupName) + .withDescription("Created through PUT") + .withMetrics(List.of(originalRoot.getFullyQualifiedName()))); + + assertNull(created.getMetrics()); + assertEquals(2, getGroup(groupName, "metricCount").getMetricCount()); + assertSubtreeGroup(originalRoot, originalChild, created); + awaitFilteredSearchResult(created, 2); + + MetricGroup updated = + createOrUpdateGroup( + new CreateMetricGroup() + .withName(groupName) + .withDescription("Updated through PUT") + .withMetrics(List.of(replacement.getFullyQualifiedName()))); + + assertEquals(created.getId(), updated.getId()); + assertNull(updated.getMetrics()); + assertEquals("Updated through PUT", getGroup(groupName, "metricCount").getDescription()); + assertEquals(1, getGroup(groupName, "metricCount").getMetricCount()); + assertUngroupedSubtree(originalRoot, originalChild); + assertMetricHasGroup(replacement, updated); + awaitFilteredSearchResult(updated, 1); + + String reindexResponse = client.search().reindexEntities(List.of(updated.getEntityReference())); + assertNotNull(reindexResponse); + awaitFilteredSearchResult(updated, 1); + } + + @Test + void get_listAndByIdExposeMetricGroupsThroughGenericPublicPaths(TestNamespace ns) { + Metric metric = createMetric(ns, "public_read_member"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("public_read_group")) + .withDescription("Metric Group public read coverage") + .withMetrics(List.of(metric.getFullyQualifiedName()))); + OpenMetadataClient client = SdkClients.adminClient(); + + JsonNode response = + JSON.valueToTree( + client + .getHttpClient() + .execute(HttpMethod.GET, GROUPS_PATH + "?limit=1000000", null, Object.class)); + JsonNode listed = null; + for (JsonNode candidate : response.path("data")) { + if (group.getId().toString().equals(candidate.path("id").asText())) { + listed = candidate; + break; + } + } + + assertNotNull(listed, "Plain Metric Group list must include the newly created group"); + assertEquals(group.getName(), listed.path("name").asText()); + assertTrue(listed.path("metrics").isMissingNode() || listed.path("metrics").isNull()); + assertTrue(response.path("paging").path("total").asInt() >= 1); + + MetricGroup byId = + client + .getHttpClient() + .execute(HttpMethod.GET, GROUPS_PATH + "/" + group.getId(), null, MetricGroup.class); + assertEquals(group.getId(), byId.getId()); + assertEquals(group.getName(), byId.getName()); + assertEquals(group.getDescription(), byId.getDescription()); + assertNull(byId.getMetrics(), "Generic get-by-id must not embed Metric membership"); + } + + @Test + void get_versionsListAndSpecificVersionReturnPersistedSnapshots(TestNamespace ns) { + MetricGroup created = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("public_versions_group")) + .withDescription("Initial Metric Group description")); + MetricGroup original = getGroup(created.getName(), "metricCount"); + MetricGroup requestedUpdate = + JsonUtils.deepCopy(original, MetricGroup.class) + .withDescription("Updated Metric Group description"); + + patchGroup(SdkClients.adminClient(), original.getId(), original, requestedUpdate); + + MetricGroup current = getGroup(created.getName(), "metricCount"); + assertTrue(current.getVersion() > original.getVersion()); + EntityHistory history = + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/" + created.getId() + "/versions", + null, + EntityHistory.class); + assertTrue(history.getVersions().size() >= 2); + + MetricGroup initialVersion = + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/" + created.getId() + "/versions/" + original.getVersion(), + null, + MetricGroup.class); + assertEquals(original.getVersion(), initialVersion.getVersion()); + assertEquals("Initial Metric Group description", initialVersion.getDescription()); + assertEquals(List.of(), initialVersion.getMetrics()); + } + + @Test + void delete_byNameHardDeletesGroupAndRefreshesPersistenceAndSearch(TestNamespace ns) { + RestClient rest = RestClient.admin(); + Metric metric = createMetric(ns, "delete_by_name_member"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("delete_by_name_group")) + .withMetrics(List.of(metric.getFullyQualifiedName()))); + + awaitSearchDocument( + rest, + "metric_group_search_index", + group.getId(), + document -> assertEquals(group.getId().toString(), document.path("id").asText())); + + try (Response response = + rest.rawDelete( + GROUPS_PATH + "/name/" + group.getFullyQualifiedName() + "?hardDelete=true")) { + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + } + + try (Response response = rest.rawGet(GROUPS_PATH + "/" + group.getId() + "?include=all")) { + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); + } + awaitSearchDocumentDeletion(rest, "metric_group_search_index", group.getId()); + awaitMetricSearchDocument(rest, metric.getId(), MetricGroupResourceIT::assertNoMetricGroup); + assertMetricHasNoVisibleGroup(metric); + assertHierarchyShowsStandaloneMetric(metric); + } + + @Test + void get_metricCarriesItsGroupBackReference(TestNamespace ns) { + Metric metric = createMetric(ns, "grp_backref"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("backref_group")) + .withMetrics(List.of(metric.getFullyQualifiedName()))); + + Metric withGroup = + SdkClients.adminClient().metrics().get(metric.getId().toString(), "metricGroup"); + + assertNotNull(withGroup.getMetricGroup(), "Metric should expose the group that holds it"); + assertEquals(group.getId(), withGroup.getMetricGroup().getId()); + } + + @Test + void delete_metricGroupLeavesItsMetricsAlive(TestNamespace ns) { + Metric metric = createMetric(ns, "grp_survivor"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("disposable_group")) + .withMetrics(List.of(metric.getFullyQualifiedName()))); + + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.DELETE, + GROUPS_PATH + "/" + group.getId() + "?hardDelete=true", + null, + Object.class); + + Metric survivor = + SdkClients.adminClient().metrics().get(metric.getId().toString(), "metricGroup"); + + assertNotNull(survivor, "Deleting a group must not delete the metrics it held"); + assertNull(survivor.getMetricGroup(), "The group reference should be gone once it is deleted"); + } + + @Test + void put_addAndRemoveMetrics(TestNamespace ns) { + Metric existing = createMetric(ns, "grp_existing"); + Metric added = createMetric(ns, "grp_added"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("membership_group")) + .withMetrics(List.of(existing.getFullyQualifiedName()))); + + BulkAssets request = new BulkAssets().withAssets(List.of(added.getEntityReference())); + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + group.getName() + "/metrics/add", + request, + Object.class); + + assertEquals(2, getGroup(group.getName(), "metricCount").getMetricCount()); + + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + group.getName() + "/metrics/remove", + request, + Object.class); + + assertEquals(1, getGroup(group.getName(), "metricCount").getMetricCount()); + } + + @Test + void put_metricGroupMembershipReturnsPartialFailureForNonMetricMembers(TestNamespace ns) { + MetricGroup group = createGroup(new CreateMetricGroup().withName(ns.prefix("bad_members"))); + Metric metric = createMetric(ns, "valid_member"); + Table table = ShortStackFactory.table(ns); + BulkAssets request = + new BulkAssets() + .withAssets(List.of(metric.getEntityReference(), table.getEntityReference())); + + BulkOperationResult result = + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + group.getName() + "/metrics/add", + request, + BulkOperationResult.class); + + assertEquals(ApiStatus.PARTIAL_SUCCESS, result.getStatus()); + assertEquals(2, result.getNumberOfRowsProcessed()); + assertEquals(1, result.getNumberOfRowsPassed()); + assertEquals(1, result.getNumberOfRowsFailed()); + assertEquals(NON_METRIC_MEMBERSHIP_MESSAGE, result.getFailedRequest().getFirst().getMessage()); + assertEquals(1, getGroup(group.getName(), "metricCount").getMetricCount()); + } + + @Test + void post_metricGroupRejectsNonMetricFqn(TestNamespace ns) { + Table table = ShortStackFactory.table(ns); + CreateMetricGroup create = + new CreateMetricGroup() + .withName(ns.prefix("bad_member_fqn")) + .withMetrics(List.of(table.getFullyQualifiedName())); + + OpenMetadataException exception = + assertThrows(OpenMetadataException.class, () -> createGroup(create)); + + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), exception.getStatusCode()); + } + + @Test + void groupWritesRequireEditPermissionForTheCompleteMetricSubtree(TestNamespace ns) { + Metric root = createMetric(ns, "write_auth_root"); + Metric child = createRestrictedChild(ns, "write_auth_child", root); + MetricGroup existing = + createGroup(new CreateMetricGroup().withName(ns.prefix("write_auth_existing"))); + + withRestrictedMetricEditor( + ns, + editor -> { + CreateMetricGroup post = + new CreateMetricGroup() + .withName(ns.prefix("write_auth_post")) + .withMetrics(List.of(root.getFullyQualifiedName())); + assertForbidden( + () -> + editor + .getHttpClient() + .execute(HttpMethod.POST, GROUPS_PATH, post, MetricGroup.class)); + assertGroupNotFound(post.getName()); + assertUngroupedSubtree(root, child); + + CreateMetricGroup put = + new CreateMetricGroup() + .withName(ns.prefix("write_auth_put")) + .withMetrics(List.of(root.getFullyQualifiedName())); + assertForbidden( + () -> + editor + .getHttpClient() + .execute(HttpMethod.PUT, GROUPS_PATH, put, MetricGroup.class)); + assertGroupNotFound(put.getName()); + assertUngroupedSubtree(root, child); + + assertForbidden( + () -> patchGroupMembers(editor, existing, List.of(root.getEntityReference()))); + assertEquals(0, getGroup(existing.getName(), "metricCount").getMetricCount()); + assertUngroupedSubtree(root, child); + + BulkAssets request = new BulkAssets().withAssets(List.of(root.getEntityReference())); + assertThrows( + InvalidRequestException.class, + () -> + editor + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + existing.getName() + "/metrics/add", + request, + BulkOperationResult.class)); + assertEquals(0, getGroup(existing.getName(), "metricCount").getMetricCount()); + assertUngroupedSubtree(root, child); + + BulkAssets adminAssignment = + new BulkAssets().withAssets(List.of(root.getEntityReference())); + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + existing.getName() + "/metrics/add", + adminAssignment, + BulkOperationResult.class); + MetricGroup grouped = getGroup(existing.getName(), "metricCount"); + grouped.setMetrics(getGroupMemberReferences(existing)); + MetricGroup descriptionUpdate = + JsonUtils.deepCopy(grouped, MetricGroup.class) + .withDescription("Authorized metadata-only update"); + patchGroup(editor, grouped.getId(), grouped, descriptionUpdate); + assertEquals( + descriptionUpdate.getDescription(), + getGroup(existing.getName(), "metricCount").getDescription()); + + assertForbidden(() -> patchGroupMembers(editor, existing, List.of())); + assertSubtreeGroup(root, child, existing); + }); + } + + @Test + void metricRootReassignmentRequiresEditPermissionForTheCompleteSubtree(TestNamespace ns) { + Metric root = createMetric(ns, "reassign_auth_root"); + Metric child = createRestrictedChild(ns, "reassign_auth_child", root); + MetricGroup source = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("reassign_auth_source")) + .withMetrics(List.of(root.getFullyQualifiedName()))); + MetricGroup target = + createGroup(new CreateMetricGroup().withName(ns.prefix("reassign_auth_target"))); + Metric targetParent = createMetric(ns, "reassign_auth_parent"); + MetricGroup parentGroup = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("reassign_auth_parent_group")) + .withMetrics(List.of(targetParent.getFullyQualifiedName()))); + + withRestrictedMetricEditor( + ns, + editor -> { + Metric groupUpdate = editor.metrics().get(root.getId().toString(), "metricGroup,parent"); + groupUpdate.setMetricGroup(target.getEntityReference()); + assertForbidden(() -> editor.metrics().update(root.getId().toString(), groupUpdate)); + assertSubtreeGroup(root, child, source); + assertEquals(0, getGroup(target.getName(), "metricCount").getMetricCount()); + + Metric parentUpdate = editor.metrics().get(root.getId().toString(), "metricGroup,parent"); + parentUpdate.setParent(targetParent.getEntityReference()); + assertForbidden(() -> editor.metrics().update(root.getId().toString(), parentUpdate)); + assertSubtreeGroup(root, child, source); + assertNull( + SdkClients.adminClient() + .metrics() + .get(root.getId().toString(), "parent") + .getParent()); + assertEquals(1, getGroup(parentGroup.getName(), "metricCount").getMetricCount()); + }); + } + + @Test + void metricAssignmentsRequireEditPermissionOnEveryDestination(TestNamespace ns) { + Metric root = createMetric(ns, "destination_auth_root"); + Metric child = createChild(ns, "destination_auth_child", root); + Metric restrictedParent = + SdkClients.adminClient() + .metrics() + .create( + new CreateMetric() + .withName(ns.prefix("destination_auth_parent")) + .withDescription("Restricted destination parent") + .withTags(List.of(new TagLabel().withTagFQN(RESTRICTED_TAG_FQN)))); + MetricGroup restrictedGroup = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("destination_auth_group")) + .withTags(List.of(new TagLabel().withTagFQN(RESTRICTED_TAG_FQN)))); + + withRestrictedMetricEditor( + ns, + editor -> { + Metric groupUpdate = editor.metrics().get(root.getId().toString(), "metricGroup,parent"); + groupUpdate.setMetricGroup(restrictedGroup.getEntityReference()); + assertForbidden(() -> editor.metrics().update(root.getId().toString(), groupUpdate)); + assertUngroupedSubtree(root, child); + + Metric parentUpdate = editor.metrics().get(root.getId().toString(), "metricGroup,parent"); + parentUpdate.setParent(restrictedParent.getEntityReference()); + assertForbidden(() -> editor.metrics().update(root.getId().toString(), parentUpdate)); + assertNull( + SdkClients.adminClient() + .metrics() + .get(root.getId().toString(), "parent") + .getParent()); + + BulkAssets assignment = new BulkAssets().withAssets(List.of(root.getEntityReference())); + assertForbidden( + () -> + editor + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + restrictedGroup.getName() + "/metrics/add", + assignment, + BulkOperationResult.class)); + assertUngroupedSubtree(root, child); + }); + } + + @Test + void concurrentAssignmentOfOneRootLeavesExactlyOneGroupMembership(TestNamespace ns) + throws Exception { + Metric root = createMetric(ns, "concurrent_root"); + Metric child = createChild(ns, "concurrent_child", root); + MetricGroup first = + createGroup(new CreateMetricGroup().withName(ns.prefix("concurrent_first"))); + MetricGroup second = + createGroup(new CreateMetricGroup().withName(ns.prefix("concurrent_second"))); + CountDownLatch ready = new CountDownLatch(2); + CountDownLatch start = new CountDownLatch(1); + + try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { + Future firstResult = + executor.submit(() -> assignGroupAfterStart(first, root, ready, start)); + Future secondResult = + executor.submit(() -> assignGroupAfterStart(second, root, ready, start)); + assertTrue(ready.await(10, TimeUnit.SECONDS)); + start.countDown(); + boolean firstSucceeded = firstResult.get(30, TimeUnit.SECONDS); + boolean secondSucceeded = secondResult.get(30, TimeUnit.SECONDS); + assertTrue( + firstSucceeded || secondSucceeded, "At least one concurrent assignment must succeed"); + } + + Jdbi jdbi = TestSuiteBootstrap.getJdbi(); + int firstRoot = membershipCount(jdbi, first.getId(), root.getId()); + int secondRoot = membershipCount(jdbi, second.getId(), root.getId()); + int firstChild = membershipCount(jdbi, first.getId(), child.getId()); + int secondChild = membershipCount(jdbi, second.getId(), child.getId()); + assertEquals(1, firstRoot + secondRoot); + assertEquals(1, firstChild + secondChild); + assertEquals(firstRoot, firstChild); + assertEquals(secondRoot, secondChild); + assertEquals( + 2, + getGroup(first.getName(), "metricCount").getMetricCount() + + getGroup(second.getName(), "metricCount").getMetricCount()); + } + + @Test + void get_emptyGroupReportsZeroRatherThanNull(TestNamespace ns) { + MetricGroup group = createGroup(new CreateMetricGroup().withName(ns.prefix("empty_group"))); + + MetricGroup fetched = getGroup(group.getName(), "metricCount"); + MetricGroup allFields = getGroup(group.getName(), "*"); + JsonNode members = getGroupMembers(group, 10, 0); + OpenMetadataException invalidField = + assertThrows(OpenMetadataException.class, () -> getGroup(group.getName(), "metrics")); + + assertEquals(0, fetched.getMetricCount()); + assertNull(allFields.getMetrics()); + assertEquals(0, members.path("paging").path("total").asInt()); + assertTrue(members.path("data").isEmpty()); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), invalidField.getStatusCode()); + } + + @Test + void groupAssignmentIncludesTheCompleteVariantSubtree(TestNamespace ns) { + Metric root = createMetric(ns, "subtree_root"); + Metric child = createChild(ns, "subtree_child", root); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("subtree_group")) + .withMetrics(List.of(root.getFullyQualifiedName()))); + + Metric groupedRoot = + SdkClients.adminClient().metrics().get(root.getId().toString(), "metricGroup"); + Metric groupedChild = + SdkClients.adminClient().metrics().get(child.getId().toString(), "metricGroup"); + + assertEquals(group.getId(), groupedRoot.getMetricGroup().getId()); + assertEquals(group.getId(), groupedChild.getMetricGroup().getId()); + assertEquals(2, getGroup(group.getName(), "metricCount").getMetricCount()); + } + + @Test + void list_groupMembersCanPageHierarchyRootsOnly(TestNamespace ns) { + Metric root = createMetric(ns, "page_root"); + createChild(ns, "page_child", root); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("page_group")) + .withMetrics(List.of(root.getFullyQualifiedName()))); + + JsonNode roots = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/" + group.getId() + "/metrics?rootOnly=true&limit=1&offset=0", + null, + Object.class)); + JsonNode allMembers = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/" + group.getId() + "/metrics?limit=1&offset=0", + null, + Object.class)); + + assertEquals(1, roots.get("paging").get("total").asInt()); + assertEquals(root.getId().toString(), roots.get("data").get(0).get("id").asText()); + assertEquals(2, allMembers.get("paging").get("total").asInt()); + } + + @Test + void list_groupRootsSearchesNamesAcrossEachCompleteSubtree(TestNamespace ns) { + Metric matchingRoot = createMetric(ns, "search_root_match"); + Metric matchingChild = createChild(ns, "search_nested_unique", matchingRoot); + Metric otherRoot = createMetric(ns, "search_root_other"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("search_roots_group")) + .withMetrics( + List.of( + matchingRoot.getFullyQualifiedName(), otherRoot.getFullyQualifiedName()))); + + JsonNode roots = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + + "/" + + group.getId() + + "/metrics?rootOnly=true&q=" + + matchingChild.getName() + + "&limit=1&offset=0", + null, + Object.class)); + + assertEquals(1, roots.get("paging").get("total").asInt()); + assertEquals(matchingRoot.getId().toString(), roots.get("data").get(0).get("id").asText()); + } + + @Test + void bulkReassignmentMovesTheWholeSubtreeAndRefreshesCounts(TestNamespace ns) { + Metric root = createMetric(ns, "move_root"); + Metric child = createChild(ns, "move_child", root); + MetricGroup original = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("move_original")) + .withMetrics(List.of(root.getFullyQualifiedName()))); + MetricGroup target = createGroup(new CreateMetricGroup().withName(ns.prefix("move_target"))); + BulkAssets request = new BulkAssets().withAssets(List.of(root.getEntityReference())); + + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + target.getName() + "/metrics/add", + request, + Object.class); + + Metric movedRoot = + SdkClients.adminClient().metrics().get(root.getId().toString(), "metricGroup"); + Metric movedChild = + SdkClients.adminClient().metrics().get(child.getId().toString(), "metricGroup"); + assertEquals(target.getId(), movedRoot.getMetricGroup().getId()); + assertEquals(target.getId(), movedChild.getMetricGroup().getId()); + assertEquals(0, getGroup(original.getName(), "metricCount").getMetricCount()); + assertEquals(2, getGroup(target.getName(), "metricCount").getMetricCount()); + } + + @Test + void failedMidSubtreeAssignmentRollsBackEveryMembership(TestNamespace ns) { + Metric root = createMetric(ns, "rollback_root"); + Metric child = createChild(ns, "rollback_child", root); + MetricGroup group = createGroup(new CreateMetricGroup().withName(ns.prefix("rollback_group"))); + BulkAssets request = new BulkAssets().withAssets(List.of(root.getEntityReference())); + ConnectionType connectionType = currentConnectionType(); + String suffix = UUID.randomUUID().toString().replace("-", "").substring(0, 8); + String constraint = "metric_membership_fail_" + suffix; + Jdbi jdbi = TestSuiteBootstrap.getJdbi(); + + createMembershipFailureConstraint(jdbi, constraint, group.getId(), child.getId()); + try { + assertThrows( + RuntimeException.class, + () -> + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + group.getName() + "/metrics/add", + request, + Object.class)); + } finally { + dropMembershipFailureConstraint(jdbi, connectionType, constraint); + } + + assertEquals(0, membershipCount(jdbi, group.getId(), root.getId())); + assertEquals(0, membershipCount(jdbi, group.getId(), child.getId())); + assertEquals(0, getGroup(group.getName(), "metricCount").getMetricCount()); + } + + @Test + void failedMidSubtreePatchGroupAssignmentRollsBackEveryMembership(TestNamespace ns) { + Metric root = createMetric(ns, "patch_rollback_root"); + Metric child = createChild(ns, "patch_rollback_child", root); + MetricGroup group = + createGroup(new CreateMetricGroup().withName(ns.prefix("patch_rollback_group"))); + ConnectionType connectionType = currentConnectionType(); + String suffix = UUID.randomUUID().toString().replace("-", "").substring(0, 8); + String constraint = "metric_patch_membership_fail_" + suffix; + Jdbi jdbi = TestSuiteBootstrap.getJdbi(); + Metric update = SdkClients.adminClient().metrics().get(root.getId().toString(), "metricGroup"); + update.setMetricGroup(group.getEntityReference()); + + createMembershipFailureConstraint(jdbi, constraint, group.getId(), child.getId()); + try { + assertThrows( + RuntimeException.class, + () -> SdkClients.adminClient().metrics().update(root.getId().toString(), update)); + } finally { + dropMembershipFailureConstraint(jdbi, connectionType, constraint); + } + + assertEquals(0, membershipCount(jdbi, group.getId(), root.getId())); + assertEquals(0, membershipCount(jdbi, group.getId(), child.getId())); + assertNull( + SdkClients.adminClient() + .metrics() + .get(root.getId().toString(), "metricGroup") + .getMetricGroup()); + assertNull( + SdkClients.adminClient() + .metrics() + .get(child.getId().toString(), "metricGroup") + .getMetricGroup()); + } + + @Test + void reparentingGroupedRootMovesItsSubtreeToTheParentGroup(TestNamespace ns) { + Metric movingRoot = createMetric(ns, "reparent_moving_root"); + Metric movingChild = createChild(ns, "reparent_moving_child", movingRoot); + Metric targetParent = createMetric(ns, "reparent_target_parent"); + MetricGroup originalGroup = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("reparent_original_group")) + .withMetrics(List.of(movingRoot.getFullyQualifiedName()))); + MetricGroup targetGroup = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("reparent_target_group")) + .withMetrics(List.of(targetParent.getFullyQualifiedName()))); + + Metric update = + SdkClients.adminClient().metrics().get(movingRoot.getId().toString(), "parent,metricGroup"); + update.setParent(targetParent.getEntityReference()); + SdkClients.adminClient().metrics().update(movingRoot.getId().toString(), update); + + Metric movedRoot = + SdkClients.adminClient().metrics().get(movingRoot.getId().toString(), "parent,metricGroup"); + Metric movedChild = + SdkClients.adminClient().metrics().get(movingChild.getId().toString(), "metricGroup"); + assertEquals(targetParent.getId(), movedRoot.getParent().getId()); + assertEquals(targetGroup.getId(), movedRoot.getMetricGroup().getId()); + assertEquals(targetGroup.getId(), movedChild.getMetricGroup().getId()); + assertEquals(0, getGroup(originalGroup.getName(), "metricCount").getMetricCount()); + assertEquals(3, getGroup(targetGroup.getName(), "metricCount").getMetricCount()); + } + + @Test + void hierarchySearchByNestedMetricReturnsItsGroup(TestNamespace ns) { + Metric root = createMetric(ns, "search_group_root"); + Metric child = createChild(ns, "search_group_child", root); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("search_group")) + .withMetrics(List.of(root.getFullyQualifiedName()))); + + JsonNode response = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + child.getName(), + null, + Object.class)); + + assertEquals(1, response.get("paging").get("total").asInt()); + assertEquals("metricGroup", response.get("data").get(0).get("kind").asText()); + assertEquals( + group.getId().toString(), response.get("data").get(0).get("group").get("id").asText()); + assertFalse(response.get("data").get(0).has("metric")); + } + + @Test + void hierarchyAndMembershipSearchMatchDisplayNames(TestNamespace ns) { + Metric root = + SdkClients.adminClient() + .metrics() + .create( + new CreateMetric() + .withName(ns.prefix("display_root")) + .withDisplayName("Friendly Revenue Root") + .withDescription("Root")); + Metric child = + SdkClients.adminClient() + .metrics() + .create( + new CreateMetric() + .withName(ns.prefix("display_child")) + .withDisplayName("Distinct Margin Variant") + .withDescription("Child") + .withParent(root.getFullyQualifiedName())); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("display_group")) + .withDisplayName("Friendly Profitability Group") + .withMetrics(List.of(root.getFullyQualifiedName()))); + + JsonNode members = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/" + group.getId() + "/metrics?q=Distinct&limit=10&offset=0", + null, + Object.class)); + assertEquals(1, members.get("paging").get("total").asInt()); + assertEquals(child.getId().toString(), members.get("data").get(0).get("id").asText()); + + JsonNode byMemberDisplayName = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=Distinct&limit=10&offset=0", + null, + Object.class)); + assertEquals(1, byMemberDisplayName.get("paging").get("total").asInt()); + assertEquals( + group.getId().toString(), + byMemberDisplayName.get("data").get(0).get("group").get("id").asText()); + + JsonNode byGroupDisplayName = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=Profitability&limit=10&offset=0", + null, + Object.class)); + assertEquals(1, byGroupDisplayName.get("paging").get("total").asInt()); + assertEquals( + group.getId().toString(), + byGroupDisplayName.get("data").get(0).get("group").get("id").asText()); + } + + @Test + void groupMutationsAndHardDeleteRefreshMemberSearchDocuments(TestNamespace ns) throws Exception { + RestClient rest = RestClient.admin(); + Metric metric = createMetric(ns, "search_refresh_member"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("search_refresh_group")) + .withDescription("Initial group description") + .withMetrics(List.of(metric.getFullyQualifiedName()))); + + awaitMetricSearchDocument( + rest, + metric.getId(), + document -> assertEquals(group.getId().toString(), groupId(document))); + + String originalJson = JSON.writeValueAsString(group); + group.setName(ns.prefix("search_refresh_renamed")); + group.setDisplayName("Renamed Metric Group"); + group.setDescription("Updated group description"); + MetricGroup updated = + rest.patch(GROUPS_PATH, group.getId(), originalJson, group, MetricGroup.class); + + awaitMetricSearchDocument( + rest, + metric.getId(), + document -> { + JsonNode groupReference = document.path("metricGroup"); + assertEquals(updated.getName(), groupReference.path("name").asText()); + assertEquals(updated.getDisplayName(), groupReference.path("displayName").asText()); + assertEquals( + updated.getFullyQualifiedName(), groupReference.path("fullyQualifiedName").asText()); + }); + awaitSearchDocument( + rest, + "metric_group_search_index", + group.getId(), + document -> + assertEquals("Updated group description", document.path("description").asText())); + + rest.delete(GROUPS_PATH, group.getId()); + awaitMetricSearchDocument(rest, metric.getId(), MetricGroupResourceIT::assertNoMetricGroup); + assertMetricHasNoVisibleGroup(metric); + assertHierarchyShowsStandaloneMetric(metric); + + rest.restore(GROUPS_PATH, group.getId(), MetricGroup.class); + awaitMetricSearchDocument( + rest, + metric.getId(), + document -> assertEquals(group.getId().toString(), groupId(document))); + assertMetricHasGroup(metric, group); + assertHierarchyShowsGroup(metric, group); + + rest.hardDelete(GROUPS_PATH, group.getId()); + awaitMetricSearchDocument(rest, metric.getId(), MetricGroupResourceIT::assertNoMetricGroup); + assertMetricHasNoVisibleGroup(metric); + assertHierarchyShowsStandaloneMetric(metric); + } + + @Test + void asyncRestoreRefreshesMemberSearchDocumentsAfterCommit(TestNamespace ns) throws Exception { + RestClient rest = RestClient.admin(); + Metric metric = createMetric(ns, "async_restore_member"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("async_restore_group")) + .withMetrics(List.of(metric.getFullyQualifiedName()))); + + rest.delete(GROUPS_PATH, group.getId()); + awaitMetricSearchDocument(rest, metric.getId(), MetricGroupResourceIT::assertNoMetricGroup); + + try (Response response = + rest.rawPut(GROUPS_PATH + "/restore?async=true", Map.of("id", group.getId()))) { + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } + + awaitMetricSearchDocument( + rest, + metric.getId(), + document -> assertEquals(group.getId().toString(), groupId(document))); + Awaitility.await("Metric Group async restore is visible through the API") + .pollDelay(Duration.ZERO) + .pollInterval(Duration.ofMillis(200)) + .atMost(Duration.ofSeconds(60)) + .untilAsserted(() -> assertMetricHasGroup(metric, group)); + assertHierarchyShowsGroup(metric, group); + } + + @Test + void memberDeleteAndRestoreRefreshGroupCountsAndSearchDocument(TestNamespace ns) { + RestClient rest = RestClient.admin(); + Metric metric = createMetric(ns, "count_refresh_member"); + MetricGroup group = + createGroup( + new CreateMetricGroup() + .withName(ns.prefix("count_refresh_group")) + .withMetrics(List.of(metric.getFullyQualifiedName()))); + + awaitSearchDocument( + rest, + "metric_group_search_index", + group.getId(), + document -> assertEquals(1, document.path("metricCount").asInt())); + + SdkClients.adminClient().metrics().delete(metric.getId().toString()); + assertEquals(0, getGroup(group.getName(), "metricCount").getMetricCount()); + awaitSearchDocument( + rest, + "metric_group_search_index", + group.getId(), + document -> assertEquals(0, document.path("metricCount").asInt())); + + SdkClients.adminClient().metrics().restore(metric.getId().toString()); + assertEquals(1, getGroup(group.getName(), "metricCount").getMetricCount()); + awaitSearchDocument( + rest, + "metric_group_search_index", + group.getId(), + document -> assertEquals(1, document.path("metricCount").asInt())); + + Map params = new HashMap<>(); + params.put("hardDelete", "true"); + SdkClients.adminClient().metrics().delete(metric.getId().toString(), params); + assertEquals(0, getGroup(group.getName(), "metricCount").getMetricCount()); + awaitSearchDocument( + rest, + "metric_group_search_index", + group.getId(), + document -> assertEquals(0, document.path("metricCount").asInt())); + } + + private static void assertNoMetricGroup(JsonNode metricDocument) { + JsonNode metricGroup = metricDocument.path("metricGroup"); + assertTrue(metricGroup.isMissingNode() || metricGroup.isNull()); + } + + private static String groupId(JsonNode metricDocument) { + return metricDocument.path("metricGroup").path("id").asText(); + } + + private static void assertMetricHasNoVisibleGroup(Metric metric) { + Metric fetched = + SdkClients.adminClient().metrics().get(metric.getId().toString(), "metricGroup"); + assertNull(fetched.getMetricGroup()); + } + + private static void assertMetricHasGroup(Metric metric, MetricGroup group) { + Metric fetched = + SdkClients.adminClient().metrics().get(metric.getId().toString(), "metricGroup"); + assertNotNull(fetched.getMetricGroup()); + assertEquals(group.getId(), fetched.getMetricGroup().getId()); + } + + private static void assertHierarchyShowsStandaloneMetric(Metric metric) { + JsonNode item = hierarchyItem(metric); + assertEquals(METRIC, item.path("kind").asText()); + assertEquals(metric.getId().toString(), item.path("metric").path("id").asText()); + assertFalse(item.has("group")); + } + + private static void assertHierarchyShowsGroup(Metric metric, MetricGroup group) { + JsonNode item = hierarchyItem(metric); + assertEquals(METRIC_GROUP, item.path("kind").asText()); + assertEquals(group.getId().toString(), item.path("group").path("id").asText()); + assertFalse(item.has("metric")); + } + + private static JsonNode hierarchyItem(Metric metric) { + JsonNode response = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + metric.getName() + "&limit=10&offset=0", + null, + Object.class)); + assertEquals(1, response.path("paging").path("total").asInt()); + return response.path("data").get(0); + } + + private static void patchGroupMembers( + OpenMetadataClient client, MetricGroup group, List metrics) { + MetricGroup original = getGroup(group.getName(), "metricCount"); + original.setMetrics(getGroupMemberReferences(group)); + MetricGroup updated = JsonUtils.deepCopy(original, MetricGroup.class).withMetrics(metrics); + patchGroup(client, group.getId(), original, updated); + } + + private static JsonNode getGroupMembers(MetricGroup group, int limit, int offset) { + return JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + GROUPS_PATH + "/" + group.getId() + "/metrics?limit=" + limit + "&offset=" + offset, + null, + Object.class)); + } + + private static List getGroupMemberReferences(MetricGroup group) { + List references = new ArrayList<>(); + for (JsonNode member : getGroupMembers(group, 1000, 0).path("data")) { + references.add(JSON.convertValue(member, Metric.class).getEntityReference()); + } + return references; + } + + private static void patchGroup( + OpenMetadataClient client, UUID groupId, MetricGroup original, MetricGroup updated) { + String patch = JsonUtils.getJsonPatch(original, updated).toString(); + client + .getHttpClient() + .executeForString( + HttpMethod.PATCH, + GROUPS_PATH + "/" + groupId, + patch, + RequestOptions.builder() + .header("Content-Type", MediaType.APPLICATION_JSON_PATCH_JSON) + .build()); + } + + private static void assertUngroupedSubtree(Metric root, Metric child) { + assertMetricHasNoVisibleGroup(root); + assertMetricHasNoVisibleGroup(child); + } + + private static void assertGroupNotFound(String name) { + OpenMetadataException exception = + assertThrows(OpenMetadataException.class, () -> getGroup(name, "metricCount")); + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), exception.getStatusCode()); + } + + private static void assertForbidden(Runnable request) { + OpenMetadataException exception = assertThrows(OpenMetadataException.class, request::run); + int statusCode = exception.getStatusCode(); + if (statusCode < 0 && exception.getCause() instanceof OpenMetadataException cause) { + statusCode = cause.getStatusCode(); + } + assertEquals(Response.Status.FORBIDDEN.getStatusCode(), statusCode); + } + + private static void assertSubtreeGroup(Metric root, Metric child, MetricGroup group) { + assertMetricHasGroup(root, group); + assertMetricHasGroup(child, group); + assertEquals(2, getGroup(group.getName(), "metricCount").getMetricCount()); + } + + private static boolean assignGroupAfterStart( + MetricGroup group, Metric root, CountDownLatch ready, CountDownLatch start) { + ready.countDown(); + try { + if (!start.await(10, TimeUnit.SECONDS)) { + throw new IllegalStateException("Concurrent assignment start barrier timed out"); + } + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.PUT, + GROUPS_PATH + "/" + group.getName() + "/metrics/add", + new BulkAssets().withAssets(List.of(root.getEntityReference())), + BulkOperationResult.class); + return true; + } catch (InterruptedException exception) { + Thread.currentThread().interrupt(); + throw new IllegalStateException("Concurrent assignment was interrupted", exception); + } catch (OpenMetadataException exception) { + return false; + } + } + + private static void withRestrictedMetricEditor( + TestNamespace ns, Consumer assertions) { + OpenMetadataClient admin = SdkClients.adminClient(); + String suffix = ns.uniqueShortId(); + Rule allowCatalog = + new Rule() + .withName("AllowMetricGroupWrites") + .withResources(List.of(ALL_RESOURCES)) + .withOperations( + List.of( + MetadataOperation.CREATE, + MetadataOperation.VIEW_ALL, + MetadataOperation.EDIT_ALL)) + .withEffect(Rule.Effect.ALLOW); + Rule denyRestrictedMetricEdits = + new Rule() + .withName("DenyRestrictedMetricEdits") + .withResources(List.of(METRIC, METRIC_GROUP)) + .withOperations(List.of(MetadataOperation.EDIT_ALL)) + .withCondition("matchAnyTag('" + RESTRICTED_TAG_FQN + "')") + .withEffect(Rule.Effect.DENY); + Policy policy = + admin + .policies() + .create( + new CreatePolicy() + .withName("metricGroupWritePolicy_" + suffix) + .withRules(List.of(allowCatalog, denyRestrictedMetricEdits))); + try { + Role role = + admin + .roles() + .create( + new CreateRole() + .withName("metricGroupWriteRole_" + suffix) + .withPolicies(List.of(policy.getFullyQualifiedName()))); + try { + String userName = "metric-group-writer-" + suffix; + String email = userName + "@test.openmetadata.org"; + User user = + admin + .users() + .create( + new CreateUser() + .withName(userName) + .withEmail(email) + .withRoles(List.of(role.getId()))); + try { + assertions.accept(SdkClients.createClient(email, email, new String[] {})); + } finally { + admin.users().delete(user.getId()); + } + } finally { + admin.roles().delete(role.getId()); + } + } finally { + admin.policies().delete(policy.getId()); + } + } + + private static ConnectionType currentConnectionType() { + return MYSQL_DATABASE_TYPE.equalsIgnoreCase(System.getProperty("databaseType", "postgres")) + ? ConnectionType.MYSQL + : ConnectionType.POSTGRES; + } + + private static void createMembershipFailureConstraint( + Jdbi jdbi, String constraint, UUID groupId, UUID metricId) { + jdbi.useHandle( + handle -> + handle.execute( + "ALTER TABLE entity_relationship ADD CONSTRAINT " + + constraint + + " CHECK (NOT (fromId = '" + + groupId + + "' AND toId = '" + + metricId + + "' AND fromEntity = '" + + METRIC_GROUP + + "' AND toEntity = '" + + METRIC + + "' AND relation = " + + Relationship.HAS.ordinal() + + "))")); + } + + private static void dropMembershipFailureConstraint( + Jdbi jdbi, ConnectionType connectionType, String constraint) { + jdbi.useHandle( + handle -> { + if (connectionType == ConnectionType.MYSQL) { + handle.execute("ALTER TABLE entity_relationship DROP CHECK " + constraint); + } else { + handle.execute("ALTER TABLE entity_relationship DROP CONSTRAINT " + constraint); + } + }); + } + + private static int membershipCount(Jdbi jdbi, UUID groupId, UUID metricId) { + return jdbi.withHandle( + handle -> + handle + .createQuery( + "SELECT COUNT(*) FROM entity_relationship WHERE fromId = :groupId " + + "AND toId = :metricId AND fromEntity = :groupType " + + "AND toEntity = :metricType AND relation = :relation") + .bind("groupId", groupId.toString()) + .bind("metricId", metricId.toString()) + .bind("groupType", METRIC_GROUP) + .bind("metricType", METRIC) + .bind("relation", Relationship.HAS.ordinal()) + .mapTo(Integer.class) + .one()); + } + + private static void awaitMetricSearchDocument( + RestClient rest, UUID metricId, Consumer assertion) { + awaitSearchDocument(rest, "metric_search_index", metricId, assertion); + } + + private static void awaitFilteredSearchResult(MetricGroup group, int metricCount) { + awaitSearchDocument( + RestClient.admin(), + "metric_group_search_index", + group.getId(), + document -> assertEquals(metricCount, document.path("metricCount").asInt())); + String queryFilter = + String.format( + "{\"query\":{\"bool\":{\"must\":[{\"term\":{\"id.keyword\":\"%s\"}},{\"term\":{\"metricCount\":%d}}]}}}", + group.getId(), metricCount); + Awaitility.await("Metric Group is returned by filtered search after reindex") + .pollDelay(Duration.ZERO) + .pollInterval(Duration.ofMillis(200)) + .atMost(Duration.ofSeconds(60)) + .untilAsserted( + () -> { + String response = + SdkClients.adminClient() + .search() + .query("*") + .index("metric_group_search_index") + .queryFilter(queryFilter) + .size(1) + .execute(); + JsonNode hits = JSON.readTree(response).path("hits").path("hits"); + assertEquals(1, hits.size(), "Filtered Metric Group search must return one group"); + JsonNode source = hits.get(0).path("_source"); + assertEquals(group.getId().toString(), source.path("id").asText()); + assertEquals(metricCount, source.path("metricCount").asInt()); + }); + } + + private static void awaitSearchDocument( + RestClient rest, String index, UUID id, Consumer assertion) { + Awaitility.await("Search document " + index + "/" + id + " is refreshed") + .pollDelay(Duration.ZERO) + .pollInterval(Duration.ofMillis(200)) + .atMost(Duration.ofSeconds(60)) + .untilAsserted( + () -> { + try (Response response = rest.rawGet("v1/search/get/" + index + "/doc/" + id)) { + assertEquals(200, response.getStatus()); + assertion.accept(JSON.readTree(response.readEntity(String.class))); + } + }); + } + + private static void awaitSearchDocumentDeletion(RestClient rest, String index, UUID id) { + Awaitility.await("Search document " + index + "/" + id + " is deleted") + .pollDelay(Duration.ZERO) + .pollInterval(Duration.ofMillis(200)) + .atMost(Duration.ofSeconds(60)) + .untilAsserted( + () -> { + try (Response response = rest.rawGet("v1/search/get/" + index + "/doc/" + id)) { + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); + } + }); + } +} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationIT.java new file mode 100644 index 000000000000..816bd4726412 --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationIT.java @@ -0,0 +1,166 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.it.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openmetadata.it.tests.MergedMetricMigrationTestSupport.runMergedUpgradeScenario; +import static org.openmetadata.it.tests.MetricMigrationSqlFixture.currentConnectionType; +import static org.openmetadata.it.tests.MetricMigrationSqlFixture.readMigrationScripts; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.INCIDENT_INDEXES; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.INCIDENT_TABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MEMBERSHIP_COLUMN; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MEMBERSHIP_INDEX; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_GROUP_DELETED_INDEX; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_GROUP_NAME_INDEX; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_GROUP_TABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.METRIC_TABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MYSQL_MEMBERSHIP_COLUMN_DDL_VARIABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MYSQL_MEMBERSHIP_COLUMN_STATEMENT; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MYSQL_MEMBERSHIP_INDEX_DDL_VARIABLE; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.MYSQL_MEMBERSHIP_INDEX_STATEMENT; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.assertCleanBootstrapSchema; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.metricPostStatements; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.metricSchemaStatements; +import static org.openmetadata.it.tests.MetricMigrationTestSupport.runUpgradeScenario; + +import java.util.List; +import java.util.function.Predicate; +import org.jdbi.v3.core.Jdbi; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.openmetadata.it.bootstrap.TestSuiteBootstrap; +import org.openmetadata.it.tests.MetricMigrationSqlFixture.MigrationScripts; +import org.openmetadata.it.tests.MetricMigrationTestSupport.IndexExpectation; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +@Execution(ExecutionMode.CONCURRENT) +class MetricMigrationIT { + + @Test + void migrationFilesContainCompleteMetricAndIncidentManagerStatements() throws Exception { + ConnectionType connectionType = currentConnectionType(); + MigrationScripts scripts = readMigrationScripts(connectionType); + List metricSchemaStatements = metricSchemaStatements(scripts); + List metricPostStatements = metricPostStatements(scripts); + + assertEquals(connectionType == ConnectionType.MYSQL ? 9 : 4, metricSchemaStatements.size()); + assertEquals(1, metricPostStatements.size()); + assertMetricDdlMarkers(metricSchemaStatements, connectionType); + assertIncidentManagerMarkers(scripts); + assertMergedStatementOrder(scripts); + } + + @Test + void cleanBootstrapContainsMetricAndIncidentManagerSchema() { + assertCleanBootstrapSchema(TestSuiteBootstrap.getJdbi(), currentConnectionType()); + } + + @Test + void metricMigrationUpgradesExistingRowsWithoutDataLoss() throws Exception { + ConnectionType connectionType = currentConnectionType(); + MigrationScripts scripts = readMigrationScripts(connectionType); + Jdbi jdbi = TestSuiteBootstrap.getJdbi(); + + runUpgradeScenario(jdbi, scripts, connectionType); + } + + @Test + void mergedMigrationUpgradesPopulatedPriorShapeFixture() throws Exception { + ConnectionType connectionType = currentConnectionType(); + MigrationScripts scripts = readMigrationScripts(connectionType); + + runMergedUpgradeScenario(TestSuiteBootstrap.getJdbi(), scripts, connectionType); + } + + private void assertMetricDdlMarkers( + List metricStatements, ConnectionType connectionType) { + String ddl = String.join(System.lineSeparator(), metricStatements); + assertTrue(ddl.contains("CREATE TABLE IF NOT EXISTS " + METRIC_GROUP_TABLE)); + assertTrue(ddl.contains(METRIC_GROUP_NAME_INDEX)); + assertTrue(ddl.contains(METRIC_GROUP_DELETED_INDEX)); + assertTrue(ddl.contains(MEMBERSHIP_INDEX)); + if (connectionType == ConnectionType.MYSQL) { + assertTrue(ddl.contains("ADD COLUMN " + MEMBERSHIP_COLUMN)); + assertTrue(ddl.contains("GENERATED ALWAYS AS")); + assertTrue(ddl.contains(MYSQL_MEMBERSHIP_COLUMN_DDL_VARIABLE)); + assertTrue(ddl.contains(MYSQL_MEMBERSHIP_COLUMN_STATEMENT)); + assertTrue(ddl.contains(MYSQL_MEMBERSHIP_INDEX_DDL_VARIABLE)); + assertTrue(ddl.contains(MYSQL_MEMBERSHIP_INDEX_STATEMENT)); + } else { + assertTrue(ddl.contains("CREATE UNIQUE INDEX IF NOT EXISTS " + MEMBERSHIP_INDEX)); + assertTrue(ddl.contains("WHERE fromEntity = 'metricGroup'")); + } + } + + private void assertIncidentManagerMarkers(MigrationScripts scripts) { + String schemaSql = String.join(System.lineSeparator(), scripts.schemaStatements()); + String postSql = String.join(System.lineSeparator(), scripts.postStatements()); + assertTrue(schemaSql.contains("CREATE TABLE IF NOT EXISTS " + INCIDENT_TABLE)); + for (IndexExpectation index : INCIDENT_INDEXES) { + assertTrue(schemaSql.contains(index.name()), index.name()); + } + assertTrue(postSql.contains("INSERT INTO " + INCIDENT_TABLE)); + } + + private void assertMergedStatementOrder(MigrationScripts scripts) { + int lastIncidentSchema = + lastMatchingIndex(scripts.schemaStatements(), this::isIncidentStatement); + int firstMetricSchema = + firstMatchingIndex(scripts.schemaStatements(), this::isMetricSchemaStatement); + int incidentBackfill = firstMatchingIndex(scripts.postStatements(), this::isIncidentStatement); + int metricBackfill = firstMatchingIndex(scripts.postStatements(), this::isMetricPostStatement); + assertTrue(lastIncidentSchema >= 0); + assertTrue(firstMetricSchema > lastIncidentSchema); + assertTrue(incidentBackfill >= 0); + assertTrue(metricBackfill > incidentBackfill); + } + + private int firstMatchingIndex(List statements, Predicate predicate) { + int result = -1; + for (int index = 0; index < statements.size() && result < 0; index++) { + if (predicate.test(statements.get(index))) { + result = index; + } + } + return result; + } + + private int lastMatchingIndex(List statements, Predicate predicate) { + int result = -1; + for (int index = 0; index < statements.size(); index++) { + if (predicate.test(statements.get(index))) { + result = index; + } + } + return result; + } + + private boolean isMetricSchemaStatement(String statement) { + return statement.contains(METRIC_GROUP_TABLE) + || statement.contains(MEMBERSHIP_COLUMN) + || statement.contains(MEMBERSHIP_INDEX); + } + + private boolean isMetricPostStatement(String statement) { + return statement.contains("UPDATE " + METRIC_TABLE); + } + + private boolean isIncidentStatement(String statement) { + return statement.contains(INCIDENT_TABLE) + || statement.contains("idx_test_case") + || statement.contains("test_case_resolution_status_time_series"); + } +} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationSqlFixture.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationSqlFixture.java new file mode 100644 index 000000000000..b122fdebf2ba --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationSqlFixture.java @@ -0,0 +1,76 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.it.tests; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import org.flywaydb.core.api.configuration.ClassicConfiguration; +import org.flywaydb.core.api.configuration.Configuration; +import org.flywaydb.core.internal.database.postgresql.PostgreSQLParser; +import org.flywaydb.core.internal.parser.Parser; +import org.flywaydb.core.internal.parser.ParsingContext; +import org.flywaydb.core.internal.resource.filesystem.FileSystemResource; +import org.flywaydb.core.internal.sqlscript.SqlStatementIterator; +import org.flywaydb.database.mysql.MySQLParser; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +final class MetricMigrationSqlFixture { + private MetricMigrationSqlFixture() {} + + static MigrationScripts readMigrationScripts(ConnectionType connectionType) throws Exception { + String dialect = connectionType == ConnectionType.MYSQL ? "mysql" : "postgres"; + Path migrationDirectory = migrationDirectory().resolve(dialect); + return new MigrationScripts( + parseSql(migrationDirectory.resolve("schemaChanges.sql"), connectionType), + parseSql(migrationDirectory.resolve("postDataMigrationSQLScript.sql"), connectionType)); + } + + private static List parseSql(Path path, ConnectionType connectionType) throws Exception { + Parser parser = sqlParser(connectionType); + List statements = new ArrayList<>(); + FileSystemResource resource = + new FileSystemResource(null, path.toString(), StandardCharsets.UTF_8, true); + try (SqlStatementIterator iterator = parser.parse(resource)) { + while (iterator.hasNext()) { + statements.add(iterator.next().getSql()); + } + } + return List.copyOf(statements); + } + + private static Parser sqlParser(ConnectionType connectionType) { + Configuration configuration = new ClassicConfiguration(); + ParsingContext parsingContext = new ParsingContext(); + return connectionType == ConnectionType.MYSQL + ? new MySQLParser(configuration, parsingContext) + : new PostgreSQLParser(configuration, parsingContext); + } + + private static Path migrationDirectory() { + Path moduleRelative = Path.of("..", "bootstrap", "sql", "migrations", "native", "2.1.0"); + Path rootRelative = Path.of("bootstrap", "sql", "migrations", "native", "2.1.0"); + return Files.exists(moduleRelative) ? moduleRelative : rootRelative; + } + + static ConnectionType currentConnectionType() { + return "mysql".equalsIgnoreCase(System.getProperty("databaseType", "postgres")) + ? ConnectionType.MYSQL + : ConnectionType.POSTGRES; + } + + record MigrationScripts(List schemaStatements, List postStatements) {} +} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationTestSupport.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationTestSupport.java new file mode 100644 index 000000000000..4d8d4d6c314e --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricMigrationTestSupport.java @@ -0,0 +1,558 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.it.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.Jdbi; +import org.jdbi.v3.core.statement.UnableToExecuteStatementException; +import org.openmetadata.it.tests.MetricMigrationSqlFixture.MigrationScripts; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +final class MetricMigrationTestSupport { + static final String METRIC_GROUP_TABLE = "metric_group_entity"; + static final String METRIC_TABLE = "metric_entity"; + static final String RELATIONSHIP_TABLE = "entity_relationship"; + static final String INCIDENT_TABLE = "test_case_incident"; + static final String METRIC_GROUP_NAME_INDEX = "metric_group_entity_name_index"; + static final String METRIC_GROUP_DELETED_INDEX = "idx_metric_group_entity_deleted_name_id"; + static final String MEMBERSHIP_INDEX = "uq_metric_group_single_membership"; + static final String MEMBERSHIP_COLUMN = "metricGroupMetricId"; + static final String MYSQL_MEMBERSHIP_COLUMN_DDL_VARIABLE = "metric_group_membership_column_ddl"; + static final String MYSQL_MEMBERSHIP_COLUMN_STATEMENT = "metric_group_membership_column_stmt"; + static final String MYSQL_MEMBERSHIP_INDEX_DDL_VARIABLE = "metric_group_membership_index_ddl"; + static final String MYSQL_MEMBERSHIP_INDEX_STATEMENT = "metric_group_membership_index_stmt"; + static final List INCIDENT_INDEXES = + List.of( + new IndexExpectation( + "test_case_resolution_status_time_series", + "idx_test_case_resolution_status_state_id"), + new IndexExpectation( + "test_case_resolution_status_time_series", "idx_test_case_resolution_status_fqn_ts"), + new IndexExpectation("test_case", "idx_test_case_id"), + new IndexExpectation( + "test_case_resolution_status_time_series", + "idx_test_case_resolution_status_assignee"), + new IndexExpectation(INCIDENT_TABLE, "idx_tci_status_fqn"), + new IndexExpectation(INCIDENT_TABLE, "idx_tci_fqn"), + new IndexExpectation(INCIDENT_TABLE, "idx_tci_assignee"), + new IndexExpectation(INCIDENT_TABLE, "idx_tci_updated")); + private static final String METRIC_GROUP = "metricGroup"; + private static final String METRIC = "metric"; + private static final String TABLE = "table"; + private static final String TEAM = "team"; + private static final GroupFixture METRIC_GROUP_FIXTURE = + new GroupFixture( + "group-fixture-id", "migration-group", "migration-group-hash", 123L, "migration-test"); + private static final GroupFixture DUPLICATE_FQN_GROUP_FIXTURE = + new GroupFixture( + "duplicate-group-fixture-id", + "duplicate-migration-group", + METRIC_GROUP_FIXTURE.fqnHash(), + 456L, + "migration-test"); + private static final int HAS_RELATION = 10; + + private MetricMigrationTestSupport() {} + + static void assertCleanBootstrapSchema(Jdbi jdbi, ConnectionType connectionType) { + jdbi.useHandle( + handle -> { + assertTrue(tableExists(handle, METRIC_GROUP_TABLE, connectionType)); + assertTrue(tableExists(handle, INCIDENT_TABLE, connectionType)); + assertTrue( + indexExists(handle, METRIC_GROUP_TABLE, METRIC_GROUP_NAME_INDEX, connectionType)); + assertTrue( + indexExists(handle, METRIC_GROUP_TABLE, METRIC_GROUP_DELETED_INDEX, connectionType)); + assertMembershipIndex(handle, RELATIONSHIP_TABLE, MEMBERSHIP_INDEX, connectionType); + for (IndexExpectation index : INCIDENT_INDEXES) { + assertTrue( + indexExists(handle, index.table(), index.name(), connectionType), + index.table() + "." + index.name()); + } + }); + } + + static void runUpgradeScenario( + Jdbi jdbi, MigrationScripts scripts, ConnectionType connectionType) { + MigrationFixture fixture = MigrationFixture.create(); + try { + jdbi.useHandle(handle -> runUpgradeScenario(handle, fixture, scripts, connectionType)); + } finally { + dropFixture(jdbi, fixture); + } + } + + private static void runUpgradeScenario( + Handle handle, + MigrationFixture fixture, + MigrationScripts scripts, + ConnectionType connectionType) { + createRelationshipFixture(handle, fixture.relationshipTable()); + insertPreexistingRelationships(handle, fixture.relationshipTable()); + executeMetricSchema(handle, fixture, scripts); + assertMetricGroupTable(handle, fixture, connectionType); + assertMembershipConstraint(handle, fixture, connectionType); + createMetricFixture(handle, fixture.metricTable(), connectionType); + insertPreexistingMetrics(handle, fixture.metricTable(), connectionType); + executeStatusBackfill(handle, fixture, scripts); + assertMetricStatuses(handle, fixture.metricTable(), connectionType); + } + + private static void executeMetricSchema( + Handle handle, MigrationFixture fixture, MigrationScripts scripts) { + List statements = + metricSchemaStatements(scripts).stream() + .map(statement -> fixtureStatement(statement, fixture)) + .toList(); + statements.forEach(handle::execute); + statements.forEach(handle::execute); + } + + private static void executeStatusBackfill( + Handle handle, MigrationFixture fixture, MigrationScripts scripts) { + String statement = + metricPostStatements(scripts).getFirst().replace(METRIC_TABLE, fixture.metricTable()); + handle.execute(statement); + handle.execute(statement); + } + + private static void createRelationshipFixture(Handle handle, String tableName) { + handle.execute( + "CREATE TABLE " + + tableName + + " (fromId VARCHAR(36) NOT NULL, toId VARCHAR(36) NOT NULL, " + + "fromEntity VARCHAR(256) NOT NULL, toEntity VARCHAR(256) NOT NULL, " + + "relation SMALLINT NOT NULL, relationType VARCHAR(64) NOT NULL DEFAULT '', " + + "PRIMARY KEY (fromId, toId, relation, relationType))"); + } + + private static void insertPreexistingRelationships(Handle handle, String tableName) { + insertRelationship( + handle, tableName, "group-a", "metric-a", METRIC_GROUP, METRIC, HAS_RELATION); + insertRelationship(handle, tableName, "team-a", "metric-a", TEAM, METRIC, HAS_RELATION); + insertRelationship( + handle, tableName, "group-b", "metric-b", METRIC_GROUP, METRIC, HAS_RELATION); + insertRelationship(handle, tableName, "group-a", "table-a", METRIC_GROUP, TABLE, HAS_RELATION); + } + + private static void assertMembershipConstraint( + Handle handle, MigrationFixture fixture, ConnectionType connectionType) { + assertEquals(4, countRows(handle, fixture.relationshipTable())); + assertMembershipIndex( + handle, fixture.relationshipTable(), fixture.membershipIndex(), connectionType); + assertGeneratedMembershipValues(handle, fixture.relationshipTable(), connectionType); + assertThrows( + UnableToExecuteStatementException.class, + () -> + insertRelationship( + handle, + fixture.relationshipTable(), + "group-c", + "metric-a", + METRIC_GROUP, + METRIC, + HAS_RELATION)); + insertRelationship( + handle, fixture.relationshipTable(), "team-b", "metric-a", TEAM, METRIC, HAS_RELATION); + insertRelationship( + handle, fixture.relationshipTable(), "group-c", "metric-a", METRIC_GROUP, METRIC, 0); + assertEquals(6, countRows(handle, fixture.relationshipTable())); + } + + private static void insertRelationship( + Handle handle, + String tableName, + String fromId, + String toId, + String fromEntity, + String toEntity, + int relation) { + handle + .createUpdate( + "INSERT INTO " + + tableName + + " (fromId, toId, fromEntity, toEntity, relation) " + + "VALUES (:fromId, :toId, :fromEntity, :toEntity, :relation)") + .bind("fromId", fromId) + .bind("toId", toId) + .bind("fromEntity", fromEntity) + .bind("toEntity", toEntity) + .bind("relation", relation) + .execute(); + } + + private static void assertGeneratedMembershipValues( + Handle handle, String relationshipTable, ConnectionType connectionType) { + if (connectionType == ConnectionType.MYSQL) { + int generatedValues = + handle + .createQuery( + "SELECT COUNT(*) FROM " + + relationshipTable + + " WHERE " + + MEMBERSHIP_COLUMN + + " IS NOT NULL") + .mapTo(Integer.class) + .one(); + assertEquals(2, generatedValues); + assertTrue(isStoredGeneratedColumn(handle, relationshipTable, MEMBERSHIP_COLUMN)); + } + } + + private static void assertMetricGroupTable( + Handle handle, MigrationFixture fixture, ConnectionType connectionType) { + assertTrue(tableExists(handle, fixture.groupTable(), connectionType)); + assertTrue(indexExists(handle, fixture.groupTable(), fixture.groupNameIndex(), connectionType)); + assertTrue( + indexExists(handle, fixture.groupTable(), fixture.groupDeletedIndex(), connectionType)); + insertMetricGroup(handle, fixture.groupTable(), connectionType, METRIC_GROUP_FIXTURE); + assertMetricGroupProjection(readMetricGroup(handle, fixture.groupTable())); + assertMetricGroupFqnIsUnique(handle, fixture.groupTable(), connectionType); + } + + private static void assertMetricGroupProjection(GroupProjection projection) { + assertEquals(METRIC_GROUP_FIXTURE.id(), projection.id()); + assertEquals(METRIC_GROUP_FIXTURE.name(), projection.name()); + assertEquals(METRIC_GROUP_FIXTURE.updatedAt(), projection.updatedAt()); + assertEquals(METRIC_GROUP_FIXTURE.updatedBy(), projection.updatedBy()); + assertFalse(projection.deleted()); + } + + private static void assertMetricGroupFqnIsUnique( + Handle handle, String groupTable, ConnectionType connectionType) { + assertThrows( + UnableToExecuteStatementException.class, + () -> insertMetricGroup(handle, groupTable, connectionType, DUPLICATE_FQN_GROUP_FIXTURE)); + assertEquals(1, countRows(handle, groupTable)); + } + + private static void insertMetricGroup( + Handle handle, String groupTable, ConnectionType connectionType, GroupFixture groupFixture) { + String jsonValue = connectionType == ConnectionType.MYSQL ? ":json" : "CAST(:json AS JSONB)"; + handle + .createUpdate( + "INSERT INTO " + groupTable + " (json, fqnHash) VALUES (" + jsonValue + ", :hash)") + .bind("json", metricGroupJson(groupFixture)) + .bind("hash", groupFixture.fqnHash()) + .execute(); + } + + private static String metricGroupJson(GroupFixture groupFixture) { + return "{\"id\":\"" + + groupFixture.id() + + "\",\"name\":\"" + + groupFixture.name() + + "\",\"updatedAt\":" + + groupFixture.updatedAt() + + ",\"updatedBy\":\"" + + groupFixture.updatedBy() + + "\",\"deleted\":false}"; + } + + private static GroupProjection readMetricGroup(Handle handle, String groupTable) { + return handle + .createQuery( + "SELECT id, name, updatedAt, updatedBy, deleted FROM " + groupTable + " LIMIT 1") + .map( + (row, context) -> + new GroupProjection( + row.getString("id"), + row.getString("name"), + row.getLong("updatedAt"), + row.getString("updatedBy"), + row.getBoolean("deleted"))) + .one(); + } + + private static void createMetricFixture( + Handle handle, String metricTable, ConnectionType connectionType) { + String jsonType = connectionType == ConnectionType.MYSQL ? "JSON" : "JSONB"; + handle.execute( + "CREATE TABLE " + + metricTable + + " (id VARCHAR(36) PRIMARY KEY, json " + + jsonType + + " NOT NULL)"); + } + + private static void insertPreexistingMetrics( + Handle handle, String metricTable, ConnectionType connectionType) { + insertMetric(handle, metricTable, connectionType, "missing", "{\"name\":\"missing\"}"); + insertMetric( + handle, + metricTable, + connectionType, + "jsonNull", + "{\"name\":\"jsonNull\",\"entityStatus\":null}"); + insertMetric( + handle, + metricTable, + connectionType, + "unprocessed", + "{\"name\":\"unprocessed\",\"entityStatus\":\"Unprocessed\"}"); + insertMetric( + handle, + metricTable, + connectionType, + "approved", + "{\"name\":\"approved\",\"entityStatus\":\"Approved\"}"); + insertMetric( + handle, + metricTable, + connectionType, + "inReview", + "{\"name\":\"inReview\",\"entityStatus\":\"In Review\"}"); + insertMetric( + handle, + metricTable, + connectionType, + "rejected", + "{\"name\":\"rejected\",\"entityStatus\":\"Rejected\"}"); + } + + private static void insertMetric( + Handle handle, String metricTable, ConnectionType connectionType, String id, String json) { + String jsonValue = connectionType == ConnectionType.MYSQL ? ":json" : "CAST(:json AS JSONB)"; + handle + .createUpdate("INSERT INTO " + metricTable + " (id, json) VALUES (:id, " + jsonValue + ")") + .bind("id", id) + .bind("json", json) + .execute(); + } + + private static void assertMetricStatuses( + Handle handle, String metricTable, ConnectionType connectionType) { + Map metrics = + handle + .createQuery(metricProjectionQuery(metricTable, connectionType)) + .map( + (row, context) -> + new MetricProjection( + row.getString("id"), row.getString("status"), row.getString("name"))) + .list() + .stream() + .collect(Collectors.toMap(MetricProjection::id, projection -> projection)); + assertEquals(6, metrics.size()); + assertEquals("Approved", metrics.get("missing").status()); + assertEquals("Approved", metrics.get("jsonNull").status()); + assertEquals("Approved", metrics.get("unprocessed").status()); + assertEquals("Approved", metrics.get("approved").status()); + assertEquals("In Review", metrics.get("inReview").status()); + assertEquals("Rejected", metrics.get("rejected").status()); + metrics.forEach((id, projection) -> assertEquals(id, projection.name())); + } + + private static String metricProjectionQuery(String metricTable, ConnectionType connectionType) { + return connectionType == ConnectionType.MYSQL + ? "SELECT id, JSON_UNQUOTE(JSON_EXTRACT(json, '$.entityStatus')) AS status, " + + "JSON_UNQUOTE(JSON_EXTRACT(json, '$.name')) AS name FROM " + + metricTable + : "SELECT id, json->>'entityStatus' AS status, json->>'name' AS name FROM " + metricTable; + } + + private static void assertMembershipIndex( + Handle handle, String tableName, String indexName, ConnectionType connectionType) { + assertTrue(indexExists(handle, tableName, indexName, connectionType)); + assertTrue(indexIsUnique(handle, tableName, indexName, connectionType)); + if (connectionType == ConnectionType.MYSQL) { + assertEquals(List.of(MEMBERSHIP_COLUMN), indexColumns(handle, tableName, indexName)); + assertTrue(isStoredGeneratedColumn(handle, tableName, MEMBERSHIP_COLUMN)); + } else { + assertPostgresPartialMembershipIndex(indexDefinition(handle, tableName, indexName)); + } + } + + private static void assertPostgresPartialMembershipIndex(String definition) { + assertNotNull(definition); + String normalized = definition.toLowerCase(Locale.ROOT); + assertTrue(normalized.contains("create unique index")); + assertTrue(normalized.contains("(toid)")); + assertTrue(normalized.contains("fromentity")); + assertTrue(normalized.contains("'metricgroup'")); + assertTrue(normalized.contains("toentity")); + assertTrue(normalized.contains("'metric'")); + assertTrue(normalized.contains("relation = 10")); + } + + static List metricSchemaStatements(MigrationScripts scripts) { + return scripts.schemaStatements().stream() + .filter(MetricMigrationTestSupport::isMetricSchemaStatement) + .toList(); + } + + private static boolean isMetricSchemaStatement(String statement) { + return statement.contains(METRIC_GROUP_TABLE) + || statement.contains(MEMBERSHIP_COLUMN) + || statement.contains(MEMBERSHIP_INDEX) + || statement.contains(MYSQL_MEMBERSHIP_COLUMN_DDL_VARIABLE) + || statement.contains(MYSQL_MEMBERSHIP_COLUMN_STATEMENT) + || statement.contains(MYSQL_MEMBERSHIP_INDEX_DDL_VARIABLE) + || statement.contains(MYSQL_MEMBERSHIP_INDEX_STATEMENT); + } + + static List metricPostStatements(MigrationScripts scripts) { + return scripts.postStatements().stream() + .filter(statement -> statement.contains("UPDATE " + METRIC_TABLE)) + .toList(); + } + + private static String fixtureStatement(String statement, MigrationFixture fixture) { + return statement + .replace(METRIC_GROUP_NAME_INDEX, fixture.groupNameIndex()) + .replace(METRIC_GROUP_DELETED_INDEX, fixture.groupDeletedIndex()) + .replace(MEMBERSHIP_INDEX, fixture.membershipIndex()) + .replace(METRIC_GROUP_TABLE, fixture.groupTable()) + .replace(RELATIONSHIP_TABLE, fixture.relationshipTable()); + } + + private static boolean tableExists( + Handle handle, String tableName, ConnectionType connectionType) { + String query = + connectionType == ConnectionType.MYSQL + ? "SELECT COUNT(*) FROM information_schema.tables " + + "WHERE table_schema = DATABASE() AND table_name = :tableName" + : "SELECT COUNT(*) FROM information_schema.tables " + + "WHERE table_schema = current_schema() AND table_name = :tableName"; + return metadataCount(handle, query, tableName, null) == 1; + } + + private static boolean indexExists( + Handle handle, String tableName, String indexName, ConnectionType connectionType) { + String query = + connectionType == ConnectionType.MYSQL + ? "SELECT COUNT(DISTINCT index_name) FROM information_schema.statistics " + + "WHERE table_schema = DATABASE() AND table_name = :tableName " + + "AND index_name = :indexName" + : "SELECT COUNT(*) FROM pg_indexes WHERE schemaname = current_schema() " + + "AND tablename = :tableName AND indexname = :indexName"; + return metadataCount(handle, query, tableName, indexName) == 1; + } + + private static boolean indexIsUnique( + Handle handle, String tableName, String indexName, ConnectionType connectionType) { + boolean result; + if (connectionType == ConnectionType.MYSQL) { + String query = + "SELECT COUNT(DISTINCT index_name) FROM information_schema.statistics " + + "WHERE table_schema = DATABASE() AND table_name = :tableName " + + "AND index_name = :indexName AND non_unique = 0"; + result = metadataCount(handle, query, tableName, indexName) == 1; + } else { + String definition = indexDefinition(handle, tableName, indexName); + result = definition != null && definition.toUpperCase(Locale.ROOT).contains("UNIQUE INDEX"); + } + return result; + } + + private static List indexColumns(Handle handle, String tableName, String indexName) { + return handle + .createQuery( + "SELECT column_name FROM information_schema.statistics " + + "WHERE table_schema = DATABASE() AND table_name = :tableName " + + "AND index_name = :indexName ORDER BY seq_in_index") + .bind("tableName", tableName) + .bind("indexName", indexName) + .mapTo(String.class) + .list(); + } + + private static boolean isStoredGeneratedColumn( + Handle handle, String tableName, String columnName) { + String extra = + handle + .createQuery( + "SELECT extra FROM information_schema.columns " + + "WHERE table_schema = DATABASE() AND table_name = :tableName " + + "AND column_name = :columnName") + .bind("tableName", tableName) + .bind("columnName", columnName) + .mapTo(String.class) + .one(); + return extra.toUpperCase(Locale.ROOT).contains("STORED GENERATED"); + } + + private static String indexDefinition(Handle handle, String tableName, String indexName) { + return handle + .createQuery( + "SELECT indexdef FROM pg_indexes WHERE schemaname = current_schema() " + + "AND tablename = :tableName AND indexname = :indexName") + .bind("tableName", tableName) + .bind("indexName", indexName) + .mapTo(String.class) + .findOne() + .orElse(null); + } + + private static int metadataCount( + Handle handle, String query, String tableName, String indexName) { + var queryHandle = handle.createQuery(query).bind("tableName", tableName); + if (indexName != null) { + queryHandle.bind("indexName", indexName); + } + return queryHandle.mapTo(Integer.class).one(); + } + + private static int countRows(Handle handle, String tableName) { + return handle.createQuery("SELECT COUNT(*) FROM " + tableName).mapTo(Integer.class).one(); + } + + private static void dropFixture(Jdbi jdbi, MigrationFixture fixture) { + jdbi.useHandle( + handle -> { + handle.execute("DROP TABLE IF EXISTS " + fixture.metricTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.groupTable()); + handle.execute("DROP TABLE IF EXISTS " + fixture.relationshipTable()); + }); + } + + private record MigrationFixture( + String groupTable, + String relationshipTable, + String metricTable, + String groupNameIndex, + String groupDeletedIndex, + String membershipIndex) { + private static MigrationFixture create() { + String suffix = UUID.randomUUID().toString().replace("-", "").substring(0, 12); + return new MigrationFixture( + "it_metric_group_" + suffix, + "it_metric_relationship_" + suffix, + "it_metric_status_" + suffix, + "it_mg_name_" + suffix, + "it_mg_deleted_" + suffix, + "it_mg_member_" + suffix); + } + } + + private record MetricProjection(String id, String status, String name) {} + + private record GroupFixture( + String id, String name, String fqnHash, long updatedAt, String updatedBy) {} + + private record GroupProjection( + String id, String name, long updatedAt, String updatedBy, boolean deleted) {} + + record IndexExpectation(String table, String name) {} +} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricResourceIT.java index 4b09d438094d..d43bbc72395c 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/MetricResourceIT.java @@ -11,38 +11,97 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.Response; import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; import org.openmetadata.it.bootstrap.SharedEntities; import org.openmetadata.it.bootstrap.TestSuiteBootstrap; +import org.openmetadata.it.factories.DashboardServiceTestFactory; import org.openmetadata.it.factories.GlossaryTermTestFactory; import org.openmetadata.it.factories.GlossaryTestFactory; +import org.openmetadata.it.factories.ShortStackFactory; import org.openmetadata.it.util.RdfTestUtils; import org.openmetadata.it.util.SdkClients; import org.openmetadata.it.util.TestNamespace; +import org.openmetadata.schema.alert.type.EmailAlertConfig; +import org.openmetadata.schema.api.data.CreateDashboard; import org.openmetadata.schema.api.data.CreateMetric; +import org.openmetadata.schema.api.data.CreateMetricGroup; +import org.openmetadata.schema.api.data.MetricDimension; import org.openmetadata.schema.api.data.MetricExpression; +import org.openmetadata.schema.api.data.MetricMeasure; +import org.openmetadata.schema.api.events.CreateEventSubscription; +import org.openmetadata.schema.api.lineage.AddLineage; +import org.openmetadata.schema.api.policies.CreatePolicy; +import org.openmetadata.schema.api.tasks.ResolveTask; +import org.openmetadata.schema.api.teams.CreateRole; +import org.openmetadata.schema.api.teams.CreateUser; +import org.openmetadata.schema.api.tests.CreateTestCaseResult; +import org.openmetadata.schema.api.tests.CreateTestDefinition; +import org.openmetadata.schema.entity.data.Dashboard; import org.openmetadata.schema.entity.data.Glossary; import org.openmetadata.schema.entity.data.GlossaryTerm; import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.entity.data.Table; +import org.openmetadata.schema.entity.events.EventSubscription; +import org.openmetadata.schema.entity.events.SubscriptionDestination; +import org.openmetadata.schema.entity.policies.Policy; +import org.openmetadata.schema.entity.policies.accessControl.Rule; +import org.openmetadata.schema.entity.services.DashboardService; +import org.openmetadata.schema.entity.tasks.Task; +import org.openmetadata.schema.entity.teams.Role; +import org.openmetadata.schema.entity.teams.User; +import org.openmetadata.schema.tests.TestCase; +import org.openmetadata.schema.tests.TestDefinition; +import org.openmetadata.schema.tests.TestPlatform; +import org.openmetadata.schema.tests.type.Severity; +import org.openmetadata.schema.tests.type.TestCaseResolutionStatus; +import org.openmetadata.schema.tests.type.TestCaseStatus; +import org.openmetadata.schema.type.ApiStatus; +import org.openmetadata.schema.type.ColumnLineage; +import org.openmetadata.schema.type.DataQualityDimensions; +import org.openmetadata.schema.type.Edge; +import org.openmetadata.schema.type.EntitiesEdge; import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityLineage; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.EntityStatus; +import org.openmetadata.schema.type.LineageDetails; +import org.openmetadata.schema.type.MetadataOperation; import org.openmetadata.schema.type.MetricExpressionLanguage; import org.openmetadata.schema.type.MetricGranularity; import org.openmetadata.schema.type.MetricType; import org.openmetadata.schema.type.MetricUnitOfMeasurement; +import org.openmetadata.schema.type.Relationship; import org.openmetadata.schema.type.TagLabel; +import org.openmetadata.schema.type.TaskCategory; +import org.openmetadata.schema.type.TaskEntityStatus; +import org.openmetadata.schema.type.TaskResolutionType; +import org.openmetadata.schema.type.TestDefinitionEntityType; +import org.openmetadata.schema.type.api.BulkAssets; import org.openmetadata.schema.type.api.BulkOperationResult; import org.openmetadata.schema.type.csv.CsvImportResult; +import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.sdk.client.OpenMetadataClient; +import org.openmetadata.sdk.exceptions.OpenMetadataException; +import org.openmetadata.sdk.fluent.builders.TestCaseBuilder; import org.openmetadata.sdk.models.ListParams; import org.openmetadata.sdk.models.ListResponse; import org.openmetadata.sdk.network.HttpMethod; +import org.openmetadata.service.Entity; +import org.openmetadata.service.jdbi3.CollectionDAO; /** * Integration tests for Metric entity operations. @@ -54,6 +113,16 @@ */ @Execution(ExecutionMode.CONCURRENT) public class MetricResourceIT extends BaseEntityIT { + private static final String METRIC_CSV_HEADER = + "name*,displayName,description,metricType,unitOfMeasurement,customUnitOfMeasurement," + + "granularity,expressionLanguage,expressionCode,relatedMetrics,tags,glossaryTerms," + + "tiers,owners,reviewers,domains,dataProducts,entityStatus,extension,parent,experts," + + "metricGroup"; + + private static final String HIERARCHY_FIELDS = "parent,children,childrenCount"; + private static final String RESTRICTED_TAG_FQN = "PII.Sensitive"; + + private static final ObjectMapper JSON = new ObjectMapper(); { supportsListHistoryByTimestamp = true; @@ -108,7 +177,7 @@ protected void restoreEntity(String id) { @Override protected void hardDeleteEntity(String id) { - java.util.Map params = new java.util.HashMap<>(); + Map params = new HashMap<>(); params.put("hardDelete", "true"); SdkClients.adminClient().metrics().delete(id, params); } @@ -161,6 +230,46 @@ protected Metric getVersion(UUID id, Double version) { return SdkClients.adminClient().metrics().getVersion(id.toString(), version); } + @Test + void metricExpertsPersistUpdateAppearInHierarchyAndRequireEditPermission(TestNamespace ns) { + SharedEntities shared = SharedEntities.get(); + Metric created = + createEntity( + createRequest(ns.prefix("metric_experts"), ns) + .withExperts(List.of(shared.USER1_REF.getFullyQualifiedName()))); + + Metric fetched = getEntityWithFields(created.getId().toString(), "experts"); + assertEquals(1, fetched.getExperts().size()); + assertEquals(shared.USER1_REF.getId(), fetched.getExperts().getFirst().getId()); + + fetched.setExperts(List.of(shared.USER2_REF)); + Metric updated = patchEntity(fetched.getId().toString(), fetched); + assertEquals(shared.USER2_REF.getId(), updated.getExperts().getFirst().getId()); + assertEquals( + shared.USER2_REF.getId(), + getEntityWithFields(created.getId().toString(), "experts").getExperts().getFirst().getId()); + + JsonNode hierarchy = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + created.getName(), + null, + Object.class)); + assertEquals( + shared.USER2_REF.getId().toString(), + hierarchy.get("data").get(0).get("metric").get("experts").get(0).get("id").asText()); + + Metric forbidden = + SdkClients.user2Client().metrics().get(created.getId().toString(), "experts"); + forbidden.setExperts(List.of(shared.USER1_REF)); + assertApiStatus( + 403, + () -> SdkClients.user2Client().metrics().update(created.getId().toString(), forbidden)); + } + @Test void test_metricGlossaryTermRdfLink(TestNamespace ns) { assumeTrue( @@ -226,12 +335,18 @@ void post_metricWithExpression_200_OK(TestNamespace ns) { @Test void put_metricCsvImportExport_200_OK(TestNamespace ns) throws Exception { OpenMetadataClient client = SdkClients.adminClient(); + SharedEntities shared = SharedEntities.get(); + MetricGroup group = + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metricGroups", + new CreateMetricGroup().withName(ns.prefix("metric_csv_group")), + MetricGroup.class); String metricName = ns.prefix("metric_csv"); String secondMetricName = ns.prefix("metric_csv_second"); - String header = - "name*,displayName,description,metricType,unitOfMeasurement,customUnitOfMeasurement," - + "granularity,expressionLanguage,expressionCode,relatedMetrics,tags,glossaryTerms," - + "tiers,owners,reviewers,domains,dataProducts,entityStatus,extension"; + String header = METRIC_CSV_HEADER; String row = String.join( ",", @@ -253,7 +368,10 @@ void put_metricCsvImportExport_200_OK(TestNamespace ns) throws Exception { "", "", "Approved", - ""); + "", + "", + shared.USER1_REF.getFullyQualifiedName(), + group.getFullyQualifiedName()); String secondRow = String.join( ",", @@ -275,6 +393,9 @@ void put_metricCsvImportExport_200_OK(TestNamespace ns) throws Exception { "", "", "Approved", + "", + "", + "", ""); String csv = header + "\n" + row + "\n" + secondRow + "\n"; @@ -283,7 +404,9 @@ void put_metricCsvImportExport_200_OK(TestNamespace ns) throws Exception { .readValue(client.metrics().importCsv("*", csv, false), CsvImportResult.class); assertEquals(2, result.getNumberOfRowsPassed(), result.getImportResultsCsv()); - Metric imported = getEntityByName(metricName); + Metric imported = getEntityByNameWithFields(metricName, "experts,metricGroup"); + assertEquals(shared.USER1_REF.getId(), imported.getExperts().getFirst().getId()); + assertEquals(group.getId(), imported.getMetricGroup().getId()); assertNotNull(imported); assertEquals(MetricExpressionLanguage.SQL, imported.getMetricExpression().getLanguage()); Metric secondImported = getEntityByName(secondMetricName); @@ -654,6 +777,61 @@ void test_getCustomUnitsAPI(TestNamespace ns) throws Exception { assertEquals(1, euroCount, "EURO should appear only once in the distinct list"); } + @Test + void getCustomUnitsRequiresMetricViewPermission(TestNamespace ns) { + OpenMetadataClient admin = SdkClients.adminClient(); + String suffix = ns.uniqueShortId(); + Rule denyMetricView = + new Rule() + .withName("DenyMetricView") + .withResources(List.of(Entity.METRIC)) + .withOperations(List.of(MetadataOperation.VIEW_BASIC)) + .withEffect(Rule.Effect.DENY); + Policy policy = + admin + .policies() + .create( + new CreatePolicy() + .withName("metricCustomUnitPolicy_" + suffix) + .withRules(List.of(denyMetricView))); + try { + Role role = + admin + .roles() + .create( + new CreateRole() + .withName("metricCustomUnitRole_" + suffix) + .withPolicies(List.of(policy.getFullyQualifiedName()))); + try { + String email = "metric-custom-unit-" + suffix + "@test.openmetadata.org"; + User user = + admin + .users() + .create( + new CreateUser() + .withName("metric-custom-unit-" + suffix) + .withEmail(email) + .withRoles(List.of(role.getId()))); + try { + OpenMetadataClient restricted = SdkClients.createClient(email, email, new String[] {}); + + assertApiStatus( + Response.Status.FORBIDDEN.getStatusCode(), + () -> + restricted + .getHttpClient() + .execute(HttpMethod.GET, "/v1/metrics/customUnits", null, List.class)); + } finally { + admin.users().delete(user.getId()); + } + } finally { + admin.roles().delete(role.getId()); + } + } finally { + admin.policies().delete(policy.getId()); + } + } + @Test void test_customUnitTrimming(TestNamespace ns) { OpenMetadataClient client = SdkClients.adminClient(); @@ -685,8 +863,7 @@ void test_reviewersUpdateAndPatch(TestNamespace ns) { metric.getReviewers() == null || metric.getReviewers().isEmpty(), "Metric should have no reviewers initially"); - metric.setReviewers(List.of(shared.USER1_REF)); - Metric updatedMetric = patchEntity(metric.getId().toString(), metric); + Metric updatedMetric = patchMetricReviewers(metric.getId(), List.of(shared.USER1_REF)); assertNotNull(updatedMetric.getReviewers(), "Metric should have reviewers after update"); assertEquals(1, updatedMetric.getReviewers().size(), "Metric should have one reviewer"); @@ -704,8 +881,7 @@ void test_reviewersUpdateAndPatch(TestNamespace ns) { retrievedMetric.getReviewers().get(0).getId(), "Retrieved reviewer should match USER1"); - updatedMetric.setReviewers(List.of(shared.USER2_REF)); - updatedMetric = patchEntity(updatedMetric.getId().toString(), updatedMetric); + updatedMetric = patchMetricReviewers(updatedMetric.getId(), List.of(shared.USER2_REF)); assertEquals(1, updatedMetric.getReviewers().size(), "Metric should still have one reviewer"); assertEquals( @@ -713,8 +889,8 @@ void test_reviewersUpdateAndPatch(TestNamespace ns) { updatedMetric.getReviewers().get(0).getId(), "Reviewer should now be USER2"); - updatedMetric.setReviewers(List.of(shared.USER2_REF, shared.USER1_REF)); - updatedMetric = patchEntity(updatedMetric.getId().toString(), updatedMetric); + updatedMetric = + patchMetricReviewers(updatedMetric.getId(), List.of(shared.USER2_REF, shared.USER1_REF)); assertEquals(2, updatedMetric.getReviewers().size(), "Metric should have two reviewers"); assertTrue( @@ -727,10 +903,21 @@ void test_reviewersUpdateAndPatch(TestNamespace ns) { "Should contain USER2 as reviewer"); } - @Test - void test_entityStatusUpdateAndPatch(TestNamespace ns) { - OpenMetadataClient client = SdkClients.adminClient(); + private Metric patchMetricReviewers(UUID metricId, List reviewers) { + JsonNode patch = + JSON.createArrayNode() + .add( + JSON.createObjectNode() + .put("op", "add") + .put("path", "/reviewers") + .set("value", JSON.valueToTree(reviewers))); + SdkClients.adminClient().metrics().patch(metricId, patch); + return getEntityWithFields(metricId.toString(), "reviewers"); + } + @Test + @Override + void test_entityStatus(TestNamespace ns) { CreateMetric createMetric = new CreateMetric() .withName(ns.prefix("metric_entity_status")) @@ -738,9 +925,9 @@ void test_entityStatusUpdateAndPatch(TestNamespace ns) { Metric metric = createEntity(createMetric); assertEquals( - EntityStatus.UNPROCESSED, + EntityStatus.APPROVED, metric.getEntityStatus(), - "Metric should be created with UNPROCESSED status"); + "A Metric without reviewers should be created Approved"); metric.setEntityStatus(EntityStatus.IN_REVIEW); Metric updatedMetric = patchEntity(metric.getId().toString(), metric); @@ -810,10 +997,2242 @@ void test_searchMetricWithLongName_doesNotCauseClauseExplosion(TestNamespace ns) "Searching for a metric with a long multi-word name should not cause clause explosion"); } + // =================================================================== + // HIERARCHY + // =================================================================== + + private Metric createChild(TestNamespace ns, String name, Metric parent) { + return createEntity( + new CreateMetric() + .withName(ns.prefix(name)) + .withDescription("Child metric") + .withParent(parent.getFullyQualifiedName())); + } + + private Metric getWithHierarchy(Metric metric) { + return getEntityWithFields(metric.getId().toString(), HIERARCHY_FIELDS); + } + + private ListResponse listByParent(String parent) { + return listEntities( + new ListParams().setParent(parent).setFields(HIERARCHY_FIELDS).setLimit(1000)); + } + + private static boolean containsMetric(ListResponse response, Metric metric) { + return response.getData().stream().anyMatch(m -> m.getId().equals(metric.getId())); + } + + @Test + void post_metricWithParent_establishesHierarchy(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("hier_parent"), ns)); + Metric child = createChild(ns, "hier_child", parent); + + assertNotNull(child.getParent(), "Child should carry its parent reference on create"); + assertEquals(parent.getId(), child.getParent().getId()); + + Metric fetchedChild = getWithHierarchy(child); + assertEquals(parent.getId(), fetchedChild.getParent().getId()); + assertEquals(0, fetchedChild.getChildrenCount()); + + Metric fetchedParent = getWithHierarchy(parent); + assertNull(fetchedParent.getParent(), "Root metric should have no parent"); + assertEquals(1, fetchedParent.getChildrenCount()); + assertEquals(1, fetchedParent.getChildren().size()); + assertEquals(child.getId(), fetchedParent.getChildren().get(0).getId()); + } + + @Test + void hierarchyWritesRequireEditPermissionOnParentAndGroupDestinations(TestNamespace ns) { + OpenMetadataClient admin = SdkClients.adminClient(); + Metric source = createEntity(createRequest(ns.prefix("destination_source"), ns)); + Metric sourceChild = createChild(ns, "destination_source_child", source); + Metric restrictedParent = + createEntity( + createRequest(ns.prefix("destination_parent"), ns) + .withTags(List.of(new TagLabel().withTagFQN(RESTRICTED_TAG_FQN)))); + MetricGroup restrictedGroup = + admin + .getHttpClient() + .execute( + HttpMethod.POST, + "/v1/metricGroups", + new CreateMetricGroup() + .withName(ns.prefix("destination_group")) + .withTags(List.of(new TagLabel().withTagFQN(RESTRICTED_TAG_FQN))) + .withMetrics(List.of(restrictedParent.getFullyQualifiedName())), + MetricGroup.class); + String unauthorizedPostName = ns.prefix("destination_post"); + String unauthorizedPutName = ns.prefix("destination_put"); + + withRestrictedHierarchyDestinationEditor( + ns, + editor -> { + assertApiStatus( + 403, + () -> + editor + .metrics() + .create( + createRequest(unauthorizedPostName, ns) + .withParent(restrictedParent.getFullyQualifiedName()))); + assertApiStatus( + 403, + () -> + editor + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics", + createRequest(unauthorizedPutName, ns) + .withMetricGroup(restrictedGroup.getFullyQualifiedName()), + Metric.class)); + + Metric parentPatch = + editor.metrics().get(source.getId().toString(), "parent,metricGroup"); + parentPatch.setParent(restrictedParent.getEntityReference()); + assertApiStatus( + 403, () -> editor.metrics().update(source.getId().toString(), parentPatch)); + + Metric groupPatch = editor.metrics().get(source.getId().toString(), "parent,metricGroup"); + groupPatch.setMetricGroup(restrictedGroup.getEntityReference()); + assertApiStatus( + 403, () -> editor.metrics().update(source.getId().toString(), groupPatch)); + + JsonNode directParentPatch = + JSON.createArrayNode() + .add( + JSON.createObjectNode() + .put("op", "add") + .put("path", "/parent") + .set("value", JSON.valueToTree(restrictedParent.getEntityReference()))); + assertApiStatus(403, () -> editor.metrics().patch(source.getId(), directParentPatch)); + assertNull(admin.metrics().get(source.getId().toString(), "parent").getParent()); + + JsonNode directGroupPatch = + JSON.createArrayNode() + .add( + JSON.createObjectNode() + .put("op", "add") + .put("path", "/metricGroup") + .set("value", JSON.valueToTree(restrictedGroup.getEntityReference()))); + assertApiStatus(403, () -> editor.metrics().patch(source.getId(), directGroupPatch)); + assertNull( + admin.metrics().get(source.getId().toString(), "metricGroup").getMetricGroup()); + + assertApiStatus( + 403, + () -> + editor + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics", + createRequest(source.getName(), ns) + .withParent(restrictedParent.getFullyQualifiedName()), + Metric.class)); + assertApiStatus( + 403, + () -> + editor + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics", + createRequest(source.getName(), ns) + .withMetricGroup(restrictedGroup.getFullyQualifiedName()), + Metric.class)); + }); + + assertApiStatus(404, () -> admin.metrics().getByName(unauthorizedPostName)); + assertApiStatus(404, () -> admin.metrics().getByName(unauthorizedPutName)); + Metric unchanged = admin.metrics().get(source.getId().toString(), "parent,metricGroup"); + Metric unchangedChild = + admin.metrics().get(sourceChild.getId().toString(), "parent,metricGroup"); + assertNull(unchanged.getParent()); + assertNull(unchanged.getMetricGroup()); + assertEquals(source.getId(), unchangedChild.getParent().getId()); + assertNull(unchangedChild.getMetricGroup()); + } + + @Test + void post_metricParentedToItself_400(TestNamespace ns) { + String name = ns.prefix("hier_self"); + Exception error = + assertThrows( + Exception.class, + () -> + createEntity( + new CreateMetric() + .withName(name) + .withDescription("Self-parented metric") + .withParent(name))); + assertTrue(error.getMessage().contains("cannot be its own parent")); + } + + @Test + void patch_metricDirectCycle_400(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("cycle_a"), ns)); + Metric child = createChild(ns, "cycle_b", parent); + + // parent already CONTAINS child, so making child the parent's parent closes a 2-node cycle + Metric reparented = getWithHierarchy(parent); + reparented.setParent(child.getEntityReference()); + Exception error = + assertThrows(Exception.class, () -> patchEntity(reparented.getId().toString(), reparented)); + assertTrue(error.getMessage().contains("Circular reference detected")); + } + + @Test + void patch_metricTransitiveCycle_400(TestNamespace ns) { + Metric grandParent = createEntity(createRequest(ns.prefix("cycle_gp"), ns)); + Metric parent = createChild(ns, "cycle_p", grandParent); + Metric child = createChild(ns, "cycle_c", parent); + + // grandParent -> parent -> child; pointing grandParent at child closes a 3-node cycle + Metric reparented = getWithHierarchy(grandParent); + reparented.setParent(child.getEntityReference()); + Exception error = + assertThrows(Exception.class, () -> patchEntity(reparented.getId().toString(), reparented)); + assertTrue(error.getMessage().contains("Circular reference detected")); + } + + @Test + void patch_metricReparent_movesEdgeAndKeepsFqn(TestNamespace ns) { + Metric oldParent = createEntity(createRequest(ns.prefix("move_old"), ns)); + Metric newParent = createEntity(createRequest(ns.prefix("move_new"), ns)); + Metric child = createChild(ns, "move_child", oldParent); + String originalFqn = child.getFullyQualifiedName(); + + Metric toMove = getWithHierarchy(child); + toMove.setParent(newParent.getEntityReference()); + Metric moved = patchEntity(toMove.getId().toString(), toMove); + + assertEquals( + originalFqn, + moved.getFullyQualifiedName(), + "Reparenting must not rewrite the metric's fully qualified name"); + assertEquals(newParent.getId(), moved.getParent().getId()); + assertEquals(0, getWithHierarchy(oldParent).getChildrenCount()); + assertEquals(1, getWithHierarchy(newParent).getChildrenCount()); + } + + @Test + void patch_metricClearParent_makesItRoot(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("clear_parent"), ns)); + Metric child = createChild(ns, "clear_child", parent); + + Metric toDetach = getWithHierarchy(child); + toDetach.setParent(null); + Metric detached = patchEntity(toDetach.getId().toString(), toDetach); + + assertNull(detached.getParent(), "Clearing parent should make the metric a root"); + assertEquals(0, getWithHierarchy(parent).getChildrenCount()); + assertTrue(containsMetric(listByParent("null"), detached)); + } + + @Test + void patch_metricChildrenAreReadOnly(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("frozen_parent"), ns)); + Metric child = createChild(ns, "frozen_child", parent); + Metric other = createEntity(createRequest(ns.prefix("frozen_other"), ns)); + + JsonNode patch = + JSON.createArrayNode() + .add( + JSON.createObjectNode() + .put("op", "add") + .put("path", "/children") + .set("value", JSON.valueToTree(List.of(other.getEntityReference())))); + assertApiStatus(400, () -> SdkClients.adminClient().metrics().patch(parent.getId(), patch)); + + Metric refetched = getWithHierarchy(parent); + assertEquals(1, refetched.getChildrenCount(), "childrenCount must stay derived from edges"); + assertEquals(1, refetched.getChildren().size()); + assertEquals( + child.getId(), + refetched.getChildren().get(0).getId(), + "Patching children must not rewire the hierarchy"); + } + + @Test + void delete_metricWithChildren_400_thenRecursiveSucceeds(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("del_parent"), ns)); + createChild(ns, "del_child", parent); + + assertThrows( + Exception.class, + () -> deleteEntity(parent.getId().toString()), + "Deleting a metric that still has children must fail without recursive=true"); + + Map params = new HashMap<>(); + params.put("recursive", "true"); + params.put("hardDelete", "true"); + assertDoesNotThrow( + () -> SdkClients.adminClient().metrics().delete(parent.getId().toString(), params)); + } + + @Test + void get_softDeletedChildExcludedFromChildrenCount(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("soft_parent"), ns)); + Metric child = createChild(ns, "soft_child", parent); + assertEquals(1, getWithHierarchy(parent).getChildrenCount()); + + deleteEntity(child.getId().toString()); + + assertEquals( + 0, getWithHierarchy(parent).getChildrenCount(), "A soft-deleted child must not be counted"); + } + + @Test + void list_parentNull_returnsRootsOnly(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("roots_parent"), ns)); + Metric child = createChild(ns, "roots_child", parent); + + ListResponse roots = listByParent("null"); + assertTrue(containsMetric(roots, parent), "A metric with no parent is a root"); + assertFalse(containsMetric(roots, child), "A child metric must not be listed as a root"); + } + + @Test + void list_parentFqn_returnsImmediateChildrenOnly(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("imm_parent"), ns)); + Metric child = createChild(ns, "imm_child", parent); + Metric grandChild = createChild(ns, "imm_grandchild", child); + + ListResponse children = listByParent(parent.getFullyQualifiedName()); + assertTrue(containsMetric(children, child)); + assertFalse( + containsMetric(children, grandChild), + "parent={fqn} must return immediate children, not the whole subtree"); + assertFalse(containsMetric(children, parent)); + } + + @Test + void list_withoutParentParam_returnsBothRootsAndChildren(TestNamespace ns) { + Metric parent = createEntity(createRequest(ns.prefix("flat_parent"), ns)); + Metric child = createChild(ns, "flat_child", parent); + + ListResponse all = + listEntities(new ListParams().setFields(HIERARCHY_FIELDS).setLimit(1000)); + assertTrue(containsMetric(all, parent), "Legacy unfiltered listing must be unchanged"); + assertTrue(containsMetric(all, child), "Legacy unfiltered listing must include children"); + } + + @Test + void get_hierarchySearchByChildReturnsNavigableRoot(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric root = createEntity(createRequest(ns.prefix("search_root"), ns)); + Metric child = createChild(ns, "search_nested_variant", root); + + JsonNode response = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + child.getName() + "&limit=1&offset=0", + null, + Object.class)); + + assertEquals(1, response.get("paging").get("total").asInt()); + assertEquals("metric", response.get("data").get(0).get("kind").asText()); + assertEquals( + root.getId().toString(), response.get("data").get(0).get("metric").get("id").asText()); + assertFalse(response.get("data").get(0).has("group")); + } + + @Test + void get_hierarchySearchMatchesStandaloneDisplayName(TestNamespace ns) { + Metric metric = + createEntity( + createRequest(ns.prefix("display_name_root"), ns) + .withDisplayName("Friendly Conversion Metric")); + + JsonNode response = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=Conversion&limit=10&offset=0", + null, + Object.class)); + + assertEquals(1, response.get("paging").get("total").asInt()); + assertEquals( + metric.getId().toString(), response.get("data").get(0).get("metric").get("id").asText()); + } + + @Test + void get_metricHierarchyContextPagesAncestorsSiblingsAndChildren(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric root = createEntity(createRequest(ns.prefix("context_root"), ns)); + Metric current = createChild(ns, "context_current", root); + createChild(ns, "context_sibling", root); + Metric child = createChild(ns, "context_child", current); + + JsonNode context = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + + current.getId() + + "/hierarchy?childLimit=1&childOffset=0&siblingLimit=1&siblingOffset=0", + null, + Object.class)); + + assertEquals(current.getId().toString(), context.get("current").get("id").asText()); + assertEquals(root.getId().toString(), context.get("ancestors").get(0).get("id").asText()); + assertEquals(child.getId().toString(), context.get("children").get(0).get("id").asText()); + assertEquals(1, context.get("childrenPaging").get("total").asInt()); + assertEquals(1, context.get("siblingPaging").get("total").asInt()); + + JsonNode childrenOnly = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + + current.getId() + + "/hierarchy?childLimit=1&childOffset=0&siblingLimit=0&siblingOffset=0", + null, + Object.class)); + assertEquals(1, childrenOnly.get("children").size()); + assertEquals(0, childrenOnly.get("siblings").size()); + assertEquals(1, childrenOnly.get("siblingPaging").get("total").asInt()); + + JsonNode siblingsOnly = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + + current.getId() + + "/hierarchy?childLimit=0&childOffset=0&siblingLimit=1&siblingOffset=0", + null, + Object.class)); + assertEquals(0, siblingsOnly.get("children").size()); + assertEquals(1, siblingsOnly.get("siblings").size()); + assertEquals(1, siblingsOnly.get("childrenPaging").get("total").asInt()); + } + + @Test + void hierarchyEndpointsFilterAndSanitizeEveryRestrictedMetricReference(TestNamespace ns) { + OpenMetadataClient admin = SdkClients.adminClient(); + TagLabel restrictedTag = new TagLabel().withTagFQN("PII.Sensitive"); + Metric restrictedParent = + createEntity( + createRequest(ns.prefix("rbac_00_restricted_parent"), ns) + .withTags(List.of(restrictedTag))); + Metric current = createChild(ns, "rbac_01_current", restrictedParent); + Metric restrictedSibling = + createEntity( + createRequest(ns.prefix("rbac_02_restricted_sibling"), ns) + .withParent(restrictedParent.getFullyQualifiedName()) + .withTags(List.of(restrictedTag))); + Metric visibleSibling = createChild(ns, "rbac_03_visible_sibling", restrictedParent); + Metric restrictedChild = + createEntity( + createRequest(ns.prefix("rbac_04_restricted_child"), ns) + .withParent(current.getFullyQualifiedName()) + .withTags(List.of(restrictedTag))); + Metric visibleChild = createChild(ns, "rbac_05_visible_child", current); + MetricGroup visibleGroup = + admin + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metricGroups", + new CreateMetricGroup() + .withName(ns.prefix("rbac_visible_group")) + .withMetrics(List.of(restrictedParent.getFullyQualifiedName())), + MetricGroup.class); + Metric visibleMetricInRestrictedGroup = + createEntity(createRequest(ns.prefix("rbac_visible_in_hidden_group"), ns)); + MetricGroup restrictedGroup = + admin + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metricGroups", + new CreateMetricGroup() + .withName(ns.prefix("rbac_restricted_group")) + .withTags(List.of(restrictedTag)) + .withMetrics(List.of(visibleMetricInRestrictedGroup.getFullyQualifiedName())), + MetricGroup.class); + Metric allowedBulkRoot = createEntity(createRequest(ns.prefix("rbac_allowed_bulk_root"), ns)); + + Rule allowCatalog = + new Rule() + .withName("AllowCatalog") + .withResources(List.of("All")) + .withOperations( + List.of( + MetadataOperation.VIEW_BASIC, + MetadataOperation.VIEW_ALL, + MetadataOperation.EDIT_ALL)) + .withEffect(Rule.Effect.ALLOW); + Rule denyRestricted = + new Rule() + .withName("DenyRestrictedMetrics") + .withResources(List.of("metric", "metricGroup")) + .withOperations( + List.of( + MetadataOperation.VIEW_BASIC, + MetadataOperation.VIEW_ALL, + MetadataOperation.EDIT_ALL)) + .withCondition("matchAnyTag('PII.Sensitive')") + .withEffect(Rule.Effect.DENY); + String suffix = ns.uniqueShortId(); + Policy policy = + admin + .policies() + .create( + new CreatePolicy() + .withName("metricHierarchyPolicy_" + suffix) + .withRules(List.of(allowCatalog, denyRestricted))); + try { + Role role = + admin + .roles() + .create( + new CreateRole() + .withName("metricHierarchyRole_" + suffix) + .withPolicies(List.of(policy.getFullyQualifiedName()))); + try { + String email = "metric-hierarchy-" + suffix + "@test.openmetadata.org"; + User user = + admin + .users() + .create( + new CreateUser() + .withName("metric-hierarchy-" + suffix) + .withEmail(email) + .withRoles(List.of(role.getId()))); + try { + OpenMetadataClient restricted = SdkClients.createClient(email, email, new String[] {}); + assertApiStatus(403, () -> restricted.metrics().get(restrictedParent.getId().toString())); + assertApiStatus( + 403, + () -> + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + restrictedParent.getId() + "/observability", + null, + Object.class)); + assertApiStatus( + 403, + () -> + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metricGroups/" + restrictedGroup.getId(), + null, + Object.class)); + + JsonNode context = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + + current.getId() + + "/hierarchy?childLimit=10&childOffset=0&siblingLimit=10&siblingOffset=0", + null, + Object.class)); + assertEquals(0, context.get("ancestors").size()); + assertEquals(1, context.get("childrenPaging").get("total").asInt()); + assertEquals(1, context.get("current").get("childrenCount").asInt()); + assertEquals(3, context.get("group").get("metricCount").asInt()); + assertEquals( + visibleChild.getId().toString(), context.get("children").get(0).get("id").asText()); + assertEquals(1, context.get("siblingPaging").get("total").asInt()); + assertEquals( + visibleSibling.getId().toString(), context.get("siblings").get(0).get("id").asText()); + assertTrue( + context.get("current").path("parent").isMissingNode() + || context.get("current").path("parent").isNull()); + assertRestrictedNamesAbsent( + context, restrictedParent, restrictedSibling, restrictedChild, restrictedGroup); + + JsonNode restrictedGroupContext = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + + visibleMetricInRestrictedGroup.getId() + + "/hierarchy?childLimit=0&siblingLimit=0", + null, + Object.class)); + assertTrue( + restrictedGroupContext.path("group").isMissingNode() + || restrictedGroupContext.path("group").isNull()); + assertTrue( + restrictedGroupContext.get("current").path("metricGroup").isMissingNode() + || restrictedGroupContext.get("current").path("metricGroup").isNull()); + assertRestrictedNamesAbsent(restrictedGroupContext, restrictedGroup); + + JsonNode genericGroup = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metricGroups/" + visibleGroup.getId() + "?fields=*", + null, + Object.class)); + assertTrue( + genericGroup.path("metrics").isMissingNode() + || genericGroup.path("metrics").isNull()); + assertRestrictedNamesAbsent( + genericGroup, restrictedParent, restrictedSibling, restrictedChild); + assertApiStatus( + 400, + () -> + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metricGroups/" + visibleGroup.getId() + "?fields=metrics", + null, + Object.class)); + + JsonNode members = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metricGroups/" + visibleGroup.getId() + "/metrics?limit=1&offset=0", + null, + Object.class)); + assertEquals(3, members.get("paging").get("total").asInt()); + assertEquals(current.getId().toString(), members.get("data").get(0).get("id").asText()); + assertEquals(1, members.get("data").get(0).get("childrenCount").asInt()); + assertTrue( + members.get("data").get(0).path("parent").isMissingNode() + || members.get("data").get(0).path("parent").isNull()); + assertRestrictedNamesAbsent( + members, restrictedParent, restrictedSibling, restrictedChild, restrictedGroup); + + JsonNode hiddenSearch = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + + restrictedSibling.getName() + + "&limit=10&offset=0", + null, + Object.class)); + assertEquals(0, hiddenSearch.get("paging").get("total").asInt()); + assertRestrictedNamesAbsent( + hiddenSearch, restrictedParent, restrictedSibling, restrictedChild, restrictedGroup); + + JsonNode hiddenGroupSearch = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + + visibleMetricInRestrictedGroup.getName() + + "&limit=10&offset=0", + null, + Object.class)); + assertEquals(0, hiddenGroupSearch.get("paging").get("total").asInt()); + assertRestrictedNamesAbsent(hiddenGroupSearch, restrictedGroup); + + String hierarchyScope = current.getName().substring(current.getName().indexOf("__")); + JsonNode visibleSecondPage = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/hierarchy?q=" + hierarchyScope + "&limit=1&offset=1", + null, + Object.class)); + assertEquals(2, visibleSecondPage.get("paging").get("total").asInt()); + assertEquals( + visibleGroup.getId().toString(), + visibleSecondPage.get("data").get(0).get("group").get("id").asText()); + assertEquals( + 3, visibleSecondPage.get("data").get(0).get("group").get("metricCount").asInt()); + assertTrue( + visibleSecondPage.get("data").get(0).get("group").path("metrics").isMissingNode() + || visibleSecondPage.get("data").get(0).get("group").path("metrics").isNull()); + assertRestrictedNamesAbsent( + visibleSecondPage, + restrictedParent, + restrictedSibling, + restrictedChild, + restrictedGroup); + + JsonNode bulk = + JSON.valueToTree( + restricted + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metricGroups/" + visibleGroup.getName() + "/metrics/add", + new BulkAssets() + .withAssets( + List.of( + restrictedParent.getEntityReference(), + allowedBulkRoot.getEntityReference())), + Object.class)); + assertEquals(1, bulk.get("numberOfRowsPassed").asInt()); + assertEquals(1, bulk.get("numberOfRowsFailed").asInt()); + assertEquals( + visibleGroup.getId(), + restricted + .metrics() + .get(allowedBulkRoot.getId().toString(), "metricGroup") + .getMetricGroup() + .getId()); + } finally { + admin.users().delete(user.getId()); + } + } finally { + admin.roles().delete(role.getId()); + } + } finally { + admin.policies().delete(policy.getId()); + } + } + + private static void assertRestrictedNamesAbsent(JsonNode response, Object... restrictedEntities) { + String serialized = response.toString(); + for (Object restricted : restrictedEntities) { + if (restricted instanceof Metric metric) { + assertFalse(serialized.contains(metric.getName())); + assertFalse(serialized.contains(metric.getFullyQualifiedName())); + } else if (restricted instanceof MetricGroup group) { + assertFalse(serialized.contains(group.getName())); + assertFalse(serialized.contains(group.getFullyQualifiedName())); + } + } + } + + @Test + void put_metricCsvRoundTripWithParent(TestNamespace ns) throws Exception { + OpenMetadataClient client = SdkClients.adminClient(); + Metric parent = createEntity(createRequest(ns.prefix("csv_parent"), ns)); + String childName = ns.prefix("csv_child"); + + String row = + String.join( + ",", + childName, + "CSV Child Metric", + "Child imported from CSV", + "SUM", + "DOLLARS", + "", + "DAY", + "SQL", + "SUM(x)", + "", + "", + "", + "", + "", + "", + "", + "", + "Approved", + "", + parent.getFullyQualifiedName(), + "", + ""); + String csv = METRIC_CSV_HEADER + "\n" + row + "\n"; + + CsvImportResult result = + new ObjectMapper() + .readValue(client.metrics().importCsv("*", csv, false), CsvImportResult.class); + assertEquals(1, result.getNumberOfRowsPassed(), result.getImportResultsCsv()); + + Metric imported = getEntityByNameWithFields(childName, HIERARCHY_FIELDS); + assertNotNull(imported.getParent(), "Imported child should be attached to its parent"); + assertEquals(parent.getId(), imported.getParent().getId()); + + String exportedCsv = client.metrics().exportCsv("*"); + assertTrue(exportedCsv.contains("parent"), "Export header should carry the parent column"); + assertTrue(exportedCsv.contains(parent.getFullyQualifiedName())); + } + + // =================================================================== + // APPROVAL + // =================================================================== + + @Test + void post_metricWithoutReviewers_isApproved(TestNamespace ns) { + Metric metric = createEntity(createRequest(ns.prefix("approval_none"), ns)); + assertEquals( + EntityStatus.APPROVED, + metric.getEntityStatus(), + "A metric with no reviewers has nothing to approve and should start Approved"); + } + + @Test + void post_metricWithReviewersButIncompleteMetadataRemainsDraft(TestNamespace ns) { + SharedEntities shared = SharedEntities.get(); + Metric metric = + createEntity( + new CreateMetric() + .withName(ns.prefix("approval_incomplete")) + .withReviewers(List.of(shared.USER1_REF))); + + Awaitility.await("Incomplete Metric should not enter approval review") + .during(Duration.ofSeconds(5)) + .atMost(Duration.ofSeconds(30)) + .pollInterval(Duration.ofMillis(500)) + .untilAsserted( + () -> { + assertEquals( + EntityStatus.DRAFT, getEntity(metric.getId().toString()).getEntityStatus()); + assertTrue(listOpenApprovalTasks(metric.getFullyQualifiedName()).getData().isEmpty()); + }); + } + + @Test + void post_metricWithReviewersCreatesApprovalTaskAndReviewerCanApprove(TestNamespace ns) + throws Exception { + SharedEntities shared = SharedEntities.get(); + Metric metric = + createEntity( + new CreateMetric() + .withName(ns.prefix("approval_reviewed")) + .withDescription("Metric awaiting review") + .withReviewers(List.of(shared.USER1_REF))); + + assertEquals(EntityStatus.DRAFT, metric.getEntityStatus()); + + Task task = awaitApprovalTask(metric); + EventSubscription notification = createApprovalTaskNotification(ns); + try { + long processedBefore = processedNotificationEvents(notification); + SdkClients.user1Client() + .tasks() + .resolve( + task.getId().toString(), + new ResolveTask().withResolutionType(TaskResolutionType.Approved)); + + Awaitility.await("Reviewer approval should synchronize Metric status") + .atMost(Duration.ofMinutes(2)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> + assertEquals( + EntityStatus.APPROVED, + getEntity(metric.getId().toString()).getEntityStatus())); + Awaitility.await("Approval task update should be delivered to its notification subscription") + .atMost(Duration.ofMinutes(1)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> assertTrue(processedNotificationEvents(notification) > processedBefore)); + + Task approvedTask = SdkClients.adminClient().tasks().get(task.getId().toString()); + assertEquals(TaskEntityStatus.Approved, approvedTask.getStatus()); + EntityHistory taskHistory = SdkClients.adminClient().tasks().getVersionList(task.getId()); + EntityHistory metricHistory = + SdkClients.adminClient().metrics().getVersionList(metric.getId()); + assertHistoryNewestFirst(taskHistory); + assertHistoryNewestFirst(metricHistory); + + Metric reviewerUpdate = + SdkClients.user1Client().metrics().get(metric.getId().toString(), "reviewers"); + reviewerUpdate.setDescription("Reviewer-authored approved definition"); + SdkClients.user1Client().metrics().update(metric.getId().toString(), reviewerUpdate); + + Awaitility.await("Reviewer-authored changes should auto-approve") + .atMost(Duration.ofMinutes(2)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> { + Metric current = getEntity(metric.getId().toString()); + assertEquals(EntityStatus.APPROVED, current.getEntityStatus()); + assertEquals("Reviewer-authored approved definition", current.getDescription()); + assertTrue( + listOpenApprovalTasks(metric.getFullyQualifiedName()).getData().isEmpty()); + }); + } finally { + SdkClients.adminClient().eventSubscriptions().delete(notification.getId().toString()); + } + } + + @Test + void rejectNewMetricRequiresCommentAndSetsRejected(TestNamespace ns) { + SharedEntities shared = SharedEntities.get(); + Metric metric = + createEntity( + new CreateMetric() + .withName(ns.prefix("approval_rejected")) + .withDescription("Metric to reject") + .withReviewers(List.of(shared.USER1_REF))); + Task task = awaitApprovalTask(metric); + EventSubscription notification = createApprovalTaskNotification(ns); + + try { + long processedBefore = processedNotificationEvents(notification); + assertApiStatus( + 400, + () -> + SdkClients.user1Client() + .tasks() + .resolve( + task.getId().toString(), + new ResolveTask() + .withTransitionId("unknown-reject-transition") + .withResolutionType(TaskResolutionType.Rejected))); + assertApiStatus( + 400, + () -> + SdkClients.user1Client() + .tasks() + .resolve( + task.getId().toString(), + new ResolveTask().withResolutionType(TaskResolutionType.Rejected))); + String decisionNote = "The definition needs revision"; + SdkClients.user1Client() + .tasks() + .resolve( + task.getId().toString(), + new ResolveTask() + .withResolutionType(TaskResolutionType.Rejected) + .withComment(decisionNote)); + + Awaitility.await("New Metric rejection should synchronize status and notification") + .atMost(Duration.ofMinutes(2)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> { + assertEquals( + EntityStatus.REJECTED, getEntity(metric.getId().toString()).getEntityStatus()); + assertTrue(processedNotificationEvents(notification) > processedBefore); + }); + Task rejectedTask = SdkClients.adminClient().tasks().get(task.getId().toString()); + assertEquals(TaskEntityStatus.Rejected, rejectedTask.getStatus()); + assertEquals(TaskResolutionType.Rejected, rejectedTask.getResolution().getType()); + assertEquals(decisionNote, rejectedTask.getResolution().getComment()); + EntityHistory taskHistory = SdkClients.adminClient().tasks().getVersionList(task.getId()); + EntityHistory metricHistory = + SdkClients.adminClient().metrics().getVersionList(metric.getId()); + assertHistoryContains(taskHistory, "status", TaskEntityStatus.Rejected.value()); + assertHistoryContains(taskHistory, "comment", decisionNote); + assertHistoryContains(metricHistory, "entityStatus", EntityStatus.REJECTED.value()); + } finally { + SdkClients.adminClient().eventSubscriptions().delete(notification.getId().toString()); + } + } + + @Test + void rejectMetricUpdateRollsBackPreviousApprovedVersion(TestNamespace ns) { + SharedEntities shared = SharedEntities.get(); + String approvedDescription = "Previously approved definition"; + Metric metric = + createEntity( + new CreateMetric() + .withName(ns.prefix("approval_rollback")) + .withDescription(approvedDescription) + .withReviewers(List.of(shared.USER1_REF))); + Task approvalTask = awaitApprovalTask(metric); + String approvalNote = "Approved baseline definition"; + + SdkClients.user1Client() + .tasks() + .resolve( + approvalTask.getId().toString(), + new ResolveTask() + .withResolutionType(TaskResolutionType.Approved) + .withComment(approvalNote)); + + Awaitility.await("Metric approval should complete before the update") + .atMost(Duration.ofMinutes(2)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> + assertEquals( + EntityStatus.APPROVED, getEntity(metric.getId().toString()).getEntityStatus())); + + Task approvedTask = SdkClients.adminClient().tasks().get(approvalTask.getId().toString()); + assertEquals(TaskEntityStatus.Approved, approvedTask.getStatus()); + assertEquals(TaskResolutionType.Approved, approvedTask.getResolution().getType()); + assertEquals(approvalNote, approvedTask.getResolution().getComment()); + + Metric update = getEntityWithFields(metric.getId().toString(), "reviewers"); + update.setDescription("Unapproved definition change"); + Metric pending = patchEntity(update.getId().toString(), update); + Task rejectionTask = awaitApprovalTask(pending); + String decisionNote = "Keep the approved definition"; + + SdkClients.user1Client() + .tasks() + .resolve( + rejectionTask.getId().toString(), + new ResolveTask() + .withResolutionType(TaskResolutionType.Rejected) + .withComment(decisionNote)); + + Awaitility.await("Rejected Metric update should roll back") + .atMost(Duration.ofMinutes(2)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> { + Metric rolledBack = getEntity(metric.getId().toString()); + assertEquals(EntityStatus.APPROVED, rolledBack.getEntityStatus()); + assertEquals(approvedDescription, rolledBack.getDescription()); + }); + Task rejectedTask = SdkClients.adminClient().tasks().get(rejectionTask.getId().toString()); + assertEquals(TaskEntityStatus.Rejected, rejectedTask.getStatus()); + assertEquals(TaskResolutionType.Rejected, rejectedTask.getResolution().getType()); + assertEquals(decisionNote, rejectedTask.getResolution().getComment()); + + Task preservedApprovalTask = + SdkClients.adminClient().tasks().get(approvalTask.getId().toString()); + assertEquals(TaskEntityStatus.Approved, preservedApprovalTask.getStatus()); + assertEquals(TaskResolutionType.Approved, preservedApprovalTask.getResolution().getType()); + assertEquals(approvalNote, preservedApprovalTask.getResolution().getComment()); + + List approvalHistory = listApprovalTasks(metric.getFullyQualifiedName()).getData(); + assertEquals(2, approvalHistory.size()); + Task listedApproval = + approvalHistory.stream() + .filter(task -> task.getId().equals(approvalTask.getId())) + .findFirst() + .orElseThrow(); + Task listedRejection = + approvalHistory.stream() + .filter(task -> task.getId().equals(rejectionTask.getId())) + .findFirst() + .orElseThrow(); + assertEquals(approvalNote, listedApproval.getResolution().getComment()); + assertEquals(decisionNote, listedRejection.getResolution().getComment()); + + EntityHistory taskHistory = + SdkClients.adminClient().tasks().getVersionList(rejectionTask.getId()); + EntityHistory metricHistory = SdkClients.adminClient().metrics().getVersionList(metric.getId()); + assertHistoryContains(taskHistory, "status", TaskEntityStatus.Rejected.value()); + assertHistoryContains(taskHistory, "comment", decisionNote); + assertHistoryContains(metricHistory, "description", "Unapproved definition change"); + assertHistoryContains(metricHistory, "description", approvedDescription); + } + + private Task awaitApprovalTask(Metric metric) { + Awaitility.await("Metric approval workflow should create an open task") + .atMost(Duration.ofMinutes(5)) + .pollInterval(Duration.ofSeconds(2)) + .untilAsserted( + () -> { + Metric current = getEntity(metric.getId().toString()); + assertEquals(EntityStatus.IN_REVIEW, current.getEntityStatus()); + assertFalse( + listOpenApprovalTasks(metric.getFullyQualifiedName()).getData().isEmpty()); + }); + return listOpenApprovalTasks(metric.getFullyQualifiedName()).getData().getFirst(); + } + + private ListResponse listOpenApprovalTasks(String metricFqn) { + return SdkClients.adminClient() + .tasks() + .listWithFilters( + Map.of( + "status", + TaskEntityStatus.Open.value(), + "category", + TaskCategory.Approval.value(), + "aboutEntity", + metricFqn, + "fields", + "assignees,about")); + } + + private ListResponse listApprovalTasks(String metricFqn) { + return SdkClients.adminClient() + .tasks() + .listWithFilters( + Map.of( + "category", + TaskCategory.Approval.value(), + "aboutEntity", + metricFqn, + "fields", + "assignees,about,resolution")); + } + + private EventSubscription createApprovalTaskNotification(TestNamespace ns) { + SubscriptionDestination destination = + new SubscriptionDestination() + .withId(UUID.randomUUID()) + .withType(SubscriptionDestination.SubscriptionType.EMAIL) + .withCategory(SubscriptionDestination.SubscriptionCategory.ASSIGNEES) + .withConfig(new EmailAlertConfig()); + return SdkClients.adminClient() + .eventSubscriptions() + .create( + new CreateEventSubscription() + .withName(ns.prefix("metric_approval_notification")) + .withAlertType(CreateEventSubscription.AlertType.NOTIFICATION) + .withResources(List.of("task")) + .withEnabled(true) + .withBatchSize(10) + .withPollInterval(1) + .withDestinations(List.of(destination))); + } + + private long processedNotificationEvents(EventSubscription subscription) { + JsonNode diagnostic = + JSON.valueToTree( + SdkClients.adminClient() + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/events/subscriptions/id/" + subscription.getId() + "/diagnosticInfo", + null, + Object.class)); + return diagnostic.path("successfulEventsCount").asLong() + + diagnostic.path("failedEventsCount").asLong(); + } + + private static void assertHistoryNewestFirst(EntityHistory history) { + assertNotNull(history); + assertNotNull(history.getVersions()); + assertFalse(history.getVersions().isEmpty()); + List versions = parseHistoryVersions(history); + if (versions.size() > 1) { + assertTrue( + versions.getFirst().path("version").asDouble() + >= versions.getLast().path("version").asDouble()); + } + } + + private static void assertHistoryContains( + EntityHistory history, String fieldName, String expectedValue) { + assertHistoryNewestFirst(history); + assertTrue( + parseHistoryVersions(history).stream() + .flatMap(version -> version.findValuesAsText(fieldName).stream()) + .anyMatch(expectedValue::equals), + () -> "Expected history field " + fieldName + " to contain " + expectedValue); + } + + private static List parseHistoryVersions(EntityHistory history) { + return history.getVersions().stream() + .map( + version -> + version instanceof String json + ? JsonUtils.readValue(json, JsonNode.class) + : JSON.valueToTree(version)) + .toList(); + } + + // =================================================================== + // ASSETS + // =================================================================== + + @Test + void post_createMetricPreservesDeprecatedAssets(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Table table = ShortStackFactory.table(ns); + Metric metric = + createEntity( + createRequest(ns.prefix("create_assets_metric"), ns) + .withAssets(List.of(table.getEntityReference().withType(Entity.TABLE)))); + + JsonNode assets = getMetricAssets(client, metric); + assertEquals(1, assets.get("paging").get("total").asInt()); + assertEquals( + table.getId().toString(), assets.get("data").get(0).get("asset").get("id").asText()); + } + + @Test + void put_bulkAddAndRemoveAssets(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("assets_metric"), ns)); + Table table = ShortStackFactory.table(ns); + + BulkAssets request = + new BulkAssets().withAssets(List.of(table.getEntityReference().withType("table"))); + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + request, + BulkOperationResult.class); + + JsonNode withAssets = getMetricAssets(client, metric); + assertEquals(1, withAssets.get("paging").get("total").asInt()); + assertEquals( + table.getId().toString(), withAssets.get("data").get(0).get("asset").get("id").asText()); + + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/remove", + request, + BulkOperationResult.class); + + JsonNode withoutAssets = getMetricAssets(client, metric); + assertEquals(0, withoutAssets.get("paging").get("total").asInt()); + assertTrue( + withoutAssets.get("data").isEmpty(), "Assets should be unlinked after a bulk remove"); + } + + @Test + void get_metricAssets_annotatesDirection(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("direction_metric"), ns)); + Table table = ShortStackFactory.table(ns); + + BulkAssets request = + new BulkAssets().withAssets(List.of(table.getEntityReference().withType("table"))); + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + request, + BulkOperationResult.class); + + JsonNode response = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + + metric.getId() + + "/assets?limit=1&offset=0&q=" + + table.getName() + + "&entityType=table&direction=unrelated", + null, + Object.class)); + + assertEquals(1, response.get("paging").get("total").asInt()); + assertEquals(1, response.get("data").size()); + JsonNode annotated = response.get("data").get(0); + assertEquals(table.getId().toString(), annotated.get("asset").get("id").asText()); + assertEquals( + "unrelated", + annotated.get("direction").asText(), + "With no lineage edge, a linked asset is neither upstream nor downstream"); + } + + @Test + void get_metricAssetsFiltersMixedEntityTypesAndBothLineageDirections(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("direction_filter_metric"), ns)); + Table upstream = ShortStackFactory.table(ns); + Table downstream = ShortStackFactory.table(ns); + DashboardService dashboardService = DashboardServiceTestFactory.createMetabase(ns); + Dashboard dashboard = + client + .dashboards() + .create( + new CreateDashboard() + .withName(ns.prefix("direction_filter_dashboard")) + .withService(dashboardService.getFullyQualifiedName())); + BulkAssets assets = + new BulkAssets() + .withAssets( + List.of( + upstream.getEntityReference().withType("table"), + downstream.getEntityReference().withType("table"), + dashboard.getEntityReference().withType("dashboard"))); + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + assets, + BulkOperationResult.class); + client + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(upstream.getEntityReference()) + .withToEntity(metric.getEntityReference()))); + client + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(metric.getEntityReference()) + .withToEntity(downstream.getEntityReference()))); + + assertSingleMetricAsset( + getMetricAssets(client, metric, "limit=10&offset=0&entityType=table&direction=upstream"), + upstream.getEntityReference(), + "upstream"); + assertSingleMetricAsset( + getMetricAssets(client, metric, "limit=10&offset=0&entityType=table&direction=downstream"), + downstream.getEntityReference(), + "downstream"); + assertSingleMetricAsset( + getMetricAssets( + client, metric, "limit=10&offset=0&entityType=dashboard&direction=unrelated"), + dashboard.getEntityReference(), + "unrelated"); + assertEquals( + 2, + getMetricAssets(client, metric, "limit=10&offset=0&entityType=table") + .path("paging") + .path("total") + .asInt()); + } + + @Test + void metricAssetsApplyRbacBeforePagingFilteringAndPartialBulkResults(TestNamespace ns) { + OpenMetadataClient admin = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("assets_rbac_metric"), ns)); + Table visible = ShortStackFactory.table(ns); + Table secondVisible = ShortStackFactory.table(ns); + Table restricted = ShortStackFactory.table(ns); + restricted.setTags(List.of(new TagLabel().withTagFQN(RESTRICTED_TAG_FQN))); + restricted = admin.tables().update(restricted.getId().toString(), restricted); + admin + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + new BulkAssets() + .withAssets( + List.of( + visible.getEntityReference().withType("table"), + restricted.getEntityReference().withType("table"))), + BulkOperationResult.class); + + Rule allowCatalog = + new Rule() + .withName("AllowMetricAssetAccess") + .withResources(List.of("All")) + .withOperations( + List.of( + MetadataOperation.VIEW_BASIC, + MetadataOperation.VIEW_ALL, + MetadataOperation.EDIT_ALL)) + .withEffect(Rule.Effect.ALLOW); + Rule denyRestrictedTables = + new Rule() + .withName("DenyRestrictedMetricAssets") + .withResources(List.of("table")) + .withOperations(List.of(MetadataOperation.VIEW_BASIC, MetadataOperation.VIEW_ALL)) + .withCondition("matchAnyTag('" + RESTRICTED_TAG_FQN + "')") + .withEffect(Rule.Effect.DENY); + String suffix = ns.uniqueShortId(); + Policy policy = + admin + .policies() + .create( + new CreatePolicy() + .withName("metricAssetPolicy_" + suffix) + .withRules(List.of(allowCatalog, denyRestrictedTables))); + try { + Role role = + admin + .roles() + .create( + new CreateRole() + .withName("metricAssetRole_" + suffix) + .withPolicies(List.of(policy.getFullyQualifiedName()))); + try { + String email = "metric-assets-" + suffix + "@test.openmetadata.org"; + User user = + admin + .users() + .create( + new CreateUser() + .withName("metric-assets-" + suffix) + .withEmail(email) + .withRoles(List.of(role.getId()))); + try { + OpenMetadataClient restrictedClient = + SdkClients.createClient(email, email, new String[] {}); + JsonNode firstPage = + getMetricAssets(restrictedClient, metric, "limit=1&offset=0&entityType=table"); + JsonNode secondPage = + getMetricAssets(restrictedClient, metric, "limit=1&offset=1&entityType=table"); + JsonNode restrictedSearch = + getMetricAssets( + restrictedClient, + metric, + "limit=10&offset=0&q=" + restricted.getName() + "&entityType=table"); + JsonNode directionFilter = + getMetricAssets( + restrictedClient, + metric, + "limit=10&offset=0&q=" + + visible.getName() + + "&entityType=table&direction=unrelated"); + + assertEquals(1, firstPage.path("paging").path("total").asInt()); + assertEquals( + visible.getId().toString(), + firstPage.path("data").get(0).path("asset").path("id").asText()); + assertTrue(secondPage.path("data").isEmpty()); + assertEquals(1, secondPage.path("paging").path("total").asInt()); + assertEquals(0, restrictedSearch.path("paging").path("total").asInt()); + assertEquals(1, directionFilter.path("paging").path("total").asInt()); + assertFalse(firstPage.toString().contains(restricted.getName())); + assertFalse(restrictedSearch.toString().contains(restricted.getName())); + assertApiStatus( + 400, + () -> getMetricAssets(restrictedClient, metric, "limit=0&offset=0&entityType=table")); + assertApiStatus( + 400, + () -> + getMetricAssets(restrictedClient, metric, "limit=1&offset=-1&entityType=table")); + assertApiStatus( + 404, + () -> + restrictedClient + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + UUID.randomUUID() + "/assets?limit=1&offset=0", + null, + Object.class)); + + EntityReference restrictedById = + new EntityReference().withId(restricted.getId()).withType("table"); + BulkOperationResult partial = + restrictedClient + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + new BulkAssets() + .withAssets( + List.of( + secondVisible.getEntityReference().withType("table"), + restrictedById)), + BulkOperationResult.class); + assertEquals(ApiStatus.PARTIAL_SUCCESS, partial.getStatus()); + assertEquals(1, partial.getNumberOfRowsPassed()); + assertEquals(1, partial.getNumberOfRowsFailed()); + JsonNode deniedRequest = + JSON.valueToTree(partial.getFailedRequest().getFirst().getRequest()); + assertEquals(restricted.getId().toString(), deniedRequest.path("id").asText()); + assertTrue( + deniedRequest.path("name").isMissingNode() || deniedRequest.path("name").isNull()); + assertFalse(JsonUtils.pojoToJson(partial).contains(restricted.getName())); + JsonNode visibleAfterBulk = + getMetricAssets( + restrictedClient, + metric, + "limit=10&offset=0&q=" + secondVisible.getName() + "&entityType=table"); + assertEquals(1, visibleAfterBulk.path("paging").path("total").asInt()); + + BulkOperationResult partialRemove = + restrictedClient + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/remove", + new BulkAssets() + .withAssets( + List.of( + visible.getEntityReference().withType("table"), restrictedById)), + BulkOperationResult.class); + assertEquals(ApiStatus.PARTIAL_SUCCESS, partialRemove.getStatus()); + assertEquals(2, partialRemove.getNumberOfRowsProcessed()); + assertEquals(1, partialRemove.getNumberOfRowsPassed()); + assertEquals(1, partialRemove.getNumberOfRowsFailed()); + assertEquals( + 0, + getMetricAssets( + restrictedClient, + metric, + "limit=10&offset=0&q=" + visible.getName() + "&entityType=table") + .path("paging") + .path("total") + .asInt()); + assertEquals( + 1, + getMetricAssets( + admin, + metric, + "limit=10&offset=0&q=" + restricted.getName() + "&entityType=table") + .path("paging") + .path("total") + .asInt()); + } finally { + admin.users().delete(user.getId()); + } + } finally { + admin.roles().delete(role.getId()); + } + } finally { + admin.policies().delete(policy.getId()); + } + } + + @Test + void metricDimensionAndMeasureSupportColumnLineageRoundTrips(TestNamespace ns) throws Exception { + OpenMetadataClient client = SdkClients.adminClient(); + Table table = ShortStackFactory.table(ns); + Metric metric = + createEntity( + createRequest(ns.prefix("lineage_metric_children"), ns) + .withDimensions(List.of(new MetricDimension().withName("region"))) + .withMeasures(List.of(new MetricMeasure().withName("revenue")))); + String tableColumn = table.getColumns().getFirst().getFullyQualifiedName(); + String dimension = metric.getFullyQualifiedName() + ".dimension.region"; + String measure = metric.getFullyQualifiedName() + ".measure.revenue"; + LineageDetails details = + new LineageDetails() + .withColumnsLineage( + List.of( + new ColumnLineage() + .withFromColumns(List.of(tableColumn)) + .withToColumn(dimension), + new ColumnLineage() + .withFromColumns(List.of(tableColumn)) + .withToColumn(measure))); + + client + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(table.getEntityReference()) + .withToEntity(metric.getEntityReference()) + .withLineageDetails(details))); + + EntityLineage lineage = + JSON.readValue( + client.lineage().getEntityLineage("metric", metric.getId().toString(), "1", "0"), + EntityLineage.class); + Edge edge = + lineage.getUpstreamEdges().stream() + .filter(candidate -> candidate.getFromEntity().equals(table.getId())) + .findFirst() + .orElseThrow(); + assertEquals(2, edge.getLineageDetails().getColumnsLineage().size()); + assertEquals( + List.of(dimension, measure), + edge.getLineageDetails().getColumnsLineage().stream() + .map(ColumnLineage::getToColumn) + .toList()); + } + + // =================================================================== + // OBSERVABILITY + // =================================================================== + + @Test + void get_metricObservability_withoutAssets_isUnknown(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("obs_bare"), ns)); + + JsonNode observability = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + metric.getId() + "/observability", + null, + Object.class)); + + assertEquals("Unknown", observability.get("health").asText()); + assertEquals(0, observability.get("upstreamAssetCount").asInt()); + assertEquals("NoLinkedAssets", observability.get("reasonCode").asText()); + assertApiStatus( + 404, + () -> + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + UUID.randomUUID() + "/observability", + null, + Object.class)); + } + + @Test + void get_metricObservability_downstreamAndUnrelatedAssetsAreNotScored(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("obs_downstream"), ns)); + Table downstream = ShortStackFactory.table(ns); + Table unrelated = ShortStackFactory.table(ns); + + BulkAssets request = + new BulkAssets() + .withAssets( + List.of( + downstream.getEntityReference().withType("table"), + unrelated.getEntityReference().withType("table"))); + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + request, + BulkOperationResult.class); + client + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(metric.getEntityReference()) + .withToEntity(downstream.getEntityReference()))); + TestCase downstreamTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_downstream") + .forTable(downstream) + .testDefinition("tableRowCountToEqual") + .parameter("value", "10") + .create(); + client + .testCaseResults() + .create( + downstreamTest.getFullyQualifiedName(), + testResult(TestCaseStatus.Failed, System.currentTimeMillis())); + + JsonNode observability = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + metric.getId() + "/observability", + null, + Object.class)); + + assertEquals( + "Unknown", + observability.get("health").asText(), + "Downstream and unrelated asset tests cannot score a metric"); + assertEquals(0, observability.get("upstreamAssetCount").asInt()); + assertEquals("NoUpstreamTables", observability.get("reasonCode").asText()); + Map directions = new HashMap<>(); + observability + .get("linkedAssets") + .forEach( + item -> + directions.put( + item.get("asset").get("id").asText(), item.get("direction").asText())); + assertEquals("downstream", directions.get(downstream.getId().toString())); + assertEquals("unrelated", directions.get(unrelated.getId().toString())); + } + + @Test + void get_metricObservabilityUsesLatestTableAndColumnTests(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("obs_scored"), ns)); + Table table = ShortStackFactory.table(ns); + BulkAssets assets = + new BulkAssets().withAssets(List.of(table.getEntityReference().withType("table"))); + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + assets, + BulkOperationResult.class); + client + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(table.getEntityReference()) + .withToEntity(metric.getEntityReference()))); + + TestDefinition consistencyDefinition = + client + .testDefinitions() + .create( + new CreateTestDefinition() + .withName(ns.uniqueShortId() + "_consistency") + .withDescription("Consistency dimension for Metric observability") + .withEntityType(TestDefinitionEntityType.TABLE) + .withTestPlatforms(List.of(TestPlatform.OPEN_METADATA)) + .withDataQualityDimension(DataQualityDimensions.CONSISTENCY)); + TestCase tableTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_table") + .forTable(table) + .testDefinition(consistencyDefinition.getFullyQualifiedName()) + .create(); + TestCase columnTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_column") + .forColumn(table, "id") + .testDefinition("columnValuesToBeNotNull") + .create(); + TestCase queuedTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_queued") + .forTable(table) + .testDefinition("tableRowCountToEqual") + .parameter("value", "10") + .create(); + TestCase missingTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_missing") + .forColumn(table, "v") + .testDefinition("columnValuesToBeNotNull") + .create(); + + long start = System.currentTimeMillis() - 10_000L; + client + .testCaseResults() + .create(tableTest.getFullyQualifiedName(), testResult(TestCaseStatus.Success, start + 100)); + client + .testCaseResults() + .create( + columnTest.getFullyQualifiedName(), testResult(TestCaseStatus.Success, start + 200)); + UUID incidentStateId = + client + .testCaseResults() + .create( + tableTest.getFullyQualifiedName(), testResult(TestCaseStatus.Failed, start + 300)) + .getIncidentId(); + TestCaseResolutionStatus incident = awaitIncidentStatus(client, incidentStateId); + JsonNode severityPatch = + JSON.createArrayNode() + .add( + JSON.createObjectNode() + .put("op", "add") + .put("path", "/severity") + .put("value", Severity.Severity1.value())); + incident = client.testCaseResolutionStatuses().patch(incident.getId(), severityPatch); + assertEquals( + Severity.Severity1, + client.testCaseResolutionStatuses().get(incident.getId()).getSeverity()); + client + .testCaseResults() + .create(queuedTest.getFullyQualifiedName(), testResult(TestCaseStatus.Queued, start + 400)); + + JsonNode observability = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + metric.getId() + "/observability", + null, + Object.class)); + + assertEquals("Degraded", observability.get("health").asText()); + assertEquals("Degraded", observability.get("reasonCode").asText()); + assertEquals(50.0, observability.get("score").asDouble()); + assertEquals(1, observability.get("statusCounts").get("passed").asInt()); + assertEquals(1, observability.get("statusCounts").get("failed").asInt()); + assertEquals(1, observability.get("statusCounts").get("queued").asInt()); + assertEquals(1, observability.get("statusCounts").get("missing").asInt()); + assertEquals(2, observability.get("statusCounts").get("terminal").asInt()); + JsonNode consistency = null; + for (JsonNode dimension : observability.get("dimensions")) { + if (DataQualityDimensions.CONSISTENCY.value().equals(dimension.get("dimension").asText())) { + consistency = dimension; + break; + } + } + assertNotNull(consistency); + assertEquals(1, consistency.get("total").asInt()); + assertEquals(0, consistency.get("passed").asInt()); + assertEquals(1, consistency.get("failed").asInt()); + assertEquals(start + 300, observability.get("latestRunTime").asLong()); + assertEquals(4, observability.get("tests").size()); + assertEquals(1, observability.get("incidents").size()); + assertEquals( + tableTest.getId().toString(), + observability.get("incidents").get(0).get("testCase").get("id").asText()); + assertEquals( + table.getId().toString(), + observability.get("incidents").get(0).get("asset").get("id").asText()); + assertEquals("New", observability.get("incidents").get(0).get("status").asText()); + assertEquals("Severity1", observability.get("incidents").get(0).get("severity").asText()); + assertEquals(1, observability.get("sourceCoverage").get("testedTables").asInt()); + assertNotNull(missingTest); + } + + @Test + void get_metricObservabilityDoesNotTruncateActiveTestsAndExcludesDeletedTests(TestNamespace ns) { + OpenMetadataClient client = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("obs_complete_active_set"), ns)); + Table table = ShortStackFactory.table(ns); + client + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + new BulkAssets().withAssets(List.of(table.getEntityReference().withType("table"))), + BulkOperationResult.class); + client + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(table.getEntityReference()) + .withToEntity(metric.getEntityReference()))); + + long resultBase = System.currentTimeMillis() - 100_000L; + List activeTests = new ArrayList<>(); + for (int index = 0; index < 6; index++) { + TestCase tableTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_obs_table_" + index) + .forTable(table) + .testDefinition("tableRowCountToEqual") + .parameter("value", "10") + .create(); + activeTests.add(tableTest); + if (index == 0) { + client + .testCaseResults() + .create( + tableTest.getFullyQualifiedName(), + testResult(TestCaseStatus.Aborted, resultBase + 100)); + } + client + .testCaseResults() + .create( + tableTest.getFullyQualifiedName(), + testResult(TestCaseStatus.Success, resultBase + 1_000 + index)); + } + for (int index = 0; index < 6; index++) { + TestCase columnTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_obs_column_" + index) + .forColumn(table, "id") + .testDefinition("columnValuesToBeNotNull") + .create(); + activeTests.add(columnTest); + if (index == 4) { + client + .testCaseResults() + .create( + columnTest.getFullyQualifiedName(), + testResult(TestCaseStatus.Success, resultBase + 1_500)); + } + TestCaseStatus latestStatus = index < 4 ? TestCaseStatus.Success : TestCaseStatus.Aborted; + client + .testCaseResults() + .create( + columnTest.getFullyQualifiedName(), + testResult(latestStatus, resultBase + 2_000 + index)); + } + + TestCase deletedTest = + TestCaseBuilder.create(client) + .name(ns.uniqueShortId() + "_obs_deleted") + .forTable(table) + .testDefinition("tableRowCountToEqual") + .parameter("value", "10") + .create(); + UUID deletedIncidentId = + client + .testCaseResults() + .create( + deletedTest.getFullyQualifiedName(), + testResult(TestCaseStatus.Failed, resultBase + 3_000)) + .getIncidentId(); + awaitIncidentStatus(client, deletedIncidentId); + client.testCases().delete(deletedTest.getId().toString(), Map.of("recursive", "true")); + + JsonNode observability = getObservability(client, metric); + double expectedScore = (10.0 / 12.0) * 100.0; + assertEquals("AtRisk", observability.path("health").asText()); + assertEquals("AtRisk", observability.path("reasonCode").asText()); + assertEquals(expectedScore, observability.path("score").asDouble(), 0.0001); + assertEquals(resultBase + 2_005, observability.path("latestRunTime").asLong()); + assertEquals(1, observability.path("upstreamAssetCount").asInt()); + assertEquals(1, observability.path("evaluatedAssetCount").asInt()); + assertEquals(12, observability.path("tests").size()); + List returnedTestIds = new ArrayList<>(); + observability + .path("tests") + .forEach(test -> returnedTestIds.add(test.path("testCase").path("id").asText())); + assertEquals(12, returnedTestIds.size()); + activeTests.forEach( + test -> + assertTrue( + returnedTestIds.contains(test.getId().toString()), + () -> "Active test was truncated from observability: " + test.getName())); + assertFalse(returnedTestIds.contains(deletedTest.getId().toString())); + + JsonNode statusCounts = observability.path("statusCounts"); + assertEquals(10, statusCounts.path("passed").asInt()); + assertEquals(0, statusCounts.path("failed").asInt()); + assertEquals(2, statusCounts.path("aborted").asInt()); + assertEquals(0, statusCounts.path("queued").asInt()); + assertEquals(0, statusCounts.path("missing").asInt()); + assertEquals(12, statusCounts.path("terminal").asInt()); + + JsonNode source = observability.path("assets").get(0); + assertEquals(table.getId().toString(), source.path("asset").path("id").asText()); + assertEquals(12, source.path("total").asInt()); + assertEquals(10, source.path("passed").asInt()); + assertEquals(0, source.path("failed").asInt()); + assertEquals(2, source.path("aborted").asInt()); + assertEquals(expectedScore, source.path("score").asDouble(), 0.0001); + + JsonNode coverage = observability.path("sourceCoverage"); + assertEquals(1, coverage.path("upstreamTables").asInt()); + assertEquals(1, coverage.path("testedTables").asInt()); + assertEquals(1, coverage.path("visibleTables").asInt()); + assertEquals(0, coverage.path("restrictedTables").asInt()); + assertEquals(100.0, coverage.path("coveragePercent").asDouble()); + + Map dimensions = new HashMap<>(); + observability + .path("dimensions") + .forEach(dimension -> dimensions.put(dimension.path("dimension").asText(), dimension)); + assertFalse(dimensions.isEmpty()); + assertEquals( + 12, + dimensions.values().stream().mapToInt(dimension -> dimension.path("total").asInt()).sum()); + assertEquals( + 10, + dimensions.values().stream().mapToInt(dimension -> dimension.path("passed").asInt()).sum()); + assertEquals( + 0, + dimensions.values().stream().mapToInt(dimension -> dimension.path("failed").asInt()).sum()); + assertEquals( + 2, + dimensions.values().stream() + .mapToInt(dimension -> dimension.path("aborted").asInt()) + .sum()); + assertEquals(0, observability.path("incidents").size()); + } + + @Test + void get_metricObservabilityRedactsRestrictedSourcesButPreservesGlobalScore(TestNamespace ns) { + OpenMetadataClient admin = SdkClients.adminClient(); + Metric metric = createEntity(createRequest(ns.prefix("obs_restricted"), ns)); + Table table = ShortStackFactory.table(ns); + BulkAssets assets = + new BulkAssets().withAssets(List.of(table.getEntityReference().withType("table"))); + admin + .getHttpClient() + .execute( + HttpMethod.PUT, + "/v1/metrics/" + metric.getFullyQualifiedName() + "/assets/add", + assets, + BulkOperationResult.class); + admin + .lineage() + .addLineage( + new AddLineage() + .withEdge( + new EntitiesEdge() + .withFromEntity(table.getEntityReference()) + .withToEntity(metric.getEntityReference()))); + TestCase failedTest = + TestCaseBuilder.create(admin) + .name(ns.uniqueShortId() + "_restricted") + .forTable(table) + .testDefinition("tableRowCountToEqual") + .parameter("value", "10") + .create(); + long resultTime = System.currentTimeMillis(); + UUID incidentStateId = + admin + .testCaseResults() + .create( + failedTest.getFullyQualifiedName(), testResult(TestCaseStatus.Failed, resultTime)) + .getIncidentId(); + awaitIncidentStatus(admin, incidentStateId); + JsonNode full = getObservability(admin, metric); + + Rule allowCatalog = + new Rule() + .withName("AllowCatalog") + .withResources(List.of("All")) + .withOperations(List.of(MetadataOperation.VIEW_ALL)) + .withEffect(Rule.Effect.ALLOW); + Rule denyTables = + new Rule() + .withName("DenyTables") + .withResources(List.of("table")) + .withOperations(List.of(MetadataOperation.VIEW_ALL)) + .withEffect(Rule.Effect.DENY); + String suffix = ns.uniqueShortId(); + Policy policy = + admin + .policies() + .create( + new CreatePolicy() + .withName("metricObsPolicy_" + suffix) + .withRules(List.of(allowCatalog, denyTables))); + try { + Role role = + admin + .roles() + .create( + new CreateRole() + .withName("metricObsRole_" + suffix) + .withPolicies(List.of(policy.getFullyQualifiedName()))); + try { + String email = "metric-obs-" + suffix + "@test.openmetadata.org"; + User user = + admin + .users() + .create( + new CreateUser() + .withName("metric-obs-" + suffix) + .withEmail(email) + .withRoles(List.of(role.getId()))); + try { + OpenMetadataClient restricted = SdkClients.createClient(email, email, new String[] {}); + assertApiStatus(403, () -> restricted.tables().get(table.getId().toString())); + + JsonNode redacted = getObservability(restricted, metric); + + assertEquals(full.get("score").asDouble(), redacted.get("score").asDouble()); + assertEquals(full.get("health").asText(), redacted.get("health").asText()); + assertEquals(full.get("statusCounts"), redacted.get("statusCounts")); + assertEquals(resultTime, redacted.get("latestRunTime").asLong()); + assertEquals(1, redacted.get("upstreamAssetCount").asInt()); + assertEquals(0, redacted.get("sourceCoverage").get("visibleTables").asInt()); + assertEquals(1, redacted.get("sourceCoverage").get("restrictedTables").asInt()); + assertTrue(redacted.get("partial").asBoolean()); + assertEquals("PartialDetails", redacted.get("reasonCode").asText()); + assertEquals(0, redacted.get("assets").size()); + assertEquals(0, redacted.get("linkedAssets").size()); + assertEquals(0, redacted.get("tests").size()); + assertEquals(0, redacted.get("incidents").size()); + } finally { + admin.users().delete(user.getId()); + } + } finally { + admin.roles().delete(role.getId()); + } + } finally { + admin.policies().delete(policy.getId()); + } + } + + private JsonNode getObservability(OpenMetadataClient client, Metric metric) { + return JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + metric.getId() + "/observability", + null, + Object.class)); + } + + private JsonNode getMetricAssets(OpenMetadataClient client, Metric metric) { + return getMetricAssets(client, metric, "limit=100&offset=0"); + } + + private JsonNode getMetricAssets( + OpenMetadataClient client, Metric metric, String queryParameters) { + return JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/metrics/" + metric.getId() + "/assets?" + queryParameters, + null, + Object.class)); + } + + private static void assertSingleMetricAsset( + JsonNode response, EntityReference expectedAsset, String expectedDirection) { + assertEquals(1, response.path("paging").path("total").asInt()); + assertEquals(1, response.path("data").size()); + JsonNode asset = response.path("data").get(0); + assertEquals(expectedAsset.getId().toString(), asset.path("asset").path("id").asText()); + assertEquals(expectedAsset.getType(), asset.path("asset").path("type").asText()); + assertEquals(expectedDirection, asset.path("direction").asText()); + } + + private static void withRestrictedHierarchyDestinationEditor( + TestNamespace ns, Consumer assertions) { + OpenMetadataClient admin = SdkClients.adminClient(); + String suffix = ns.uniqueShortId(); + Rule allowCatalog = + new Rule() + .withName("AllowHierarchyDestinationWrites") + .withResources(List.of("All")) + .withOperations( + List.of( + MetadataOperation.CREATE, + MetadataOperation.VIEW_ALL, + MetadataOperation.EDIT_ALL)) + .withEffect(Rule.Effect.ALLOW); + Rule denyRestrictedDestinations = + new Rule() + .withName("DenyRestrictedHierarchyDestinations") + .withResources(List.of("metric", "metricGroup")) + .withOperations(List.of(MetadataOperation.EDIT_ALL)) + .withCondition("matchAnyTag('" + RESTRICTED_TAG_FQN + "')") + .withEffect(Rule.Effect.DENY); + Policy policy = + admin + .policies() + .create( + new CreatePolicy() + .withName("metricDestinationPolicy_" + suffix) + .withRules(List.of(allowCatalog, denyRestrictedDestinations))); + try { + Role role = + admin + .roles() + .create( + new CreateRole() + .withName("metricDestinationRole_" + suffix) + .withPolicies(List.of(policy.getFullyQualifiedName()))); + try { + String userName = "metric-destination-writer-" + suffix; + String email = userName + "@test.openmetadata.org"; + User user = + admin + .users() + .create( + new CreateUser() + .withName(userName) + .withEmail(email) + .withRoles(List.of(role.getId()))); + try { + assertions.accept(SdkClients.createClient(email, email, new String[] {})); + } finally { + admin.users().delete(user.getId()); + } + } finally { + admin.roles().delete(role.getId()); + } + } finally { + admin.policies().delete(policy.getId()); + } + } + + private static void assertApiStatus(int expectedStatus, Executable request) { + Throwable current = assertThrows(Throwable.class, request); + OpenMetadataException apiFailure = null; + while (current != null) { + if (current instanceof OpenMetadataException candidate && candidate.getStatusCode() > 0) { + apiFailure = candidate; + break; + } + current = current.getCause(); + } + assertNotNull(apiFailure, "Expected an SDK API exception with an HTTP status"); + assertEquals(expectedStatus, apiFailure.getStatusCode()); + } + + private static TestCaseResolutionStatus awaitIncidentStatus( + OpenMetadataClient client, UUID stateId) { + AtomicReference incident = new AtomicReference<>(); + Awaitility.await("incident status synchronized from its task") + .atMost(Duration.ofSeconds(10)) + .pollInterval(Duration.ofMillis(100)) + .ignoreExceptions() + .untilAsserted( + () -> { + JsonNode response = + JSON.valueToTree( + client + .getHttpClient() + .execute( + HttpMethod.GET, + "/v1/dataQuality/testCases/testCaseIncidentStatus/stateId/" + stateId, + null, + Object.class)); + assertFalse(response.path("data").isEmpty()); + TestCaseResolutionStatus status = + JSON.convertValue(response.path("data").get(0), TestCaseResolutionStatus.class); + assertNotNull(status.getId()); + incident.set(status); + }); + return incident.get(); + } + + private CreateTestCaseResult testResult(TestCaseStatus status, long timestamp) { + return new CreateTestCaseResult() + .withTimestamp(timestamp) + .withTestCaseStatus(status) + .withResult(status.value()); + } + // =================================================================== // BULK API SUPPORT // =================================================================== + @Test + void bulkCreateInvalidatesPreviouslyCachedMissingMetric(TestNamespace ns) { + String metricName = ns.prefix("bulk_negative_cache"); + assertApiStatus(404, () -> getEntityByName(metricName)); + + BulkOperationResult result = executeBulkCreate(List.of(createRequest(metricName, ns))); + + assertEquals(ApiStatus.SUCCESS, result.getStatus()); + assertEquals(1, result.getNumberOfRowsPassed()); + assertEquals(metricName, getEntityByName(metricName).getFullyQualifiedName()); + } + + @Test + void relationshipJsonInsertAndDuplicateUpdatePreserveUnicode(TestNamespace ns) throws Exception { + Metric metric = createEntity(createRequest(ns.prefix("relationship_json"), ns)); + int relation = Relationship.RELATED_TO.ordinal(); + String relationType = "unicode_" + ns.uniqueShortId(); + CollectionDAO.EntityRelationshipDAO dao = Entity.getCollectionDAO().relationshipDAO(); + + try { + dao.insert( + metric.getId(), + metric.getId(), + Entity.METRIC, + Entity.METRIC, + relation, + relationType, + "{\"label\":\"Métrica 東京 📈\"}"); + List relationships = + dao.findTo(metric.getId(), Entity.METRIC, relation).stream() + .filter(record -> metric.getId().equals(record.getId())) + .toList(); + assertEquals(1, relationships.size()); + assertEquals( + "Métrica 東京 📈", JSON.readTree(relationships.getFirst().getJson()).get("label").asText()); + + dao.insert( + metric.getId(), + metric.getId(), + Entity.METRIC, + Entity.METRIC, + relation, + relationType, + "{\"label\":\"Résumé Київ ✅\"}"); + relationships = + dao.findTo(metric.getId(), Entity.METRIC, relation).stream() + .filter(record -> metric.getId().equals(record.getId())) + .toList(); + assertEquals(1, relationships.size()); + assertEquals( + "Résumé Київ ✅", JSON.readTree(relationships.getFirst().getJson()).get("label").asText()); + } finally { + dao.deleteWithRelationType( + metric.getId(), Entity.METRIC, metric.getId(), Entity.METRIC, relation, relationType); + } + } + @Override protected BulkOperationResult executeBulkCreate(List createRequests) { return SdkClients.adminClient().metrics().bulkCreateOrUpdate(createRequests); diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TaskResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TaskResourceIT.java index e4ab6a5d1e0d..7faa050909de 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TaskResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TaskResourceIT.java @@ -578,6 +578,36 @@ void testResolveTaskWithRejection(TestNamespace ns) { assertEquals(TaskResolutionType.Rejected, resolvedTask.getResolution().getType()); } + @Test + void testResolveTaskRejectsMissingRequiredTransitionComment(TestNamespace ns) { + DatabaseService service = DatabaseServiceTestFactory.createPostgres(ns); + DatabaseSchema dbSchema = DatabaseSchemaTestFactory.createSimple(ns, service); + Table table = TableTestFactory.createSimple(ns, dbSchema.getFullyQualifiedName()); + org.openmetadata.schema.type.DescriptionUpdatePayload payload = + new org.openmetadata.schema.type.DescriptionUpdatePayload() + .withFieldPath("description") + .withCurrentDescription(table.getDescription()) + .withNewDescription("Description rejected without a comment"); + Task task = + createEntity( + new CreateTask() + .withName(ns.prefix("resolve-reject-comment-required")) + .withDescription("Task whose rejection requires a comment") + .withCategory(TaskCategory.MetadataUpdate) + .withType(TaskEntityType.DescriptionUpdate) + .withAbout(entityLink("table", table.getFullyQualifiedName())) + .withPayload(payload)); + awaitTaskReadyForWorkflowResolution(task.getId()); + ResolveTask resolveRequest = new ResolveTask().withResolutionType(TaskResolutionType.Rejected); + + assertThrows( + InvalidRequestException.class, + () -> SdkClients.adminClient().tasks().resolve(task.getId().toString(), resolveRequest)); + + Task unchanged = SdkClients.adminClient().tasks().get(task.getId().toString()); + assertEquals(TaskEntityStatus.Open, unchanged.getStatus()); + } + @Test void testListTasksByStatus(TestNamespace ns) { CreateTask request1 = diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TestCaseResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TestCaseResourceIT.java index 6931083b9ca8..ae55b05be825 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TestCaseResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TestCaseResourceIT.java @@ -3053,7 +3053,8 @@ void test_searchListIncidentIdClearedAfterResolve(TestNamespace ns) { .withTestCaseReference(testCase.getFullyQualifiedName()) .withTestCaseResolutionStatusType(TestCaseResolutionStatusTypes.Resolved) .withTestCaseResolutionStatusDetails( - new org.openmetadata.schema.tests.type.Resolved())); + new org.openmetadata.schema.tests.type.Resolved() + .withTestCaseFailureComment("Resolved by integration test"))); // A resolve carries no test result, so only the targeted search update can clear the pointer. Awaitility.await("search/list incidentId cleared after resolve") @@ -3279,7 +3280,9 @@ void test_incidentReopensAsNewAfterResolveAndNewFailure(TestNamespace ns) { .withTestCaseReference(testCase.getFullyQualifiedName()) .withTestCaseResolutionStatusType( org.openmetadata.schema.tests.type.TestCaseResolutionStatusTypes.Resolved) - .withTestCaseResolutionStatusDetails(new org.openmetadata.schema.tests.type.Resolved()); + .withTestCaseResolutionStatusDetails( + new org.openmetadata.schema.tests.type.Resolved() + .withTestCaseFailureComment("Resolved by integration test")); client.testCaseResolutionStatuses().create(resolvedStatus); Awaitility.await() @@ -3432,7 +3435,8 @@ void test_incidentIdDerivation_followsLatestUnresolvedTcrs(TestNamespace ns) { .withTestCaseReference(testCase.getFullyQualifiedName()) .withTestCaseResolutionStatusType(TestCaseResolutionStatusTypes.Resolved) .withTestCaseResolutionStatusDetails( - new org.openmetadata.schema.tests.type.Resolved())); + new org.openmetadata.schema.tests.type.Resolved() + .withTestCaseFailureComment("Resolved by integration test"))); Awaitility.await("Resolved clears the ongoing incident pointer") .atMost(90, TimeUnit.SECONDS) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/AIContextMcpIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/AIContextMcpIT.java index ad098a4f266d..85424df6da57 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/AIContextMcpIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/AIContextMcpIT.java @@ -34,6 +34,8 @@ import org.openmetadata.schema.type.ColumnDataType; import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.TableConstraint; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; /** * End-to-end integration test for the AI Context Platform's Mode A (get_entity_details with @@ -167,45 +169,59 @@ private static Metric createMetricAppliedToTable() throws Exception { new CreateMetric() .withName("aicontext_revenue_" + suffix) .withDescription("Total revenue from completed orders.") - .withMetricExpression(new MetricExpression().withCode(METRIC_CODE)) - .withAssets( - List.of(new EntityReference().withId(ordersTable.getId()).withType("table"))); - return post("metrics", createMetric, Metric.class); + .withMetricExpression(new MetricExpression().withCode(METRIC_CODE)); + Metric metric = post("metrics", createMetric, Metric.class); + addAsset(metric, ordersTable); + return metric; } @Test - void metricAssets_updateViaPatchRewiresTheEdge() throws Exception { + void metricAssets_bulkOperationsRewireTheEdge() throws Exception { Metric metric = post( "metrics", new CreateMetric() .withName("aicontext_patch_metric_" + suffix) - .withDescription("Metric whose applied assets get rewired.") - .withAssets( - List.of(new EntityReference().withId(ordersTable.getId()).withType("table"))), + .withDescription("Metric whose applied assets get rewired."), Metric.class); + addAsset(metric, ordersTable); - String rewirePatch = - String.format( - "[{\"op\":\"add\",\"path\":\"/assets\",\"value\":[{\"id\":\"%s\",\"type\":\"table\"}]}]", - customersTable.getId()); - patch("metrics/" + metric.getId(), rewirePatch); + put( + "metrics/" + metric.getName() + "/assets/remove", + new BulkAssets().withAssets(List.of(tableReference(ordersTable))), + BulkOperationResult.class); + addAsset(metric, customersTable); - JsonNode updated = get("metrics/name/" + metric.getName() + "?fields=assets", JsonNode.class); - JsonNode assets = updated.get("assets"); + JsonNode assets = assetsOf(metric); assertThat(assets).isNotNull(); assertThat(assets.size()).isEqualTo(1); - assertThat(assets.get(0).get("id").asText()).isEqualTo(customersTable.getId().toString()); + assertThat(assets.get(0).path("asset").path("id").asText()) + .isEqualTo(customersTable.getId().toString()); } @Test void metricAssets_roundTripsThroughApi() throws Exception { - JsonNode metric = - get("metrics/name/" + revenueMetric.getName() + "?fields=assets", JsonNode.class); - JsonNode assets = metric.get("assets"); + JsonNode assets = assetsOf(revenueMetric); assertThat(assets).isNotNull(); assertThat(assets.isArray()).isTrue(); - assertThat(assets.get(0).get("id").asText()).isEqualTo(ordersTable.getId().toString()); + assertThat(assets.get(0).path("asset").path("id").asText()) + .isEqualTo(ordersTable.getId().toString()); + } + + private static void addAsset(Metric metric, Table table) throws Exception { + put( + "metrics/" + metric.getName() + "/assets/add", + new BulkAssets().withAssets(List.of(tableReference(table))), + BulkOperationResult.class); + } + + private static EntityReference tableReference(Table table) { + return new EntityReference().withId(table.getId()).withType("table"); + } + + private static JsonNode assetsOf(Metric metric) throws Exception { + return get("metrics/" + metric.getId() + "/assets?limit=100&offset=0", JsonNode.class) + .path("data"); } @Test diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/MetricAssetsIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/MetricAssetsIT.java index 28ceb93d58b5..06c19ed48b5f 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/MetricAssetsIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/MetricAssetsIT.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.JsonNode; import java.net.http.HttpResponse; +import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.StreamSupport; @@ -26,12 +27,13 @@ import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.schema.entity.data.Table; import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; /** - * Full lifecycle coverage for the metric → asset relationship ({@code Metric.assets}, an APPLIED_TO - * edge): adding on create, adding/replacing/removing/clearing via PATCH, and referential cleanup - * when an asset is deleted. Complements AIContextMcpIT, which covers how the edge surfaces as - * context; this class exercises the CRUD mechanics of the edge itself. + * Full lifecycle coverage for the metric → asset APPLIED_TO relationship through the bounded + * Metric assets API: adding, replacing, removing, clearing, and referential cleanup when an asset + * is deleted. Complements AIContextMcpIT, which covers how the edge surfaces as context. */ @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MetricAssetsIT extends McpTestBase { @@ -53,10 +55,11 @@ static void setup() throws Exception { private static Metric createMetric(String name, Table... assets) throws Exception { CreateMetric create = new CreateMetric().withName(name).withDescription("Metric assets lifecycle: " + name); + Metric metric = post("metrics", create, Metric.class); if (assets.length > 0) { - create.withAssets(List.of(assets).stream().map(MetricAssetsIT::assetRef).toList()); + addAssets(metric, assets); } - return post("metrics", create, Metric.class); + return metric; } private static EntityReference assetRef(Table table) { @@ -64,31 +67,46 @@ private static EntityReference assetRef(Table table) { } private static JsonNode assetsOf(Metric metric) throws Exception { - return get("metrics/name/" + metric.getName() + "?fields=assets", JsonNode.class).get("assets"); + return get("metrics/" + metric.getId() + "/assets?limit=100&offset=0", JsonNode.class) + .path("data"); } - private static void patchAssets(Metric metric, Table... assets) throws Exception { - StringBuilder value = new StringBuilder("["); - for (int i = 0; i < assets.length; i++) { - if (i > 0) { - value.append(','); - } - value.append(String.format("{\"id\":\"%s\",\"type\":\"table\"}", assets[i].getId())); + private static void addAssets(Metric metric, Table... assets) throws Exception { + put( + "metrics/" + metric.getName() + "/assets/add", + new BulkAssets().withAssets(Arrays.stream(assets).map(MetricAssetsIT::assetRef).toList()), + BulkOperationResult.class); + } + + private static void replaceAssets(Metric metric, Table... assets) throws Exception { + List existing = + StreamSupport.stream(assetsOf(metric).spliterator(), false) + .map(node -> node.path("asset")) + .map( + node -> + new EntityReference() + .withId(UUID.fromString(node.path("id").asText())) + .withType(node.path("type").asText())) + .toList(); + if (!existing.isEmpty()) { + put( + "metrics/" + metric.getName() + "/assets/remove", + new BulkAssets().withAssets(existing), + BulkOperationResult.class); + } + if (assets.length > 0) { + addAssets(metric, assets); } - value.append(']'); - patch( - "metrics/" + metric.getId(), - String.format("[{\"op\":\"add\",\"path\":\"/assets\",\"value\":%s}]", value)); } private static boolean containsAsset(JsonNode assets, Table table) { return assets != null && StreamSupport.stream(assets.spliterator(), false) - .anyMatch(a -> a.get("id").asText().equals(table.getId().toString())); + .anyMatch(a -> a.path("asset").path("id").asText().equals(table.getId().toString())); } @Test - void create_withAssets_persistsTheEdges() throws Exception { + void bulkAdd_persistsTheEdges() throws Exception { Metric metric = createMetric("metricassets_create_" + suffix, assetA, assetB); JsonNode assets = assetsOf(metric); assertThat(assets.size()).isEqualTo(2); @@ -104,9 +122,9 @@ void create_withoutAssets_isEmpty() throws Exception { } @Test - void update_addAssetViaPatch() throws Exception { + void bulkAdd_appendsAnAsset() throws Exception { Metric metric = createMetric("metricassets_add_" + suffix, assetA); - patchAssets(metric, assetA, assetB); + addAssets(metric, assetB); JsonNode assets = assetsOf(metric); assertThat(assets.size()).isEqualTo(2); assertThat(containsAsset(assets, assetA)).isTrue(); @@ -114,9 +132,9 @@ void update_addAssetViaPatch() throws Exception { } @Test - void update_replaceAssetsViaPatch() throws Exception { + void bulkOperations_replaceAssets() throws Exception { Metric metric = createMetric("metricassets_replace_" + suffix, assetA); - patchAssets(metric, assetB); + replaceAssets(metric, assetB); JsonNode assets = assetsOf(metric); assertThat(assets.size()).isEqualTo(1); assertThat(containsAsset(assets, assetB)).isTrue(); @@ -124,9 +142,9 @@ void update_replaceAssetsViaPatch() throws Exception { } @Test - void update_removeOneAssetViaPatch() throws Exception { + void bulkOperations_removeOneAsset() throws Exception { Metric metric = createMetric("metricassets_remove_" + suffix, assetA, assetB); - patchAssets(metric, assetA); + replaceAssets(metric, assetA); JsonNode assets = assetsOf(metric); assertThat(assets.size()).isEqualTo(1); assertThat(containsAsset(assets, assetA)).isTrue(); @@ -134,9 +152,9 @@ void update_removeOneAssetViaPatch() throws Exception { } @Test - void update_clearAllAssetsViaPatch() throws Exception { + void bulkRemove_clearsAllAssets() throws Exception { Metric metric = createMetric("metricassets_clear_" + suffix, assetA, assetB); - patchAssets(metric); + replaceAssets(metric); JsonNode assets = assetsOf(metric); assertThat(assets == null || assets.isEmpty()).isTrue(); } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/PersonaAIContextIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/PersonaAIContextIT.java index 44357a078379..1b7972ba8fa9 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/PersonaAIContextIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/mcp/PersonaAIContextIT.java @@ -27,13 +27,18 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.openmetadata.it.auth.JwtAuthProvider; +import org.openmetadata.schema.api.data.CreateMetric; import org.openmetadata.schema.api.teams.CreatePersona; import org.openmetadata.schema.api.teams.CreateTeam; import org.openmetadata.schema.api.teams.CreateUser; +import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.schema.entity.data.Table; import org.openmetadata.schema.entity.teams.Persona; import org.openmetadata.schema.entity.teams.User; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.PersonaContextDefinition; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; import org.openmetadata.schema.type.personaContext.ContextRule; import org.openmetadata.schema.type.personaContext.ContextSection; import org.openmetadata.service.Entity; @@ -42,6 +47,7 @@ class PersonaAIContextIT extends McpTestBase { private static Persona persona; private static Table table; + private static Metric metric; private static String directMemberToken; private static String inheritedMemberToken; private static String nonMemberToken; @@ -52,6 +58,7 @@ static void setup() throws Exception { initAuth(); String suffix = UUID.randomUUID().toString().substring(0, 8); table = createServiceDatabaseSchemaTable("persona_context_" + suffix); + metric = createMetricWithAsset(suffix); User directMember = createUser("persona_direct_" + suffix); User inheritedMember = createUser("persona_inherited_" + suffix); @@ -91,6 +98,41 @@ static void setup() throws Exception { post(contextPath() + "/rules", tableRule("Baseline tables"), PersonaContextDefinition.class); } + @Test + void metricKnowledgeRuleRendersAssetsFromTheBoundedRelationshipRepository() throws Exception { + String suffix = UUID.randomUUID().toString().substring(0, 8); + Persona metricPersona = + post( + "personas", + new CreatePersona() + .withName("metric_persona_context_" + suffix) + .withDescription("Metric asset persona context integration test"), + Persona.class); + String metricContextPath = "personas/" + metricPersona.getId() + "/aiContext"; + put( + metricContextPath, + new PersonaContextDefinition().withEnabled(true).withCharacterBudget(400_000), + PersonaContextDefinition.class); + ContextRule requested = metricRule("Revenue metric assets"); + PersonaContextDefinition created = + post(metricContextPath + "/rules", requested, PersonaContextDefinition.class); + ContextRule createdRule = + created.getRules().stream() + .filter(rule -> requested.getName().equals(rule.getName())) + .findFirst() + .orElseThrow(); + + try { + JsonNode document = post(metricContextPath + "/document:refresh", Map.of(), JsonNode.class); + assertThat(document.path("markdown").asText()) + .contains(metric.getFullyQualifiedName()) + .contains("### Related Assets") + .contains(table.getFullyQualifiedName()); + } finally { + deleteResponse(metricContextPath + "/rules/" + createdRule.getId()); + } + } + @Test void ruleCrudPreviewDocumentCacheAndMcpRoundTrip() throws Exception { ContextRule requested = tableRule("CRUD tables"); @@ -192,6 +234,23 @@ private static User createUser(String name) throws Exception { "users", new CreateUser().withName(name).withEmail(name + "@example.com"), User.class); } + private static Metric createMetricWithAsset(String suffix) throws Exception { + Metric created = + post( + "metrics", + new CreateMetric() + .withName("persona_context_metric_" + suffix) + .withDescription("Revenue metric used by persona context"), + Metric.class); + put( + "metrics/" + created.getName() + "/assets/add", + new BulkAssets() + .withAssets( + List.of(new EntityReference().withId(table.getId()).withType(Entity.TABLE))), + BulkOperationResult.class); + return created; + } + private static String tokenFor(User user) { return "Bearer " + JwtAuthProvider.tokenFor(user.getEmail(), user.getEmail(), new String[] {}, 3_600); @@ -210,6 +269,19 @@ private static ContextRule tableRule(String name) { .withEnabled(true); } + private static ContextRule metricRule(String name) { + return new ContextRule() + .withName(name) + .withEntityType(Entity.METRIC) + .withQueryFilter( + "{\"query\":{\"term\":{\"fullyQualifiedName\":\"" + + metric.getFullyQualifiedName() + + "\"}}}") + .withSections(Set.of(ContextSection.RELATED_ASSETS)) + .withMaxAssets(1) + .withEnabled(true); + } + private static String contextPath() { return "personas/" + persona.getId() + "/aiContext"; } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespace.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespace.java index 39311cc13407..e7e0102749bb 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespace.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespace.java @@ -4,10 +4,17 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLong; import org.openmetadata.schema.EntityInterface; public class TestNamespace { private static final String RUN_ID = UUID.randomUUID().toString().replaceAll("-", ""); + private static final AtomicLong UNIQUE_SHORT_ID_SEQUENCE = new AtomicLong(); + private static final String SHORT_ID_SEQUENCE_FORMAT = "%08x"; + private static final long SHORT_ID_SEQUENCE_MASK = 0xFFFFFFFFL; + private static final long SHORT_ID_SEQUENCE_STEP = 0x9E3779B9L; + private static final long SHORT_ID_SEQUENCE_OFFSET = + Long.parseUnsignedLong(RUN_ID.substring(8, 16), 16); private final String classId; private String methodId; private String cachedShortPrefix; @@ -83,15 +90,16 @@ public String shortPrefix(String base) { } /** - * Generate a unique short ID for each call. Use this when creating multiple independent entities - * within the same test method that need different names (e.g., multiple tables). + * Generates a compact ID without the repeated-zero runs that make fuzzy search queries expand + * past the engine clause limit. The odd step permutes the 32-bit counter space, so suffixes stay + * collision-free while their characters remain dispersed. */ public String uniqueShortId() { - String shortRun = RUN_ID.substring(0, 8); - String methodHash = - methodId != null ? Integer.toHexString(Math.abs(methodId.hashCode()) % 0xFFFF) : "0"; - String uniqueSuffix = java.util.UUID.randomUUID().toString().substring(0, 4); - return shortRun + methodHash + uniqueSuffix; + final String shortRun = RUN_ID.substring(0, 8); + final long sequence = UNIQUE_SHORT_ID_SEQUENCE.getAndIncrement(); + final long dispersedSequence = + (SHORT_ID_SEQUENCE_OFFSET + sequence * SHORT_ID_SEQUENCE_STEP) & SHORT_ID_SEQUENCE_MASK; + return shortRun + SHORT_ID_SEQUENCE_FORMAT.formatted(dispersedSequence); } public String runTagKey() { diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespaceTest.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespaceTest.java new file mode 100644 index 000000000000..380b4504a9f6 --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/util/TestNamespaceTest.java @@ -0,0 +1,50 @@ +package org.openmetadata.it.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.IntStream; +import org.junit.jupiter.api.Test; + +class TestNamespaceTest { + + private static final int IDENTIFIER_COUNT = 65_537; + private static final int IDENTIFIER_LENGTH = 16; + private static final int RUN_PREFIX_LENGTH = 8; + + @Test + void uniqueShortIdsRemainDistinctPastTheLegacyRandomSuffixSpace() { + final TestNamespace namespace = new TestNamespace("TestNamespaceTest"); + namespace.setMethodId("uniqueShortIdsRemainDistinctPastTheLegacyRandomSuffixSpace"); + final Set identifiers = ConcurrentHashMap.newKeySet(IDENTIFIER_COUNT); + + IntStream.range(0, IDENTIFIER_COUNT) + .parallel() + .forEach(ignored -> identifiers.add(namespace.uniqueShortId())); + + assertEquals(IDENTIFIER_COUNT, identifiers.size()); + assertTrue( + identifiers.stream().allMatch(identifier -> identifier.length() == IDENTIFIER_LENGTH)); + } + + @Test + void uniqueShortIdsDisperseTheCounterAcrossEverySuffixPosition() { + final TestNamespace namespace = new TestNamespace("TestNamespaceTest"); + final List identifiers = + IntStream.range(0, 256).mapToObj(ignored -> namespace.uniqueShortId()).toList(); + + IntStream.range(RUN_PREFIX_LENGTH, IDENTIFIER_LENGTH) + .forEach( + position -> + assertTrue( + identifiers.stream() + .mapToInt(identifier -> identifier.charAt(position)) + .distinct() + .count() + > 1, + "Expected suffix position %d to vary".formatted(position))); + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java b/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java index 8a9704974601..4c7dda38e359 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java @@ -180,6 +180,7 @@ public final class Entity { public static final String DATABASE = "database"; public static final String DATABASE_SCHEMA = "databaseSchema"; public static final String METRIC = "metric"; + public static final String METRIC_GROUP = "metricGroup"; public static final String DASHBOARD = "dashboard"; public static final String DASHBOARD_DATA_MODEL = "dashboardDataModel"; public static final String PIPELINE = "pipeline"; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/aicontext/PersonaContextBuilder.java b/openmetadata-service/src/main/java/org/openmetadata/service/aicontext/PersonaContextBuilder.java index a93232b1a1f9..f667ca47f135 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/aicontext/PersonaContextBuilder.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/aicontext/PersonaContextBuilder.java @@ -35,6 +35,7 @@ import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.openmetadata.schema.EntityInterface; +import org.openmetadata.schema.api.data.MetricAssetDirection; import org.openmetadata.schema.entity.data.GlossaryTerm; import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.schema.entity.data.Page; @@ -60,6 +61,7 @@ import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.jdbi3.CollectionDAO; import org.openmetadata.service.jdbi3.DataProductRepository; +import org.openmetadata.service.jdbi3.MetricRepository; import org.openmetadata.service.search.SearchRepository; import org.openmetadata.service.search.SearchResultListMapper; import org.openmetadata.service.search.SearchSortFilter; @@ -71,6 +73,7 @@ public class PersonaContextBuilder { static final int MAX_SHARED_KNOWLEDGE_ITEMS = 500; private static final int SEARCH_BATCH_SIZE = 100; private static final int DATA_PRODUCT_ASSET_BATCH_SIZE = 1000; + static final int METRIC_ASSET_BATCH_SIZE = 1000; private static final int DEFAULT_MAX_ASSETS = 200; private static final Set KNOWLEDGE_ENTITY_TYPES = Set.of(Entity.GLOSSARY_TERM, Entity.PAGE, Entity.METRIC); @@ -446,8 +449,7 @@ private SelectedEntity buildKnowledgeSelection(ContextRule rule, Map assets = new ArrayList<>(); + int offset = 0; + ResultList page; + do { + page = + repository.listAssets(metric.getId(), METRIC_ASSET_BATCH_SIZE, offset, null, null, null); + List linkedAssets = listOrEmpty(page.getData()); + linkedAssets.stream() + .map(MetricAssetDirection::getAsset) + .filter(asset -> asset != null) + .forEach(assets::add); + offset += linkedAssets.size(); + } while (hasNextMetricAssetPage(page, offset)); + metric.setAssets(List.copyOf(assets)); + } + + private static boolean hasNextMetricAssetPage(ResultList page, int offset) { + return page.getPaging() != null + && !nullOrEmpty(page.getData()) + && offset < page.getPaging().getTotal(); + } + + static String knowledgeFields(String entityType) { return switch (entityType) { case Entity.PAGE -> "owners,tags,relatedEntities"; - case Entity.METRIC -> "owners,tags,assets,relatedMetrics"; + case Entity.METRIC -> "owners,tags,relatedMetrics"; case Entity.GLOSSARY_TERM -> "owners,tags,relatedTerms"; default -> ""; }; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImpl.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImpl.java index ed6a16cbdac1..254aa335926f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImpl.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImpl.java @@ -1,277 +1,286 @@ +/* + * Copyright 2026 Collate + * 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. + */ package org.openmetadata.service.governance.workflows.elements.nodes.automatedTask.impl; +import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty; import static org.openmetadata.service.governance.workflows.Workflow.RELATED_ENTITY_VARIABLE; import static org.openmetadata.service.governance.workflows.Workflow.UPDATED_BY_VARIABLE; -import static org.openmetadata.service.governance.workflows.Workflow.WORKFLOW_INSTANCE_EXECUTION_ID_VARIABLE; +import jakarta.json.JsonPatch; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; -import java.util.UUID; +import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.flowable.common.engine.api.delegate.Expression; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.JavaDelegate; import org.openmetadata.schema.EntityInterface; +import org.openmetadata.schema.type.ChangeDescription; import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.EntityStatus; +import org.openmetadata.schema.type.FieldChange; import org.openmetadata.schema.type.Include; import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.service.Entity; -import org.openmetadata.service.governance.workflows.Workflow; +import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.governance.workflows.WorkflowVariableHandler; import org.openmetadata.service.governance.workflows.WorkflowVariableHandler.InputNamespaces; import org.openmetadata.service.jdbi3.EntityRepository; import org.openmetadata.service.resources.feeds.MessageParser; +import org.openmetadata.service.security.policyevaluator.SubjectContext; @Slf4j public class RollbackEntityImpl implements JavaDelegate { - private Workflow workflow; + private static final String GOVERNANCE_BOT = "governance-bot"; + private static final String ROLLBACK_ACTION_VARIABLE = "rollbackAction"; + private static final String ROLLBACK_FROM_VERSION_VARIABLE = "rollbackFromVersion"; + private static final String ROLLBACK_TO_VERSION_VARIABLE = "rollbackToVersion"; + private static final String ROLLBACK_ENTITY_ID_VARIABLE = "rollbackEntityId"; + private static final String ROLLBACK_ENTITY_TYPE_VARIABLE = "rollbackEntityType"; + private static final String ROLLBACK_ACTION = "rollback"; + private static final String REJECT_ACTION = "reject"; + private Expression inputNamespaceMapExpr; @Deprecated @SuppressWarnings("unused") - private org.flowable.common.engine.api.delegate.Expression rollbackToStatus; + private Expression rollbackToStatus; @Override public void execute(DelegateExecution execution) { try { - WorkflowVariableHandler varHandler = new WorkflowVariableHandler(execution); - - InputNamespaces inputNamespaces = InputNamespaces.from(inputNamespaceMapExpr, execution); - - Object workflowInstanceExecutionIdObj = - execution.getVariable(WORKFLOW_INSTANCE_EXECUTION_ID_VARIABLE); - String workflowInstanceExecutionId = - workflowInstanceExecutionIdObj instanceof UUID - ? workflowInstanceExecutionIdObj.toString() - : (String) workflowInstanceExecutionIdObj; - - MessageParser.EntityLink entityLink = - MessageParser.EntityLink.parse( - (String) - varHandler.getNamespacedVariable( - inputNamespaces.namespaceFor(RELATED_ENTITY_VARIABLE), - RELATED_ENTITY_VARIABLE)); - - String updatedBy = - (String) - varHandler.getNamespacedVariable( - inputNamespaces.namespaceFor(UPDATED_BY_VARIABLE), UPDATED_BY_VARIABLE); - if (updatedBy == null || updatedBy.isEmpty()) { - updatedBy = "governance-bot"; - } - - EntityInterface currentEntity = varHandler.getRelatedEntity(entityLink, "", Include.ALL); - - String entityType = currentEntity.getEntityReference().getType(); - UUID entityId = currentEntity.getId(); - - LOG.info( - "[RollbackEntity] Rolling back entity: {} ({}), Workflow Instance: {}", - currentEntity.getName(), - entityId, - workflowInstanceExecutionId); + RollbackContext context = createContext(execution); + RejectionOutcome outcome = + applyRejection(context.repository(), context.currentEntity(), context.updatedBy()); + setOutcomeVariables(execution, context, outcome); + } catch (RuntimeException exception) { + LOG.error("[RollbackEntity] Entity rejection failed", exception); + throw new IllegalStateException( + "Failed to reject entity through rollback workflow", exception); + } + } - EntityRepository repository = Entity.getEntityRepository(entityType); + RejectionOutcome applyRejection( + EntityRepository repository, EntityInterface currentEntity, String updatedBy) { + Optional approvedVersion = + findMostRecentApprovedVersion(currentEntity, repository); + RejectionOutcome outcome; + if (approvedVersion.isPresent()) { + ApprovedVersion approved = approvedVersion.get(); + restoreToApprovedVersion(repository, currentEntity, approved.entity(), updatedBy); + outcome = RejectionOutcome.rolledBack(currentEntity.getVersion(), approved.version()); + } else { + rejectCurrentVersion(repository, currentEntity, updatedBy); + outcome = RejectionOutcome.rejected(currentEntity.getVersion()); + } + return outcome; + } - Double previousVersion = getPreviousApprovedVersion(currentEntity, repository); - if (previousVersion == null) { - LOG.warn( - "[RollbackEntity] No previous approved version found for entity: {} ({})", - currentEntity.getName(), - entityId); - return; + Optional findMostRecentApprovedVersion( + EntityInterface currentEntity, EntityRepository repository) { + List earlierVersions = earlierVersions(currentEntity, repository); + Optional approvedVersion = Optional.empty(); + for (Double version : earlierVersions) { + EntityInterface versionEntity = + repository.getVersion(currentEntity.getId(), version.toString()); + if (isApprovedBaseline(versionEntity)) { + approvedVersion = Optional.of(new ApprovedVersion(version, versionEntity)); + break; } + } + return approvedVersion; + } - EntityInterface previousEntity = repository.getVersion(entityId, previousVersion.toString()); - - LOG.info( - "[RollbackEntity] Rolling back entity {} from version {} to version {}", - currentEntity.getName(), - currentEntity.getVersion(), - previousVersion); - - restoreToPreviousVersion(repository, currentEntity, previousEntity, updatedBy); + private RollbackContext createContext(DelegateExecution execution) { + WorkflowVariableHandler variableHandler = new WorkflowVariableHandler(execution); + InputNamespaces namespaces = InputNamespaces.from(inputNamespaceMapExpr, execution); + MessageParser.EntityLink entityLink = relatedEntityLink(variableHandler, namespaces); + EntityInterface entity = variableHandler.getRelatedEntity(entityLink, "", Include.ALL); + String updatedBy = updatedBy(variableHandler, namespaces); + String entityType = entityLink.getEntityType(); + EntityRepository repository = Entity.getEntityRepository(entityType); + return new RollbackContext(entity, repository, entityType, updatedBy); + } - execution.setVariable("rollbackAction", "rollback"); - execution.setVariable("rollbackFromVersion", currentEntity.getVersion()); - execution.setVariable("rollbackToVersion", previousVersion); - execution.setVariable("rollbackEntityId", entityId.toString()); - execution.setVariable("rollbackEntityType", entityType); + private MessageParser.EntityLink relatedEntityLink( + WorkflowVariableHandler variableHandler, InputNamespaces namespaces) { + String namespace = namespaces.namespaceFor(RELATED_ENTITY_VARIABLE); + String value = + (String) variableHandler.getNamespacedVariable(namespace, RELATED_ENTITY_VARIABLE); + return MessageParser.EntityLink.parse(value); + } - LOG.info( - "[RollbackEntity] Successfully rolled back entity: {} ({}) to version {}", - currentEntity.getName(), - entityId, - previousVersion); + private String updatedBy(WorkflowVariableHandler variableHandler, InputNamespaces namespaces) { + String namespace = namespaces.namespaceFor(UPDATED_BY_VARIABLE); + String user = (String) variableHandler.getNamespacedVariable(namespace, UPDATED_BY_VARIABLE); + return nullOrEmpty(user) ? GOVERNANCE_BOT : user; + } - } catch (Exception e) { - LOG.error("[RollbackEntity] Error during entity rollback: {}", e.getMessage(), e); - throw new RuntimeException("Failed to rollback entity", e); + private List earlierVersions( + EntityInterface currentEntity, EntityRepository repository) { + EntityHistory history = repository.listVersions(currentEntity.getId()); + List versions = new ArrayList<>(); + for (Object serializedVersion : history.getVersions()) { + parsedVersion(serializedVersion, currentEntity) + .filter(version -> version < currentEntity.getVersion()) + .ifPresent(versions::add); } + versions.sort(Comparator.reverseOrder()); + return versions; } - private Double getPreviousApprovedVersion( - EntityInterface entity, EntityRepository repository) { + private Optional parsedVersion(Object serializedVersion, EntityInterface currentEntity) { + Optional version; try { - UUID entityId = entity.getId(); - EntityHistory history = repository.listVersions(entityId); - Double currentVersion = entity.getVersion(); - List versionNumbers = new ArrayList<>(); - for (Object versionObj : history.getVersions()) { - try { - String versionJson; - if (versionObj instanceof String) { - versionJson = (String) versionObj; - } else { - versionJson = JsonUtils.pojoToJson(versionObj); - } - - EntityInterface versionEntity = JsonUtils.readValue(versionJson, entity.getClass()); - Double versionNumber = versionEntity.getVersion(); - - if (versionNumber < currentVersion) { - versionNumbers.add(versionNumber); - } - } catch (Exception e) { - LOG.warn("Could not parse version: {}", e.getMessage()); - continue; - } - } + String json = + serializedVersion instanceof String serialized + ? serialized + : JsonUtils.pojoToJson(serializedVersion); + EntityInterface entity = JsonUtils.readValue(json, currentEntity.getClass()); + version = Optional.ofNullable(entity.getVersion()); + } catch (RuntimeException exception) { + LOG.warn("[RollbackEntity] Ignoring an unreadable entity version", exception); + version = Optional.empty(); + } + return version; + } - versionNumbers.sort((v1, v2) -> Double.compare(v2, v1)); + private boolean isApprovedBaseline(EntityInterface entity) { + // A non-reviewer edit inherits Approved until its asynchronous workflow marks it In Review. + // Only an actual approval event (or reviewer-authored change) is safe to restore later. + boolean isApproved = entity.getEntityStatus() == EntityStatus.APPROVED; + boolean hasDurableApproval = + nullOrEmpty(entity.getReviewers()) + || recordsApprovalTransition(entity) + || wasUpdatedByReviewer(entity); + return isApproved && hasDurableApproval; + } - for (Double versionNumber : versionNumbers) { - try { - EntityInterface fullVersionEntity = - repository.getVersion(entityId, versionNumber.toString()); + private boolean recordsApprovalTransition(EntityInterface entity) { + ChangeDescription change = entity.getIncrementalChangeDescription(); + if (change == null) { + change = entity.getChangeDescription(); + } + List updatedFields = change == null ? List.of() : change.getFieldsUpdated(); + return !nullOrEmpty(updatedFields) && updatedFields.stream().anyMatch(this::setsApprovedStatus); + } - try { - java.lang.reflect.Method getStatusMethod = - fullVersionEntity.getClass().getMethod("getEntityStatus"); - Object statusObj = getStatusMethod.invoke(fullVersionEntity); - LOG.debug( - "[RollbackEntity] Checking {} version {} - Status: {}", - fullVersionEntity.getClass().getSimpleName(), - versionNumber, - statusObj != null ? statusObj.toString() : "null"); - } catch (NoSuchMethodException e) { - LOG.debug( - "[RollbackEntity] {} version {} - No entityStatus field", - fullVersionEntity.getClass().getSimpleName(), - versionNumber); - } catch (Exception e) { - LOG.debug( - "[RollbackEntity] Could not get status for {} version {}", - fullVersionEntity.getClass().getSimpleName(), - versionNumber); - } + private boolean setsApprovedStatus(FieldChange change) { + return Entity.FIELD_ENTITY_STATUS.equals(change.getName()) + && EntityStatus.APPROVED.value().equals(String.valueOf(change.getNewValue())); + } - String status = getRollbackStatus(fullVersionEntity); - if (status != null) { - LOG.info( - "[RollbackEntity] Found {} version {} for entity: {} ({})", - status, - versionNumber, - entity.getName(), - entityId); - return versionNumber; - } else { - LOG.debug( - "[RollbackEntity] Skipping version {} - not in Approved/Rejected status", - versionNumber); - } - } catch (Exception e) { - LOG.warn("Could not load version {}: {}", versionNumber, e.getMessage()); - continue; - } + private boolean wasUpdatedByReviewer(EntityInterface entity) { + List reviewers = entity.getReviewers(); + String updatedBy = entity.getUpdatedBy(); + boolean isReviewer = false; + if (!nullOrEmpty(reviewers) && !nullOrEmpty(updatedBy)) { + isReviewer = reviewers.stream().anyMatch(reviewer -> matchesUser(reviewer, updatedBy)); + if (!isReviewer && reviewers.stream().anyMatch(this::isTeam)) { + isReviewer = belongsToReviewerTeam(updatedBy, reviewers); } - - LOG.warn( - "[RollbackEntity] No approved or rejected version found in history for entity: {} ({})", - entity.getName(), - entityId); - return null; - } catch (Exception e) { - LOG.error("Error finding previous approved or rejected version", e); - return null; } + return isReviewer; } - private String getRollbackStatus(EntityInterface entity) { - try { - java.lang.reflect.Method getStatusMethod = entity.getClass().getMethod("getEntityStatus"); - Object statusObj = getStatusMethod.invoke(entity); - - if (statusObj == null) { - LOG.warn( - "[RollbackEntity] Status is null for {} version {}", - entity.getClass().getSimpleName(), - entity.getVersion()); - return null; - } + private boolean matchesUser(EntityReference reviewer, String user) { + return Entity.USER.equals(reviewer.getType()) + && (user.equals(reviewer.getName()) || user.equals(reviewer.getFullyQualifiedName())); + } - if (statusObj instanceof EntityStatus status) { - LOG.debug( - "[RollbackEntity] Checking status: '{}' for version {}", status, entity.getVersion()); + private boolean isTeam(EntityReference reviewer) { + return Entity.TEAM.equals(reviewer.getType()); + } - if (status == EntityStatus.APPROVED) { - return "Approved"; - } else if (status == EntityStatus.REJECTED) { - return "Rejected"; - } + private boolean belongsToReviewerTeam(String user, List reviewers) { + boolean isReviewer = false; + try { + isReviewer = SubjectContext.getSubjectContext(user).isReviewer(reviewers); + } catch (EntityNotFoundException exception) { + LOG.debug("[RollbackEntity] Historical reviewer '{}' no longer exists", user); + } + return isReviewer; + } - LOG.debug( - "[RollbackEntity] Skipping version {} with status '{}' - not a rollback target", - entity.getVersion(), - status); + private void restoreToApprovedVersion( + EntityRepository repository, + EntityInterface currentEntity, + EntityInterface approvedEntity, + String updatedBy) { + EntityInterface persistedCurrent = persistedCurrentVersion(repository, currentEntity); + applyPatch(repository, persistedCurrent, approvedEntity, updatedBy); + } - return null; - } + private void rejectCurrentVersion( + EntityRepository repository, EntityInterface currentEntity, String updatedBy) { + EntityInterface persistedCurrent = persistedCurrentVersion(repository, currentEntity); + String currentJson = JsonUtils.pojoToJson(persistedCurrent); + EntityInterface rejectedEntity = JsonUtils.readValue(currentJson, persistedCurrent.getClass()); + setRejectedStatus(rejectedEntity); + applyPatch(repository, persistedCurrent, rejectedEntity, updatedBy); + } - LOG.warn( - "[RollbackEntity] Unexpected status type for {}: {}", - entity.getClass().getSimpleName(), - statusObj.getClass().getName()); - return null; + private EntityInterface persistedCurrentVersion( + EntityRepository repository, EntityInterface currentEntity) { + return repository.getVersion(currentEntity.getId(), currentEntity.getVersion().toString()); + } - } catch (NoSuchMethodException e) { - LOG.debug( - "[RollbackEntity] Entity type {} doesn't have entityStatus field, treating as approved", - entity.getClass().getSimpleName()); - return "Approved"; - } catch (Exception e) { - LOG.error( - "[RollbackEntity] Error checking entity status for {}", - entity.getClass().getSimpleName(), - e); - return null; + private void setRejectedStatus(EntityInterface entity) { + entity.setEntityStatus(EntityStatus.REJECTED); + if (entity.getEntityStatus() != EntityStatus.REJECTED) { + throw new IllegalStateException("Entity does not support a rejected approval status"); } } - private void restoreToPreviousVersion( + private void applyPatch( EntityRepository repository, EntityInterface currentEntity, - EntityInterface previousEntity, + EntityInterface targetEntity, String updatedBy) { - try { - currentEntity = - repository.getVersion(currentEntity.getId(), currentEntity.getVersion().toString()); + JsonPatch patch = + JsonUtils.getJsonPatch( + JsonUtils.pojoToJson(currentEntity), JsonUtils.pojoToJson(targetEntity)); + repository.patch(null, currentEntity.getFullyQualifiedName(), updatedBy, patch); + } - String currentJson = JsonUtils.pojoToJson(currentEntity); - String previousJson = JsonUtils.pojoToJson(previousEntity); - jakarta.json.JsonPatch patch = JsonUtils.getJsonPatch(currentJson, previousJson); + private void setOutcomeVariables( + DelegateExecution execution, RollbackContext context, RejectionOutcome outcome) { + execution.setVariable(ROLLBACK_ACTION_VARIABLE, outcome.action()); + execution.setVariable(ROLLBACK_FROM_VERSION_VARIABLE, outcome.fromVersion()); + if (outcome.toVersion() != null) { + execution.setVariable(ROLLBACK_TO_VERSION_VARIABLE, outcome.toVersion()); + } + execution.setVariable(ROLLBACK_ENTITY_ID_VARIABLE, context.currentEntity().getId().toString()); + execution.setVariable(ROLLBACK_ENTITY_TYPE_VARIABLE, context.entityType()); + } - repository.patch(null, currentEntity.getFullyQualifiedName(), updatedBy, patch); + record ApprovedVersion(Double version, EntityInterface entity) {} - LOG.info( - "[RollbackEntity] Successfully applied rollback patch for entity: {} ({})", - currentEntity.getName(), - currentEntity.getId()); + record RejectionOutcome(String action, Double fromVersion, Double toVersion) { + private static RejectionOutcome rolledBack(Double fromVersion, Double toVersion) { + return new RejectionOutcome(ROLLBACK_ACTION, fromVersion, toVersion); + } - } catch (Exception e) { - LOG.error("[RollbackEntity] Failed to restore entity to previous version", e); - throw new RuntimeException("Failed to restore entity to previous version", e); + private static RejectionOutcome rejected(Double fromVersion) { + return new RejectionOutcome(REJECT_ACTION, fromVersion, null); } } + + private record RollbackContext( + EntityInterface currentEntity, + EntityRepository repository, + String entityType, + String updatedBy) {} } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTask.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTask.java index 777e13ba4edc..7cf79021da48 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTask.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTask.java @@ -781,6 +781,7 @@ static boolean isSupersedablePriorApprovalTask( && currentWorkflowDefinitionId != null && prior.getWorkflowInstanceId() != null && !isTerminalTaskStatus(prior.getStatus()) + && prior.getResolution() == null && !prior.getWorkflowInstanceId().equals(currentWorkflowInstanceId) && currentWorkflowDefinitionId.equals(resolvePriorWorkflowDefinitionId(prior)); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CoreRelationshipDAOs.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CoreRelationshipDAOs.java index 125be9fd9367..12bcab87f253 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CoreRelationshipDAOs.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CoreRelationshipDAOs.java @@ -508,8 +508,8 @@ default void bulkRemoveFromRelationship( @ConnectionAwareSqlUpdate( value = "INSERT INTO entity_relationship(fromId, toId, fromEntity, toEntity, relation, relationType, json) " - + "VALUES (:fromId, :toId, :fromEntity, :toEntity, :relation, :relationType, :json) " - + "ON DUPLICATE KEY UPDATE json = :json", + + "VALUES (:fromId, :toId, :fromEntity, :toEntity, :relation, :relationType, CONVERT(:json USING utf8mb4)) " + + "ON DUPLICATE KEY UPDATE json = VALUES(json)", connectionType = MYSQL) @ConnectionAwareSqlUpdate( value = @@ -1018,6 +1018,24 @@ List countNonDeletedChildFilesBatch( @Bind("relation") int relation, @Bind("toEntity") String toEntity); + @SqlQuery( + "SELECT COUNT(*) FROM entity_relationship er " + + "JOIN metric_entity me ON er.toId = me.id " + + "WHERE er.fromId = :fromId AND er.fromEntity = 'metric' AND er.relation = :relation " + + "AND er.toEntity = 'metric' AND (me.deleted = false OR me.deleted IS NULL)") + int countNonDeletedChildMetrics( + @BindUUID("fromId") UUID fromId, @Bind("relation") int relation); + + @SqlQuery( + "SELECT er.fromId, COUNT(er.toId) FROM entity_relationship er " + + "JOIN metric_entity me ON er.toId = me.id " + + "WHERE er.fromId IN () AND er.fromEntity = 'metric' AND er.relation = :relation " + + "AND er.toEntity = 'metric' AND (me.deleted = false OR me.deleted IS NULL) " + + "GROUP BY er.fromId") + @RegisterRowMapper(ToRelationshipCountMapper.class) + List countNonDeletedChildMetricsBatch( + @BindList("fromIds") List fromIds, @Bind("relation") int relation); + @SqlQuery( "SELECT er.fromId, COUNT(er.toId) FROM entity_relationship er " + "JOIN test_case tc ON er.toId = tc.id " diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityDataDAOs.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityDataDAOs.java index a95ea588704e..b6f740d8a587 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityDataDAOs.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityDataDAOs.java @@ -32,10 +32,12 @@ import org.jdbi.v3.sqlobject.CreateSqlObject; import org.jdbi.v3.sqlobject.config.RegisterRowMapper; import org.jdbi.v3.sqlobject.customizer.Bind; +import org.jdbi.v3.sqlobject.customizer.BindList; import org.jdbi.v3.sqlobject.customizer.BindMap; import org.jdbi.v3.sqlobject.customizer.Define; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; +import org.jdbi.v3.sqlobject.statement.UseRowMapper; import org.openmetadata.schema.entity.Bot; import org.openmetadata.schema.entity.app.App; import org.openmetadata.schema.entity.app.AppMarketPlaceDefinition; @@ -43,6 +45,7 @@ import org.openmetadata.schema.entity.data.Glossary; import org.openmetadata.schema.entity.data.GlossaryTerm; import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; import org.openmetadata.schema.entity.data.MlModel; import org.openmetadata.schema.entity.data.Pipeline; import org.openmetadata.schema.entity.data.Query; @@ -55,11 +58,16 @@ import org.openmetadata.schema.entity.services.PipelineService; import org.openmetadata.schema.entity.services.ingestionPipelines.IngestionPipeline; import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Relationship; import org.openmetadata.service.Entity; +import org.openmetadata.service.jdbi3.CoreRelationshipDAOs.EntityRelationshipCount; +import org.openmetadata.service.jdbi3.CoreRelationshipDAOs.EntityRelationshipDAO; +import org.openmetadata.service.jdbi3.CoreRelationshipDAOs.EntityRelationshipObject; import org.openmetadata.service.jdbi3.locator.ConnectionAwareSqlQuery; import org.openmetadata.service.resources.databases.DatasourceConfig; import org.openmetadata.service.util.FullyQualifiedName; import org.openmetadata.service.util.jdbi.BindConcat; +import org.openmetadata.service.util.jdbi.BindUUID; public interface EntityDataDAOs { @CreateSqlObject @@ -71,6 +79,9 @@ public interface EntityDataDAOs { @CreateSqlObject MetricDAO metricDAO(); + @CreateSqlObject + MetricGroupDAO metricGroupDAO(); + @CreateSqlObject ChartDAO chartDAO(); @@ -206,7 +217,300 @@ default Class getEntityClass() { } } + interface MetricGroupDAO extends EntityDAO { + String MEMBER_MATCH_MYSQL = + "(LOWER(me.name) LIKE :nameLike ESCAPE '!' " + + "OR LOWER(COALESCE(JSON_UNQUOTE(JSON_EXTRACT(me.json, '$.displayName')), '')) " + + "LIKE :nameLike ESCAPE '!')"; + String MEMBER_MATCH_POSTGRES = + "(LOWER(me.name) LIKE :nameLike ESCAPE '!' " + + "OR LOWER(COALESCE(me.json ->> 'displayName', '')) LIKE :nameLike ESCAPE '!')"; + + @Override + default String getTableName() { + return "metric_group_entity"; + } + + @Override + default Class getEntityClass() { + return MetricGroup.class; + } + + @Override + default String getNameHashColumn() { + return "fqnHash"; + } + + @ConnectionAwareSqlQuery( + value = + "SELECT me.json FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :groupId AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_MYSQL + + " ORDER BY me.name, me.id LIMIT :limit OFFSET :offset", + connectionType = MYSQL) + @ConnectionAwareSqlQuery( + value = + "SELECT me.json FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :groupId AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_POSTGRES + + " ORDER BY me.name, me.id LIMIT :limit OFFSET :offset", + connectionType = POSTGRES) + List listMemberJsons( + @BindUUID("groupId") UUID groupId, + @Bind("relation") int relation, + @Bind("nameLike") String nameLike, + @Bind("limit") int limit, + @Bind("offset") int offset); + + @ConnectionAwareSqlQuery( + value = + "SELECT COUNT(*) FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :groupId AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_MYSQL, + connectionType = MYSQL) + @ConnectionAwareSqlQuery( + value = + "SELECT COUNT(*) FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :groupId AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_POSTGRES, + connectionType = POSTGRES) + int countMembers( + @BindUUID("groupId") UUID groupId, + @Bind("relation") int relation, + @Bind("nameLike") String nameLike); + + @SqlQuery( + "SELECT me.id FROM entity_relationship group_rel " + + "JOIN metric_entity me ON me.id = group_rel.toId " + + "WHERE group_rel.fromId = :groupId AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND me.id <> :excludeId AND (me.deleted = FALSE OR me.deleted IS NULL) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = me.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation) " + + "ORDER BY me.name, me.id LIMIT :limit OFFSET :offset") + List listRootMemberIds( + @BindUUID("groupId") UUID groupId, + @BindUUID("excludeId") UUID excludeId, + @Bind("hasRelation") int hasRelation, + @Bind("containsRelation") int containsRelation, + @Bind("limit") int limit, + @Bind("offset") int offset); + + @SqlQuery( + "SELECT COUNT(*) FROM entity_relationship group_rel " + + "JOIN metric_entity me ON me.id = group_rel.toId " + + "WHERE group_rel.fromId = :groupId AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND me.id <> :excludeId AND (me.deleted = FALSE OR me.deleted IS NULL) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = me.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation)") + int countRootMembers( + @BindUUID("groupId") UUID groupId, + @BindUUID("excludeId") UUID excludeId, + @Bind("hasRelation") int hasRelation, + @Bind("containsRelation") int containsRelation); + + @SqlQuery( + "SELECT COUNT(*) FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :groupId AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL)") + int countNonDeletedMembers(@BindUUID("groupId") UUID groupId, @Bind("relation") int relation); + + @SqlQuery( + "SELECT er.fromId, COUNT(er.toId) FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId IN () AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) GROUP BY er.fromId") + @RegisterRowMapper(EntityRelationshipDAO.ToRelationshipCountMapper.class) + List countNonDeletedMembersBatch( + @BindList("groupIds") List groupIds, @Bind("relation") int relation); + + @ConnectionAwareSqlQuery( + value = + "SELECT me.json FROM entity_relationship group_rel " + + "JOIN metric_entity me ON me.id = group_rel.toId " + + "WHERE group_rel.fromId = :groupId AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_MYSQL + + " AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = me.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation) " + + "ORDER BY me.name, me.id LIMIT :limit OFFSET :offset", + connectionType = MYSQL) + @ConnectionAwareSqlQuery( + value = + "SELECT me.json FROM entity_relationship group_rel " + + "JOIN metric_entity me ON me.id = group_rel.toId " + + "WHERE group_rel.fromId = :groupId AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_POSTGRES + + " AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = me.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation) " + + "ORDER BY me.name, me.id LIMIT :limit OFFSET :offset", + connectionType = POSTGRES) + List listRootMemberJsonsPage( + @BindUUID("groupId") UUID groupId, + @Bind("hasRelation") int hasRelation, + @Bind("containsRelation") int containsRelation, + @Bind("nameLike") String nameLike, + @Bind("limit") int limit, + @Bind("offset") int offset); + + @ConnectionAwareSqlQuery( + value = + "SELECT COUNT(*) FROM entity_relationship group_rel " + + "JOIN metric_entity me ON me.id = group_rel.toId " + + "WHERE group_rel.fromId = :groupId AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_MYSQL + + " AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = me.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation)", + connectionType = MYSQL) + @ConnectionAwareSqlQuery( + value = + "SELECT COUNT(*) FROM entity_relationship group_rel " + + "JOIN metric_entity me ON me.id = group_rel.toId " + + "WHERE group_rel.fromId = :groupId AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) AND " + + MEMBER_MATCH_POSTGRES + + " AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = me.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation)", + connectionType = POSTGRES) + int countRootMembersPage( + @BindUUID("groupId") UUID groupId, + @Bind("hasRelation") int hasRelation, + @Bind("containsRelation") int containsRelation, + @Bind("nameLike") String nameLike); + } + interface MetricDAO extends EntityDAO { + String HIERARCHY_CTE = + "WITH RECURSIVE metric_tree(root_id, member_id) AS (" + + "SELECT root.id, root.id FROM metric_entity root " + + "WHERE (root.deleted = FALSE OR root.deleted IS NULL) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = root.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation) " + + "UNION SELECT tree.root_id, child.id FROM metric_tree tree " + + "JOIN entity_relationship child_rel ON child_rel.fromId = tree.member_id " + + "AND child_rel.fromEntity = 'metric' AND child_rel.toEntity = 'metric' " + + "AND child_rel.relation = :containsRelation " + + "JOIN metric_entity child ON child.id = child_rel.toId " + + "WHERE (child.deleted = FALSE OR child.deleted IS NULL)) "; + String HIERARCHY_GROUP_MEMBER_EXISTS = + " OR EXISTS (SELECT 1 FROM entity_relationship group_member " + + "JOIN metric_entity member ON member.id = group_member.toId " + + "WHERE group_member.fromId = mg.id AND group_member.fromEntity = 'metricGroup' " + + "AND group_member.toEntity = 'metric' AND group_member.relation = :hasRelation " + + "AND (member.deleted = FALSE OR member.deleted IS NULL) AND "; + String HIERARCHY_STANDALONE_ROOT = + " UNION ALL SELECT m.id AS hierarchy_id, m.name AS hierarchy_name, " + + "'metric' AS entity_type FROM metric_entity m " + + "WHERE (m.deleted = FALSE OR m.deleted IS NULL) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = m.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship group_rel " + + "JOIN metric_group_entity active_group ON active_group.id = group_rel.fromId " + + "WHERE group_rel.toId = m.id AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND (active_group.deleted = FALSE OR active_group.deleted IS NULL)) " + + "AND EXISTS (SELECT 1 FROM metric_tree tree " + + "JOIN metric_entity member ON member.id = tree.member_id " + + "WHERE tree.root_id = m.id AND "; + String HIERARCHY_STANDALONE_ROOT_COUNT = + " UNION ALL SELECT m.id AS hierarchy_id FROM metric_entity m " + + "WHERE (m.deleted = FALSE OR m.deleted IS NULL) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship parent_rel " + + "WHERE parent_rel.toId = m.id AND parent_rel.fromEntity = 'metric' " + + "AND parent_rel.toEntity = 'metric' AND parent_rel.relation = :containsRelation) " + + "AND NOT EXISTS (SELECT 1 FROM entity_relationship group_rel " + + "JOIN metric_group_entity active_group ON active_group.id = group_rel.fromId " + + "WHERE group_rel.toId = m.id AND group_rel.fromEntity = 'metricGroup' " + + "AND group_rel.toEntity = 'metric' AND group_rel.relation = :hasRelation " + + "AND (active_group.deleted = FALSE OR active_group.deleted IS NULL)) " + + "AND EXISTS (SELECT 1 FROM metric_tree tree " + + "JOIN metric_entity member ON member.id = tree.member_id " + + "WHERE tree.root_id = m.id AND "; + String HIERARCHY_GROUP_MATCH_MYSQL = + "(LOWER(mg.name) LIKE :nameLike ESCAPE '!' " + + "OR LOWER(COALESCE(JSON_UNQUOTE(JSON_EXTRACT(mg.json, '$.displayName')), '')) " + + "LIKE :nameLike ESCAPE '!')"; + String HIERARCHY_GROUP_MATCH_POSTGRES = + "(LOWER(mg.name) LIKE :nameLike ESCAPE '!' " + + "OR LOWER(COALESCE(mg.json ->> 'displayName', '')) LIKE :nameLike ESCAPE '!')"; + String HIERARCHY_MEMBER_MATCH_MYSQL = + "(LOWER(member.name) LIKE :nameLike ESCAPE '!' " + + "OR LOWER(COALESCE(JSON_UNQUOTE(JSON_EXTRACT(member.json, '$.displayName')), '')) " + + "LIKE :nameLike ESCAPE '!')"; + String HIERARCHY_MEMBER_MATCH_POSTGRES = + "(LOWER(member.name) LIKE :nameLike ESCAPE '!' " + + "OR LOWER(COALESCE(member.json ->> 'displayName', '')) LIKE :nameLike ESCAPE '!')"; + + record HierarchyRow(UUID id, String entityType) {} + + @SqlQuery("SELECT id FROM metric_entity WHERE id IN () ORDER BY id FOR UPDATE") + List lockForGroupAssignment(@BindList("metricIds") List metricIds); + + @SqlQuery( + "SELECT mg.id FROM entity_relationship er " + + "JOIN metric_group_entity mg ON mg.id = er.fromId " + + "WHERE er.toId = :metricId AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :hasRelation " + + "AND (mg.deleted = FALSE OR mg.deleted IS NULL) LIMIT 1") + String findActiveGroupId( + @BindUUID("metricId") UUID metricId, @Bind("hasRelation") int hasRelation); + + @SqlQuery( + "SELECT er.fromId, er.toId, er.fromEntity, er.toEntity, er.relation, er.json, er.jsonSchema " + + "FROM entity_relationship er " + + "JOIN metric_group_entity mg ON mg.id = er.fromId " + + "WHERE er.toId IN () AND er.fromEntity = 'metricGroup' " + + "AND er.toEntity = 'metric' AND er.relation = :hasRelation " + + "AND er.deleted = FALSE AND (mg.deleted = FALSE OR mg.deleted IS NULL)") + @UseRowMapper(EntityRelationshipDAO.RelationshipObjectMapper.class) + List findActiveGroupsInternal( + @BindList("metricIds") List metricIds, @Bind("hasRelation") int hasRelation); + + default List findActiveGroups( + List metricIds, int hasRelation) { + return EntityDAO.queryInChunks( + metricIds, chunk -> findActiveGroupsInternal(chunk, hasRelation)); + } + + class HierarchyRowMapper implements RowMapper { + @Override + public HierarchyRow map(ResultSet resultSet, StatementContext context) throws SQLException { + return new HierarchyRow( + UUID.fromString(resultSet.getString("hierarchy_id")), + resultSet.getString("entity_type")); + } + } + @Override default String getTableName() { return "metric_entity"; @@ -222,6 +526,211 @@ default String getNameHashColumn() { return "fqnHash"; } + @ConnectionAwareSqlQuery( + value = + HIERARCHY_CTE + + "SELECT hierarchy_id, entity_type FROM (" + + "SELECT mg.id AS hierarchy_id, mg.name AS hierarchy_name, 'metricGroup' AS entity_type " + + "FROM metric_group_entity mg WHERE (mg.deleted = FALSE OR mg.deleted IS NULL) " + + "AND (" + + HIERARCHY_GROUP_MATCH_MYSQL + + HIERARCHY_GROUP_MEMBER_EXISTS + + HIERARCHY_MEMBER_MATCH_MYSQL + + "))" + + HIERARCHY_STANDALONE_ROOT + + HIERARCHY_MEMBER_MATCH_MYSQL + + ")) hierarchy_items " + + "ORDER BY hierarchy_name, entity_type, hierarchy_id LIMIT :limit OFFSET :offset", + connectionType = MYSQL) + @ConnectionAwareSqlQuery( + value = + HIERARCHY_CTE + + "SELECT hierarchy_id, entity_type FROM (" + + "SELECT mg.id AS hierarchy_id, mg.name AS hierarchy_name, 'metricGroup' AS entity_type " + + "FROM metric_group_entity mg WHERE (mg.deleted = FALSE OR mg.deleted IS NULL) " + + "AND (" + + HIERARCHY_GROUP_MATCH_POSTGRES + + HIERARCHY_GROUP_MEMBER_EXISTS + + HIERARCHY_MEMBER_MATCH_POSTGRES + + "))" + + HIERARCHY_STANDALONE_ROOT + + HIERARCHY_MEMBER_MATCH_POSTGRES + + ")) hierarchy_items " + + "ORDER BY hierarchy_name, entity_type, hierarchy_id LIMIT :limit OFFSET :offset", + connectionType = POSTGRES) + @RegisterRowMapper(HierarchyRowMapper.class) + List listHierarchy( + @Bind("containsRelation") int containsRelation, + @Bind("hasRelation") int hasRelation, + @Bind("nameLike") String nameLike, + @Bind("limit") int limit, + @Bind("offset") int offset); + + @ConnectionAwareSqlQuery( + value = + HIERARCHY_CTE + + "SELECT COUNT(*) FROM (" + + "SELECT mg.id AS hierarchy_id FROM metric_group_entity mg " + + "WHERE (mg.deleted = FALSE OR mg.deleted IS NULL) " + + "AND (" + + HIERARCHY_GROUP_MATCH_MYSQL + + HIERARCHY_GROUP_MEMBER_EXISTS + + HIERARCHY_MEMBER_MATCH_MYSQL + + "))" + + HIERARCHY_STANDALONE_ROOT_COUNT + + HIERARCHY_MEMBER_MATCH_MYSQL + + ")) hierarchy_items", + connectionType = MYSQL) + @ConnectionAwareSqlQuery( + value = + HIERARCHY_CTE + + "SELECT COUNT(*) FROM (" + + "SELECT mg.id AS hierarchy_id FROM metric_group_entity mg " + + "WHERE (mg.deleted = FALSE OR mg.deleted IS NULL) " + + "AND (" + + HIERARCHY_GROUP_MATCH_POSTGRES + + HIERARCHY_GROUP_MEMBER_EXISTS + + HIERARCHY_MEMBER_MATCH_POSTGRES + + "))" + + HIERARCHY_STANDALONE_ROOT_COUNT + + HIERARCHY_MEMBER_MATCH_POSTGRES + + ")) hierarchy_items", + connectionType = POSTGRES) + int countHierarchy( + @Bind("containsRelation") int containsRelation, + @Bind("hasRelation") int hasRelation, + @Bind("nameLike") String nameLike); + + @SqlQuery( + "SELECT me.id FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :parentId AND er.fromEntity = 'metric' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND (me.deleted = FALSE OR me.deleted IS NULL) " + + "ORDER BY me.name, me.id LIMIT :limit OFFSET :offset") + List listChildIds( + @BindUUID("parentId") UUID parentId, + @Bind("relation") int relation, + @Bind("limit") int limit, + @Bind("offset") int offset); + + @SqlQuery( + "SELECT me.id FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :parentId AND er.fromEntity = 'metric' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND me.id <> :excludeId AND (me.deleted = FALSE OR me.deleted IS NULL) " + + "ORDER BY me.name, me.id LIMIT :limit OFFSET :offset") + List listSiblingIds( + @BindUUID("parentId") UUID parentId, + @BindUUID("excludeId") UUID excludeId, + @Bind("relation") int relation, + @Bind("limit") int limit, + @Bind("offset") int offset); + + @SqlQuery( + "SELECT COUNT(*) FROM entity_relationship er " + + "JOIN metric_entity me ON me.id = er.toId " + + "WHERE er.fromId = :parentId AND er.fromEntity = 'metric' " + + "AND er.toEntity = 'metric' AND er.relation = :relation " + + "AND me.id <> :excludeId AND (me.deleted = FALSE OR me.deleted IS NULL)") + int countSiblings( + @BindUUID("parentId") UUID parentId, + @BindUUID("excludeId") UUID excludeId, + @Bind("relation") int relation); + + @SqlQuery( + "SELECT er.toId FROM entity_relationship er " + + "WHERE er.fromId = :parentId AND er.fromEntity = 'metric' " + + "AND er.toEntity = 'metric' AND er.relation = :relation") + List listDescendantSeedIds( + @BindUUID("parentId") UUID parentId, @Bind("relation") int relation); + + @SqlQuery( + "SELECT me.id FROM metric_entity me " + + "WHERE me.id IN () AND (me.deleted = FALSE OR me.deleted IS NULL) " + + "ORDER BY me.name, me.id LIMIT :limit OFFSET :offset") + List pageMetricIds( + @BindList("ids") List ids, @Bind("limit") int limit, @Bind("offset") int offset); + + @SqlQuery( + "SELECT fromId FROM entity_relationship WHERE toId = :metricId " + + "AND toEntity = 'metric' AND fromId IN () AND relation = :relation") + List findUpstreamAssetIds( + @BindUUID("metricId") UUID metricId, + @BindList("assetIds") List assetIds, + @Bind("relation") int relation); + + @SqlQuery( + "SELECT toId FROM entity_relationship WHERE fromId = :metricId " + + "AND fromEntity = 'metric' AND toId IN () AND relation = :relation") + List findDownstreamAssetIds( + @BindUUID("metricId") UUID metricId, + @BindList("assetIds") List assetIds, + @Bind("relation") int relation); + + /** + * Metric fully qualified names are flat — a child metric's FQN is not prefixed by its parent's. + * The generic {@code fqnHash LIKE 'parent.%'} hierarchy filtering used by domains and glossary + * terms therefore cannot work here, so hierarchy listing walks the CONTAINS edges instead. + * {@code parentMetricId} selects immediate children of one metric; {@code rootMetrics} selects + * metrics that no other metric contains. + */ + static String addHierarchyCondition(ListFilter filter, String condition) { + String parentMetricId = filter.getQueryParam("parentMetricId"); + String rootMetrics = filter.getQueryParam("rootMetrics"); + String result = condition; + if (!nullOrEmpty(parentMetricId)) { + result += + " AND metric_entity.id IN (SELECT er.toId FROM entity_relationship er" + + " WHERE er.fromId = :parentMetricId AND er.fromEntity = 'metric'" + + " AND er.toEntity = 'metric' AND er.relation = " + + Relationship.CONTAINS.ordinal() + + ")"; + } else if (Boolean.TRUE.toString().equals(rootMetrics)) { + result += + " AND NOT EXISTS (SELECT 1 FROM entity_relationship er" + + " WHERE er.toId = metric_entity.id AND er.fromEntity = 'metric'" + + " AND er.toEntity = 'metric' AND er.relation = " + + Relationship.CONTAINS.ordinal() + + ")"; + } + return result; + } + + @Override + default int listCount(ListFilter filter) { + String condition = addHierarchyCondition(filter, filter.getCondition()); + return listCount(getTableName(), getNameHashColumn(), filter.getQueryParams(), condition); + } + + @Override + default List listBefore( + ListFilter filter, int limit, String beforeName, String beforeId) { + String condition = addHierarchyCondition(filter, filter.getCondition()); + return listBefore( + getTableName(), filter.getQueryParams(), condition, limit, beforeName, beforeId); + } + + @Override + default List listAfter(ListFilter filter, int limit, String afterName, String afterId) { + String condition = addHierarchyCondition(filter, filter.getCondition()); + return listAfter( + getTableName(), filter.getQueryParams(), condition, limit, afterName, afterId); + } + + @Override + default List listAfter(ListFilter filter, int limit, int offset) { + String condition = addHierarchyCondition(filter, filter.getCondition()); + return listAfter(getTableName(), filter.getQueryParams(), condition, limit, offset); + } + + @Override + default CursorRow getCursorAtOffset(ListFilter filter, int offset) { + String condition = addHierarchyCondition(filter, filter.getCondition()); + return getCursorAtOffset(getTableName(), filter.getQueryParams(), condition, offset); + } + @ConnectionAwareSqlQuery( value = "SELECT DISTINCT customUnitOfMeasurement AS customUnit " diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java index 1d40c964359d..6cbe0da5326c 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java @@ -4158,6 +4158,7 @@ protected void postCreate(List entities) { for (T entity : uniqueEntities) { RdfUpdater.updateEntity(entity); + CacheBundle.invalidateEntity(entityType, entity.getId(), entity.getFullyQualifiedName()); } ListCountCache.invalidate(entityType); } @@ -4678,8 +4679,16 @@ public final void restoreFromSearch(T entity) { EntityLifecycleEventDispatcher.getInstance() .onEntitySoftDeletedOrRestored(entity, false, null); } + postRestoreFromSearch(entity); } + /** + * Runs after a restored entity's search document is updated. Both synchronous and asynchronous + * resource paths invoke {@link #restoreFromSearch(EntityInterface)} only after the database + * restore returns, so relationship-derived documents can be rebuilt from committed state here. + */ + protected void postRestoreFromSearch(T entity) {} + public ResultList listFromSearchWithOffset( UriInfo uriInfo, Fields fields, @@ -5093,8 +5102,8 @@ public final ResultList getResultList( * Run {@code flushBody} as a single JDBI transaction, wrapped in deadlock retry. The * {@code DeadlockRetry.execute} layer is OUTER (each replay opens a fresh handle) and * {@code inTransaction} is INNER, matching the {@code DeadlockRetry} contract that the operation - * opens its own transaction. Every {@code daoCollection.xDAO()} call inside {@code flushBody} - * enrolls in the single thread-bound handle and commits ONCE instead of auto-committing per call. + * opens its own transaction. The handle-bound {@link CollectionDAO} is exposed through {@link + * RepositoryTransactionContext} for mutations that must share this transaction. * *

No network side effect (RDF/SPARQL, Elasticsearch, Redis L2) may run inside {@code flushBody} * — a pooled connection is held for the whole body, so a network round trip there would pin the @@ -5111,7 +5120,8 @@ private void runInTransactionWithRetry(Runnable flushBody) { Entity.getJdbi() .inTransaction( handle -> { - flushBody.run(); + RepositoryTransactionContext.runWith( + handle.attach(CollectionDAO.class), flushBody); return null; })); } @@ -5482,15 +5492,20 @@ protected void store(T entity, boolean update) { store(entity, update, null); } + protected EntityDAO entityDAOForWrite() { + return dao; + } + protected void store(T entity, boolean update, Double expectedVersion) { String json = serializeForStorage(entity); + EntityDAO writeDAO = entityDAOForWrite(); if (update) { if (expectedVersion != null) { int rowsUpdated = - dao.updateWithVersion( - dao.getTableName(), - dao.getNameHashColumn(), + writeDAO.updateWithVersion( + writeDAO.getTableName(), + writeDAO.getNameHashColumn(), entity.getFullyQualifiedName(), entity.getId().toString(), json, @@ -5508,12 +5523,16 @@ protected void store(T entity, boolean update, Double expectedVersion) { expectedVersion, entity.getVersion()); } else { - dao.update(entity.getId(), entity.getFullyQualifiedName(), json); + writeDAO.update(entity.getId(), entity.getFullyQualifiedName(), json); LOG.info("Updated {}:{}:{}", entityType, entity.getId(), entity.getFullyQualifiedName()); } invalidate(entity); } else { - dao.insert(dao.getTableName(), dao.getNameHashColumn(), entity.getFullyQualifiedName(), json); + writeDAO.insert( + writeDAO.getTableName(), + writeDAO.getNameHashColumn(), + entity.getFullyQualifiedName(), + json); LOG.info("Created {}:{}:{}", entityType, entity.getId(), entity.getFullyQualifiedName()); } StoredEntityJson pendingCapture = storedEntityJson.get(); @@ -5531,7 +5550,8 @@ protected void storeMany(List entities) { fqns.add(entity.getFullyQualifiedName()); jsons.add(serializeForStorage(entity)); } - dao.insertMany(dao.getTableName(), dao.getNameHashColumn(), fqns, jsons); + EntityDAO writeDAO = entityDAOForWrite(); + writeDAO.insertMany(writeDAO.getTableName(), writeDAO.getNameHashColumn(), fqns, jsons); } protected void updateMany(List entities) { @@ -5543,7 +5563,8 @@ protected void updateMany(List entities) { ids.add(entity.getId()); jsons.add(serializeForStorage(entity)); } - dao.updateMany(dao.getTableName(), dao.getNameHashColumn(), fqns, ids, jsons); + EntityDAO writeDAO = entityDAOForWrite(); + writeDAO.updateMany(writeDAO.getTableName(), writeDAO.getNameHashColumn(), fqns, ids, jsons); } @Transaction diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java index 15b9f407ddc0..a88ac1238165 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryTermRepository.java @@ -485,7 +485,7 @@ public void setFieldsInBulk(Fields fields, List entities) { // Resolve parent/glossary references in batch to avoid per-entity relationship lookups. populateParentAndGlossaryReferencesInBulk(entities); - fetchAndSetFields(entities, fields); + fetchAndSetFieldsExcept(entities, fields, Set.of("parent")); setInheritedFields(entities, fields); entities.forEach(entity -> clearFieldsInternal(entity, fields)); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/LineageRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/LineageRepository.java index 52cc80e18a37..3c2206ea51f9 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/LineageRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/LineageRepository.java @@ -71,6 +71,8 @@ import org.openmetadata.common.utils.CommonUtil; import org.openmetadata.csv.CsvUtil; import org.openmetadata.schema.EntityInterface; +import org.openmetadata.schema.api.data.MetricDimension; +import org.openmetadata.schema.api.data.MetricMeasure; import org.openmetadata.schema.api.lineage.AddLineage; import org.openmetadata.schema.api.lineage.EsLineageData; import org.openmetadata.schema.api.lineage.LineageDirection; @@ -81,6 +83,7 @@ import org.openmetadata.schema.entity.data.Container; import org.openmetadata.schema.entity.data.Dashboard; import org.openmetadata.schema.entity.data.DashboardDataModel; +import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.schema.entity.data.MlModel; import org.openmetadata.schema.entity.data.SearchIndex; import org.openmetadata.schema.entity.data.Table; @@ -313,14 +316,16 @@ public void addLineage(AddLineage addLineage, String updatedBy) { String detailsJson = validateLineageDetails(from, to, lineageDetails); // Finally, add lineage relationship - dao.relationshipDAO() - .insert( - from.getId(), - to.getId(), - from.getType(), - to.getType(), - Relationship.UPSTREAM.ordinal(), - detailsJson); + executeRelationshipWriteWithDeadlockRetry( + () -> + dao.relationshipDAO() + .insert( + from.getId(), + to.getId(), + from.getType(), + to.getType(), + Relationship.UPSTREAM.ordinal(), + detailsJson)); addLineageToSearch(from, to, lineageDetails); // Direct invalidation of cached lineage rooted at either endpoint of the new edge. @@ -566,14 +571,16 @@ private LineageDetails getOrCreateLineageDetails( private void insertLineage( EntityReference from, EntityReference to, LineageDetails lineageDetails) { - dao.relationshipDAO() - .insert( - from.getId(), - to.getId(), - from.getType(), - to.getType(), - Relationship.UPSTREAM.ordinal(), - JsonUtils.pojoToJson(lineageDetails)); + executeRelationshipWriteWithDeadlockRetry( + () -> + dao.relationshipDAO() + .insert( + from.getId(), + to.getId(), + from.getType(), + to.getType(), + Relationship.UPSTREAM.ordinal(), + JsonUtils.pojoToJson(lineageDetails))); addLineageToSearch(from, to, lineageDetails); // Add lineage to RDF @@ -1229,8 +1236,8 @@ private Set getChildrenNames(EntityReference entityReference) { return result; } case METRIC -> { - LOG.info("Metric column level lineage is not supported"); - return new HashSet<>(); + Metric metric = Entity.getEntity(METRIC, entityReference.getId(), "", Include.NON_DELETED); + return metricChildNames(metric); } case PIPELINE -> { LOG.info("Pipeline column level lineage is not supported"); @@ -1243,6 +1250,24 @@ private Set getChildrenNames(EntityReference entityReference) { } } + static Set metricChildNames(Metric metric) { + Set result = new HashSet<>(); + String prefix = metric.getFullyQualifiedName() + "."; + for (MetricDimension dimension : listOrEmpty(metric.getDimensions())) { + addMetricChildName(result, dimension.getFullyQualifiedName(), prefix); + } + for (MetricMeasure measure : listOrEmpty(metric.getMeasures())) { + addMetricChildName(result, measure.getFullyQualifiedName(), prefix); + } + return result; + } + + private static void addMetricChildName(Set names, String childFqn, String parentPrefix) { + if (childFqn != null && childFqn.startsWith(parentPrefix)) { + names.add(childFqn.substring(parentPrefix.length())); + } + } + @Transaction public boolean deleteLineageByFQN( String fromEntity, String fromFQN, String toEntity, String toFQN, String deletedBy) { @@ -1472,14 +1497,16 @@ private void processExtendedLineageCleanup(EntityReference fromRef, EntityRefere deleteLineageFromSearch(fromRef, toRef, lineageDetails); } else { lineageDetails.withAssetEdges(lineageDetails.getAssetEdges() - 1); - dao.relationshipDAO() - .insert( - fromRef.getId(), - toRef.getId(), - fromRef.getType(), - toRef.getType(), - Relationship.UPSTREAM.ordinal(), - JsonUtils.pojoToJson(lineageDetails)); + executeRelationshipWriteWithDeadlockRetry( + () -> + dao.relationshipDAO() + .insert( + fromRef.getId(), + toRef.getId(), + fromRef.getType(), + toRef.getType(), + Relationship.UPSTREAM.ordinal(), + JsonUtils.pojoToJson(lineageDetails))); addLineageToSearch(fromRef, toRef, lineageDetails); // Add lineage to RDF @@ -1504,6 +1531,14 @@ private int deleteLineageRelationshipWithRetry( .delete(fromId, fromEntity, toId, toEntity, Relationship.UPSTREAM.ordinal())); } + static void executeRelationshipWriteWithDeadlockRetry(Runnable relationshipWrite) { + DeadlockRetry.execute( + () -> { + relationshipWrite.run(); + return null; + }); + } + private void processDeletedRelations( List relations, String deletedBy) { for (CollectionDAO.EntityRelationshipObject obj : relations) { @@ -1694,8 +1729,16 @@ public Response patchLineageEdge( // Validate Lineage Details String detailsJson = validateLineageDetails(from, to, updated); - dao.relationshipDAO() - .insert(fromId, toId, fromEntity, toEntity, Relationship.UPSTREAM.ordinal(), detailsJson); + executeRelationshipWriteWithDeadlockRetry( + () -> + dao.relationshipDAO() + .insert( + fromId, + toId, + fromEntity, + toEntity, + Relationship.UPSTREAM.ordinal(), + detailsJson)); addLineageToSearch(from, to, updated); return new RestUtil.PatchResponse<>(Response.Status.OK, updated, EventType.ENTITY_UPDATED) .toResponse(); @@ -1796,14 +1839,16 @@ public void updateColumnLineage( details.setUpdatedAt(System.currentTimeMillis()); details.setUpdatedBy(updatedBy); // UPSERT the updated lineage JSON back into the relationship table - dao.relationshipDAO() - .insert( - UUID.fromString(row.getFromId()), - UUID.fromString(row.getToId()), - row.getFromEntity(), - row.getToEntity(), - row.getRelation(), - JsonUtils.pojoToJson(details)); + executeRelationshipWriteWithDeadlockRetry( + () -> + dao.relationshipDAO() + .insert( + UUID.fromString(row.getFromId()), + UUID.fromString(row.getToId()), + row.getFromEntity(), + row.getToEntity(), + row.getRelation(), + JsonUtils.pojoToJson(details))); } } catch (Exception ex) { LOG.warn( diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricGroupRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricGroupRepository.java new file mode 100644 index 000000000000..184d89277ae3 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricGroupRepository.java @@ -0,0 +1,905 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; +import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty; +import static org.openmetadata.schema.type.Include.NON_DELETED; +import static org.openmetadata.service.Entity.METRIC; +import static org.openmetadata.service.Entity.METRIC_GROUP; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.jdbi.v3.sqlobject.transaction.Transaction; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.ApiStatus; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.EntityRelationship; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.Paging; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; +import org.openmetadata.schema.type.api.BulkResponse; +import org.openmetadata.schema.type.change.ChangeSource; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.schema.utils.ResultList; +import org.openmetadata.service.Entity; +import org.openmetadata.service.events.lifecycle.EntityLifecycleEventDispatcher; +import org.openmetadata.service.rdf.RdfUpdater; +import org.openmetadata.service.resources.metrics.MetricGroupResource; +import org.openmetadata.service.util.EntityUtil; +import org.openmetadata.service.util.EntityUtil.RelationIncludes; +import org.openmetadata.service.util.RequestEntityCache; + +/** + * A Metric Group is a named collection of metrics used to organize them for browsing. + * + *

Membership is modelled as {@link Relationship#HAS} rather than {@code CONTAINS} on purpose: + * the base {@code deleteChildren} cascade only walks {@code CONTAINS}/{@code PARENT_OF}, so a + * group can be deleted without taking its metrics with it. A group organizes metrics, it does not + * own their lifecycle — deleting one simply leaves its members ungrouped. + * + *

Groups never nest, so their fully qualified name is the bare name, matching Metric. + */ +@Slf4j +public class MetricGroupRepository extends EntityRepository { + private static final String UPDATE_FIELDS = "metrics"; + private static final String PATCH_FIELDS = "metrics"; + static final String FIELD_METRICS = "metrics"; + static final String FIELD_METRIC_COUNT = "metricCount"; + private static final int COUNT_BATCH_SIZE = 500; + private static final int MEMBER_SCAN_BATCH_SIZE = 500; + static final int MAX_PERMISSION_FILTER_SCAN_SIZE = MEMBER_SCAN_BATCH_SIZE * 20; + + public MetricGroupRepository() { + super( + MetricGroupResource.COLLECTION_PATH, + METRIC_GROUP, + MetricGroup.class, + Entity.getCollectionDAO().metricGroupDAO(), + PATCH_FIELDS, + UPDATE_FIELDS); + supportsSearch = true; + renameAllowed = true; + + // Membership is exposed only by the authorized, paginated /metricGroups/{id}/metrics API. + // The updater still carries the relationship field captured by putFields/patchFields in the + // superclass constructor, while arbitrary GET/list callers cannot request an unbounded list. + allowedFields.remove(FIELD_METRICS); + + fieldFetchers.put(FIELD_METRICS, this::fetchAndSetMetrics); + fieldFetchers.put(FIELD_METRIC_COUNT, this::fetchAndSetMetricCounts); + } + + @Override + public void setFullyQualifiedName(MetricGroup metricGroup) { + metricGroup.setFullyQualifiedName(metricGroup.getName()); + } + + @Override + public void prepare(MetricGroup metricGroup, boolean update) { + List requestedMetrics = resolveMembers(metricGroup.getMetrics()); + metricGroup.setMetrics(expandRootSubtrees(requestedMetrics)); + validateAvailableMembership(metricGroup); + } + + private List resolveMembers(List metrics) { + if (nullOrEmpty(metrics)) { + return metrics; + } + List resolved = new ArrayList<>(); + for (EntityReference metric : metrics) { + if (!METRIC.equals(metric.getType())) { + throw new IllegalArgumentException( + String.format( + "A metric group can only contain metrics, but '%s' is a %s", + metric.getFullyQualifiedName(), metric.getType())); + } + resolved.add(Entity.getEntityReference(metric, NON_DELETED)); + } + return resolved; + } + + private void validateAvailableMembership(MetricGroup metricGroup) { + for (EntityReference metric : listOrEmpty(metricGroup.getMetrics())) { + for (EntityReference existing : + findFrom(metric.getId(), METRIC, Relationship.HAS, METRIC_GROUP)) { + if (!referencesTargetGroup(existing, metricGroup)) { + throw new IllegalArgumentException( + "Metric already belongs to another Metric Group; use the bulk membership endpoint to reassign it"); + } + } + } + } + + static boolean referencesTargetGroup(EntityReference existing, MetricGroup target) { + if (target.getId() != null && target.getId().equals(existing.getId())) { + return true; + } + String targetName = + target.getFullyQualifiedName() == null ? target.getName() : target.getFullyQualifiedName(); + return targetName != null + && (targetName.equals(existing.getFullyQualifiedName()) + || targetName.equals(existing.getName())); + } + + private void validateMembers(List metrics) { + for (EntityReference metric : listOrEmpty(metrics)) { + if (!METRIC.equals(metric.getType())) { + throw new IllegalArgumentException( + String.format( + "A metric group can only contain metrics, but '%s' is a %s", + metric.getFullyQualifiedName(), metric.getType())); + } + } + } + + @Override + public void setFields( + MetricGroup metricGroup, EntityUtil.Fields fields, RelationIncludes relationIncludes) { + metricGroup.setMetrics( + fields.contains(FIELD_METRICS) ? getMetrics(metricGroup) : metricGroup.getMetrics()); + metricGroup.setMetricCount( + fields.contains(FIELD_METRIC_COUNT) + ? getMetricCount(metricGroup) + : metricGroup.getMetricCount()); + } + + @Override + protected void clearFields(MetricGroup metricGroup, EntityUtil.Fields fields) { + metricGroup.setMetrics(fields.contains(FIELD_METRICS) ? metricGroup.getMetrics() : null); + metricGroup.setMetricCount( + fields.contains(FIELD_METRIC_COUNT) ? metricGroup.getMetricCount() : null); + } + + private List getMetrics(MetricGroup metricGroup) { + return findTo(metricGroup.getId(), METRIC_GROUP, Relationship.HAS, METRIC); + } + + public MetricGroup getWithMembers(UUID id, Include include) { + MetricGroup metricGroup = get(null, id, EntityUtil.Fields.EMPTY_FIELDS, include, false); + metricGroup.setMetrics(getMetrics(metricGroup)); + return metricGroup; + } + + public MetricGroup getByNameWithMembers(String fullyQualifiedName, Include include) { + MetricGroup metricGroup = + getByName(null, fullyQualifiedName, EntityUtil.Fields.EMPTY_FIELDS, include, false); + metricGroup.setMetrics(getMetrics(metricGroup)); + return metricGroup; + } + + private Integer getMetricCount(MetricGroup metricGroup) { + return ((CollectionDAO.MetricGroupDAO) dao) + .countNonDeletedMembers(metricGroup.getId(), Relationship.HAS.ordinal()); + } + + private void fetchAndSetMetrics(List groups, EntityUtil.Fields fields) { + if (!fields.contains(FIELD_METRICS) || nullOrEmpty(groups)) { + return; + } + Map> membersByGroup = batchFetchMembers(groups); + for (MetricGroup group : groups) { + group.setMetrics(membersByGroup.getOrDefault(group.getId(), new ArrayList<>())); + } + } + + private void fetchAndSetMetricCounts(List groups, EntityUtil.Fields fields) { + if (!fields.contains(FIELD_METRIC_COUNT) || nullOrEmpty(groups)) { + return; + } + Map counts = new HashMap<>(); + CollectionDAO.MetricGroupDAO groupDAO = (CollectionDAO.MetricGroupDAO) dao; + for (int start = 0; start < groups.size(); start += COUNT_BATCH_SIZE) { + int end = Math.min(start + COUNT_BATCH_SIZE, groups.size()); + for (CollectionDAO.EntityRelationshipCount count : + groupDAO.countNonDeletedMembersBatch( + entityListToStrings(groups.subList(start, end)), Relationship.HAS.ordinal())) { + counts.put(count.getId(), count.getCount()); + } + } + for (MetricGroup group : groups) { + group.setMetricCount(counts.getOrDefault(group.getId(), 0)); + } + } + + private Map> batchFetchMembers(List groups) { + Map> membersByGroup = new HashMap<>(); + for (MetricGroup group : groups) { + membersByGroup.put(group.getId(), new ArrayList<>()); + } + for (CollectionDAO.EntityRelationshipObject record : + daoCollection + .relationshipDAO() + .findToBatch(entityListToStrings(groups), Relationship.HAS.ordinal(), METRIC)) { + membersByGroup + .get(UUID.fromString(record.getFromId())) + .add( + Entity.getEntityReferenceById( + METRIC, UUID.fromString(record.getToId()), NON_DELETED)); + } + return membersByGroup; + } + + @Override + protected List getFieldsStrippedFromStorageJson() { + return List.of(FIELD_METRICS, FIELD_METRIC_COUNT); + } + + @Override + public void storeEntity(MetricGroup metricGroup, boolean update) { + store(metricGroup, update); + } + + @Override + public void storeEntities(List entities) { + storeMany(entities); + } + + @Override + public void storeRelationships(MetricGroup metricGroup) { + for (EntityReference metric : listOrEmpty(metricGroup.getMetrics())) { + removeOtherGroupMemberships(metric.getId(), metricGroup.getId()); + addRelationship(metricGroup.getId(), metric.getId(), METRIC_GROUP, METRIC, Relationship.HAS); + } + } + + @Override + protected void postCreate(MetricGroup metricGroup) { + super.postCreate(metricGroup); + MembershipChange change = + new MembershipChange( + new ArrayList<>(listOrEmpty(metricGroup.getMetrics())), + Set.of(metricGroup.getEntityReference())); + publishMembershipChange(change); + } + + @Override + protected void postDelete(MetricGroup metricGroup, boolean hardDelete) { + super.postDelete(metricGroup, hardDelete); + if (!hardDelete) { + retainMembersForPostDelete(metricGroup, getMetrics(metricGroup)); + } + publishMembershipChange( + new MembershipChange( + new ArrayList<>(listOrEmpty(metricGroup.getMetrics())), + Set.of(metricGroup.getEntityReference()))); + } + + @Override + protected void postUpdate(MetricGroup original, MetricGroup updated) { + super.postUpdate(original, updated); + if (Boolean.TRUE.equals(original.getDeleted()) && !Boolean.TRUE.equals(updated.getDeleted())) { + List restoredMembers = getMetrics(updated); + updated.setMetrics(restoredMembers); + publishMembershipChange( + new MembershipChange(restoredMembers, Set.of(updated.getEntityReference()))); + } + } + + @Override + protected void postRestoreFromSearch(MetricGroup metricGroup) { + refreshMembersAfterGroupLifecycle(metricGroup); + } + + @Override + protected void entitySpecificCleanup(MetricGroup metricGroup) { + retainMembersForPostDelete(metricGroup, getMetrics(metricGroup)); + } + + static void retainMembersForPostDelete( + MetricGroup metricGroup, List currentMembers) { + metricGroup.setMetrics(new ArrayList<>(listOrEmpty(currentMembers))); + } + + @Override + protected void clearEntitySpecificRelationshipsForMany(List entities) { + if (entities.isEmpty()) { + return; + } + // Only groups that carry an explicit member list are cleared: a null list means "unchanged" + // on bulk import paths, and wiping those would silently empty every group in the file. + List memberCarryingIds = + entities.stream() + .filter(group -> group.getMetrics() != null) + .map(MetricGroup::getId) + .toList(); + deleteFromMany(memberCarryingIds, METRIC_GROUP, Relationship.HAS, METRIC); + } + + @Override + public EntityRepository.EntityUpdater getUpdater( + MetricGroup original, MetricGroup updated, Operation operation, ChangeSource changeSource) { + return new MetricGroupUpdater(original, updated, operation); + } + + public BulkOperationResult bulkAddMetrics(String groupName, BulkAssets request, String userName) { + MetricGroup group = getByName(null, groupName, getFields("id")); + return updateMembership(group, request, true); + } + + public BulkOperationResult bulkRemoveMetrics( + String groupName, BulkAssets request, String userName) { + MetricGroup group = getByName(null, groupName, getFields("id")); + return updateMembership(group, request, false); + } + + public ResultList listMetrics( + UUID groupId, int limit, int offset, String query, boolean rootOnly) { + MemberScan scan = scanUnrestrictedMemberIds(groupId, limit, offset, query, rootOnly); + return buildMetricPage(scan, limit, offset, ignored -> true); + } + + public ResultList listMetrics( + UUID groupId, + int limit, + int offset, + String query, + boolean rootOnly, + Predicate isVisible) { + CollectionDAO.MetricGroupDAO groupDAO = (CollectionDAO.MetricGroupDAO) dao; + String nameLike = buildNameLike(query); + validatePermissionFilteredScanSize(groupDAO, groupId, query, nameLike, rootOnly); + MemberScan scan = + scanMemberIds(groupDAO, groupId, limit, offset, query, nameLike, rootOnly, isVisible); + return buildMetricPage(scan, limit, offset, isVisible); + } + + private ResultList buildMetricPage( + MemberScan scan, int limit, int offset, Predicate isVisible) { + List ids = scan.ids(); + List metrics = daoCollection.metricDAO().findEntitiesByIds(ids, NON_DELETED); + MetricRepository metricRepository = + (MetricRepository) Entity.getEntityRepository(Entity.METRIC); + metricRepository.setFieldsInBulk( + metricRepository.getFields("owners,reviewers,parent,childrenCount,metricGroup"), metrics); + metrics = + metrics.stream() + .map( + metric -> + MetricRepository.sanitizeHierarchyMetric(metric, isVisible, ignored -> true)) + .collect(Collectors.toCollection(ArrayList::new)); + for (Metric metric : metrics) { + metric.setChildrenCount(metricRepository.visibleChildCount(metric.getId(), isVisible)); + } + Map positions = new HashMap<>(); + for (int index = 0; index < ids.size(); index++) { + positions.put(ids.get(index), index); + } + metrics.sort((left, right) -> positions.get(left.getId()) - positions.get(right.getId())); + Paging paging = new Paging().withOffset(offset).withLimit(limit).withTotal(scan.total()); + return new ResultList<>(metrics, paging); + } + + MemberScan scanUnrestrictedMemberIds( + UUID groupId, int limit, int offset, String query, boolean rootOnly) { + CollectionDAO.MetricGroupDAO groupDAO = (CollectionDAO.MetricGroupDAO) dao; + String nameLike = buildNameLike(query); + MemberScan result; + if (rootOnly && hasSearchQuery(query)) { + result = + scanMemberIds(groupDAO, groupId, limit, offset, query, nameLike, true, ignored -> true); + } else { + List references = + memberReferences(groupDAO, groupId, limit, offset, nameLike, rootOnly); + int total = countUnrestrictedMembers(groupDAO, groupId, nameLike, rootOnly); + result = new MemberScan(references.stream().map(EntityReference::getId).toList(), total); + } + return result; + } + + private int countUnrestrictedMembers( + CollectionDAO.MetricGroupDAO groupDAO, UUID groupId, String nameLike, boolean rootOnly) { + return rootOnly + ? groupDAO.countRootMembersPage( + groupId, Relationship.HAS.ordinal(), Relationship.CONTAINS.ordinal(), nameLike) + : groupDAO.countMembers(groupId, Relationship.HAS.ordinal(), nameLike); + } + + int visibleMetricCount(UUID groupId, Predicate isVisible) { + CollectionDAO.MetricGroupDAO groupDAO = (CollectionDAO.MetricGroupDAO) dao; + validatePermissionFilteredScanSize(groupDAO, groupId, null, "%", false); + return scanMemberIds(groupDAO, groupId, 0, 0, null, "%", false, isVisible).total(); + } + + private void validatePermissionFilteredScanSize( + CollectionDAO.MetricGroupDAO groupDAO, + UUID groupId, + String query, + String nameLike, + boolean rootOnly) { + int candidateCount = + rootOnly && hasSearchQuery(query) + ? groupDAO.countMembers(groupId, Relationship.HAS.ordinal(), "%") + : countUnrestrictedMembers(groupDAO, groupId, nameLike, rootOnly); + if (candidateCount > MAX_PERMISSION_FILTER_SCAN_SIZE) { + throw new IllegalArgumentException( + String.format( + "Permission-filtered Metric Group listing supports at most %,d candidate Metrics. " + + "Narrow the query before retrying.", + MAX_PERMISSION_FILTER_SCAN_SIZE)); + } + } + + private MemberScan scanMemberIds( + CollectionDAO.MetricGroupDAO groupDAO, + UUID groupId, + int limit, + int offset, + String query, + String nameLike, + boolean rootOnly, + Predicate isVisible) { + List page = new ArrayList<>(); + int relationshipOffset = 0; + int visible = 0; + List batch; + do { + batch = + memberReferences( + groupDAO, + groupId, + MEMBER_SCAN_BATCH_SIZE, + relationshipOffset, + rootOnly ? "%" : nameLike, + rootOnly); + for (EntityReference reference : batch) { + if (isVisible.test(reference) + && (!rootOnly || subtreeMatchesQuery(reference.getId(), query, isVisible))) { + if (visible >= offset && page.size() < limit) { + page.add(reference.getId()); + } + visible++; + } + } + relationshipOffset += batch.size(); + } while (batch.size() == MEMBER_SCAN_BATCH_SIZE); + return new MemberScan(page, visible); + } + + boolean hasVisibleMemberMatching( + UUID groupId, String query, Predicate isVisible) { + CollectionDAO.MetricGroupDAO groupDAO = (CollectionDAO.MetricGroupDAO) dao; + String nameLike = buildNameLike(query); + validatePermissionFilteredScanSize(groupDAO, groupId, query, nameLike, false); + int relationshipOffset = 0; + List batch; + do { + batch = + memberReferences( + groupDAO, groupId, MEMBER_SCAN_BATCH_SIZE, relationshipOffset, nameLike, false); + for (EntityReference reference : batch) { + if (isVisible.test(reference)) { + return true; + } + } + relationshipOffset += batch.size(); + } while (batch.size() == MEMBER_SCAN_BATCH_SIZE); + return false; + } + + private boolean subtreeMatchesQuery( + UUID rootId, String query, Predicate isVisible) { + if (!hasSearchQuery(query)) { + return true; + } + return expandSubtree(rootId).stream() + .anyMatch(metric -> isVisible.test(metric) && referenceMatchesQuery(metric, query)); + } + + static boolean referenceMatchesQuery(EntityReference reference, String query) { + if (!hasSearchQuery(query)) { + return true; + } + String normalized = query.trim().toLowerCase(Locale.ROOT); + return stringContains(reference.getName(), normalized) + || stringContains(reference.getDisplayName(), normalized); + } + + private static boolean stringContains(String value, String normalizedQuery) { + return value != null && value.toLowerCase(Locale.ROOT).contains(normalizedQuery); + } + + private static boolean hasSearchQuery(String query) { + return !nullOrEmpty(query) && !query.trim().isEmpty(); + } + + private List memberReferences( + CollectionDAO.MetricGroupDAO groupDAO, + UUID groupId, + int limit, + int offset, + String nameLike, + boolean rootOnly) { + List memberJsons = + rootOnly + ? groupDAO.listRootMemberJsonsPage( + groupId, + Relationship.HAS.ordinal(), + Relationship.CONTAINS.ordinal(), + nameLike, + limit, + offset) + : groupDAO.listMemberJsons( + groupId, Relationship.HAS.ordinal(), nameLike, limit, offset); + return memberJsons.stream() + .map(json -> JsonUtils.readValue(json, Metric.class).getEntityReference()) + .toList(); + } + + public List hierarchySubtree(EntityReference requested) { + return expandSubtree(resolveRootMetric(requested).getId()); + } + + private BulkOperationResult updateMembership( + MetricGroup group, BulkAssets request, boolean isAdd) { + boolean dryRun = Boolean.TRUE.equals(request.getDryRun()); + BulkOperationResult result = new BulkOperationResult().withDryRun(dryRun); + List successes = new ArrayList<>(); + List failures = new ArrayList<>(); + for (EntityReference requested : listOrEmpty(request.getAssets())) { + updateRequestedRoot(group, requested, isAdd, dryRun, result, successes, failures); + } + setBulkStatus(result, successes, failures); + return result.withSuccessRequest(successes).withFailedRequest(failures); + } + + private void updateRequestedRoot( + MetricGroup group, + EntityReference requested, + boolean isAdd, + boolean dryRun, + BulkOperationResult result, + List successes, + List failures) { + result.setNumberOfRowsProcessed(result.getNumberOfRowsProcessed() + 1); + try { + EntityReference metric = resolveRootMetric(requested); + if (!dryRun) { + MembershipChange change = updateSubtreeMembership(group, metric, isAdd); + publishMembershipChange(change); + } + successes.add(new BulkResponse().withRequest(requested)); + result.setNumberOfRowsPassed(result.getNumberOfRowsPassed() + 1); + } catch (IllegalArgumentException exception) { + failures.add(new BulkResponse().withRequest(requested).withMessage(exception.getMessage())); + result.setNumberOfRowsFailed(result.getNumberOfRowsFailed() + 1); + } + } + + private EntityReference resolveRootMetric(EntityReference requested) { + if (!METRIC.equals(requested.getType())) { + throw new IllegalArgumentException("Metric Group membership accepts Metric entities only"); + } + EntityReference metric = Entity.getEntityReference(requested.withType(METRIC), NON_DELETED); + if (!findFrom(metric.getId(), METRIC, Relationship.CONTAINS, METRIC).isEmpty()) { + throw new IllegalArgumentException( + String.format("Metric '%s' is not a hierarchy root", metric.getFullyQualifiedName())); + } + return metric; + } + + private MembershipChange updateSubtreeMembership( + MetricGroup group, EntityReference rootMetric, boolean isAdd) { + List metrics = expandSubtree(rootMetric.getId()); + return inLockedMembershipTransaction( + metrics, + relationshipDAO -> + isAdd + ? assignHierarchyGroup(relationshipDAO, metrics, group.getEntityReference()) + : removeHierarchyGroup(relationshipDAO, metrics, group.getEntityReference())); + } + + static MembershipChange removeHierarchyGroup( + CollectionDAO.EntityRelationshipDAO relationshipDAO, + List metrics, + EntityReference group) { + UUID rootMetricId = metrics.getFirst().getId(); + boolean isMember = + relationshipDAO + .findFrom(rootMetricId, METRIC, Relationship.HAS.ordinal(), METRIC_GROUP) + .stream() + .anyMatch(existing -> existing.getId().equals(group.getId())); + if (!isMember) { + throw new IllegalArgumentException("Metric is not a member of the requested Metric Group"); + } + for (EntityReference metric : metrics) { + relationshipDAO.delete( + group.getId(), METRIC_GROUP, metric.getId(), METRIC, Relationship.HAS.ordinal()); + } + return new MembershipChange(metrics, Set.of(group)); + } + + static MembershipChange assignHierarchyGroup( + CollectionDAO.EntityRelationshipDAO relationshipDAO, + List metrics, + EntityReference group) { + Set groupsToRefresh = new LinkedHashSet<>(); + if (group != null) { + groupsToRefresh.add(group); + } + for (EntityReference metric : metrics) { + for (CollectionDAO.EntityRelationshipRecord existing : + relationshipDAO.findFrom( + metric.getId(), METRIC, Relationship.HAS.ordinal(), METRIC_GROUP)) { + if (group == null || !existing.getId().equals(group.getId())) { + relationshipDAO.delete( + existing.getId(), METRIC_GROUP, metric.getId(), METRIC, Relationship.HAS.ordinal()); + groupsToRefresh.add( + new EntityReference().withId(existing.getId()).withType(METRIC_GROUP)); + } + } + if (group != null) { + relationshipDAO.insert( + group.getId(), metric.getId(), METRIC_GROUP, METRIC, Relationship.HAS.ordinal()); + } + } + return new MembershipChange(metrics, groupsToRefresh); + } + + MembershipChange assignHierarchyGroup(UUID rootMetricId, EntityReference group) { + List metrics = expandSubtree(rootMetricId); + return inLockedMembershipTransaction( + metrics, relationshipDAO -> assignHierarchyGroup(relationshipDAO, metrics, group)); + } + + MembershipChange assignHierarchyGroupInCurrentTransaction( + UUID rootMetricId, EntityReference group) { + CollectionDAO transactionDAO = RepositoryTransactionContext.requireCurrentDAO(); + List metrics = expandSubtree(rootMetricId, transactionDAO.metricDAO()); + return assignHierarchyGroupWithLock( + transactionDAO.metricDAO(), transactionDAO.relationshipDAO(), metrics, group); + } + + static MembershipChange assignHierarchyGroupWithLock( + CollectionDAO.MetricDAO metricDAO, + CollectionDAO.EntityRelationshipDAO relationshipDAO, + List metrics, + EntityReference group) { + lockMembershipRows(metricDAO, metrics); + return assignHierarchyGroup(relationshipDAO, metrics, group); + } + + private MembershipChange inLockedMembershipTransaction( + List metrics, + java.util.function.Function update) { + return Entity.getJdbi() + .inTransaction( + handle -> { + lockMembershipRows(handle.attach(CollectionDAO.MetricDAO.class), metrics); + return update.apply(handle.attach(CollectionDAO.EntityRelationshipDAO.class)); + }); + } + + private static void lockMembershipRows( + CollectionDAO.MetricDAO metricDAO, List metrics) { + List metricIds = + metrics.stream().map(EntityReference::getId).map(UUID::toString).sorted().toList(); + metricDAO.lockForGroupAssignment(metricIds); + } + + void publishMembershipChange(MembershipChange change) { + synchronizeMembershipSideEffects(change); + refreshMemberSearchDocuments(change.metrics()); + change.groups().forEach(this::refreshGroup); + } + + public void refreshMembersAfterGroupLifecycle(MetricGroup groupSnapshot) { + MembershipChange change = + new MembershipChange( + new ArrayList<>(listOrEmpty(groupSnapshot.getMetrics())), + Set.of(groupSnapshot.getEntityReference())); + synchronizeMembershipSideEffects(change); + refreshMemberSearchDocuments(change.metrics()); + } + + private void refreshMemberSearchDocuments(List metrics) { + for (EntityReference metric : metrics) { + EntityLifecycleEventDispatcher.getInstance().onEntityUpdated(metric, null); + } + } + + private void synchronizeMembershipSideEffects(MembershipChange change) { + for (EntityReference metric : change.metrics()) { + Set currentGroups = + findFrom(metric.getId(), METRIC, Relationship.HAS, METRIC_GROUP).stream() + .map(EntityReference::getId) + .collect(Collectors.toSet()); + RequestEntityCache.invalidate(METRIC, metric.getId(), metric.getFullyQualifiedName()); + EntityRepository.invalidateCacheForEntity( + METRIC, metric.getId(), metric.getFullyQualifiedName()); + for (EntityReference group : change.groups()) { + EntityRelationship relationship = + new EntityRelationship() + .withFromId(group.getId()) + .withFromEntity(METRIC_GROUP) + .withToId(metric.getId()) + .withToEntity(METRIC) + .withRelationshipType(Relationship.HAS); + if (currentGroups.contains(group.getId())) { + RdfUpdater.addRelationship(relationship); + } else { + RdfUpdater.removeRelationship(relationship); + } + } + } + change + .groups() + .forEach( + group -> EntityRepository.invalidateCacheForEntity(METRIC_GROUP, group.getId(), null)); + } + + private List expandSubtree(UUID rootMetricId) { + return expandSubtree(rootMetricId, daoCollection.metricDAO()); + } + + static List expandSubtree(UUID rootMetricId, CollectionDAO.MetricDAO metricDAO) { + Set metricIds = new LinkedHashSet<>(); + ArrayDeque pending = new ArrayDeque<>(List.of(rootMetricId)); + while (!pending.isEmpty()) { + UUID current = pending.removeFirst(); + if (metricIds.add(current)) { + metricDAO.listDescendantSeedIds(current, Relationship.CONTAINS.ordinal()).stream() + .map(UUID::fromString) + .forEach(pending::addLast); + } + } + Map referencesById = + metricDAO.findEntitiesByIds(new ArrayList<>(metricIds), NON_DELETED).stream() + .map(Metric::getEntityReference) + .collect(Collectors.toMap(EntityReference::getId, reference -> reference)); + return metricIds.stream() + .map(referencesById::get) + .filter(reference -> reference != null) + .toList(); + } + + private List removeGroupMemberships( + UUID metricId, EntityReference retainedGroup) { + List removed = new ArrayList<>(); + for (EntityReference existing : findFrom(metricId, METRIC, Relationship.HAS, METRIC_GROUP)) { + if (retainedGroup == null || !existing.getId().equals(retainedGroup.getId())) { + deleteRelationship(existing.getId(), METRIC_GROUP, metricId, METRIC, Relationship.HAS); + removed.add(existing); + } + } + return removed; + } + + private void setBulkStatus( + BulkOperationResult result, List successes, List failures) { + ApiStatus status = ApiStatus.SUCCESS; + if (successes.isEmpty() && !failures.isEmpty()) { + status = ApiStatus.FAILURE; + } else if (!failures.isEmpty()) { + status = ApiStatus.PARTIAL_SUCCESS; + } + result.setStatus(status); + } + + private List expandRootSubtrees(List roots) { + if (nullOrEmpty(roots)) { + return roots; + } + List hierarchyRoots = + roots.stream() + .filter( + metric -> findFrom(metric.getId(), METRIC, Relationship.CONTAINS, METRIC).isEmpty()) + .toList(); + Set metricIds = new LinkedHashSet<>(); + for (EntityReference root : hierarchyRoots) { + expandSubtree(root.getId()).stream().map(EntityReference::getId).forEach(metricIds::add); + } + validateRequestedHierarchyMembers(roots, metricIds); + return Entity.getEntityReferencesByIds(METRIC, new ArrayList<>(metricIds), NON_DELETED); + } + + static void validateRequestedHierarchyMembers( + List requestedMetrics, Set expandedMetricIds) { + for (EntityReference metric : requestedMetrics) { + if (!expandedMetricIds.contains(metric.getId())) { + throw new IllegalArgumentException( + String.format("Metric '%s' is not a hierarchy root", metric.getFullyQualifiedName())); + } + } + } + + private void removeOtherGroupMemberships(UUID metricId, UUID targetGroupId) { + for (EntityReference existing : findFrom(metricId, METRIC, Relationship.HAS, METRIC_GROUP)) { + if (!existing.getId().equals(targetGroupId)) { + deleteRelationship(existing.getId(), METRIC_GROUP, metricId, METRIC, Relationship.HAS); + } + } + } + + private void refreshGroup(EntityReference group) { + if (group != null) { + EntityLifecycleEventDispatcher.getInstance().onEntityUpdated(group, null); + } + } + + record MembershipChange(List metrics, Set groups) {} + + record MemberScan(List ids, int total) {} + + static String buildNameLike(String query) { + String result = "%"; + if (!nullOrEmpty(query)) { + String normalized = query.trim(); + if (normalized.isEmpty()) { + return result; + } + String escaped = + normalized + .toLowerCase(Locale.ROOT) + .replace("!", "!!") + .replace("%", "!%") + .replace("_", "!_"); + result = "%" + escaped + "%"; + } + return result; + } + + public class MetricGroupUpdater extends EntityUpdater { + private final Set metricsToRefresh = new LinkedHashSet<>(); + private final Set groupsToRefresh = new LinkedHashSet<>(); + + public MetricGroupUpdater(MetricGroup original, MetricGroup updated, Operation operation) { + super(original, updated, operation); + metricsToRefresh.addAll(listOrEmpty(original.getMetrics())); + metricsToRefresh.addAll(listOrEmpty(updated.getMetrics())); + } + + @Transaction + @Override + public void entitySpecificUpdate(boolean consolidatingChanges) { + compareAndUpdate(FIELD_METRICS, () -> updateMetrics(original, updated)); + MembershipChange change = + new MembershipChange( + new ArrayList<>(metricsToRefresh), new LinkedHashSet<>(groupsToRefresh)); + deferReactOperation(() -> publishMembershipChange(change)); + } + + private void updateMetrics(MetricGroup original, MetricGroup updated) { + validateMembers(updated.getMetrics()); + List expanded = new ArrayList<>(listOrEmpty(updated.getMetrics())); + updateToRelationships( + FIELD_METRICS, + METRIC_GROUP, + original.getId(), + Relationship.HAS, + METRIC, + new ArrayList<>(listOrEmpty(original.getMetrics())), + new ArrayList<>(expanded), + false); + groupsToRefresh.add(updated.getEntityReference()); + for (EntityReference metric : expanded) { + groupsToRefresh.addAll( + removeGroupMemberships(metric.getId(), original.getEntityReference())); + } + } + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilder.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilder.java new file mode 100644 index 000000000000..bb28bd31e578 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilder.java @@ -0,0 +1,697 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; +import static org.openmetadata.service.Entity.TABLE; +import static org.openmetadata.service.Entity.TEST_CASE; +import static org.openmetadata.service.Entity.TEST_CASE_RESULT; +import static org.openmetadata.service.Entity.TEST_DEFINITION; +import static org.openmetadata.service.Entity.TEST_SUITE; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.DistributionSummary; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Timer; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.openmetadata.schema.api.data.MetricAssetDirection; +import org.openmetadata.schema.api.data.MetricAssetRollup; +import org.openmetadata.schema.api.data.MetricDimensionRollup; +import org.openmetadata.schema.api.data.MetricIncident; +import org.openmetadata.schema.api.data.MetricObservability; +import org.openmetadata.schema.api.data.MetricObservabilityReasonCode; +import org.openmetadata.schema.api.data.MetricSourceCoverage; +import org.openmetadata.schema.api.data.MetricTestResult; +import org.openmetadata.schema.api.data.MetricTestStatusCounts; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.tests.ResultSummary; +import org.openmetadata.schema.tests.TestCase; +import org.openmetadata.schema.tests.TestDefinition; +import org.openmetadata.schema.tests.type.TestCaseResolutionStatus; +import org.openmetadata.schema.tests.type.TestCaseResolutionStatusTypes; +import org.openmetadata.schema.tests.type.TestCaseStatus; +import org.openmetadata.schema.type.DataQualityDimensions; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.MetricHealth; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.service.Entity; +import org.openmetadata.service.util.FullyQualifiedName; + +/** Computes Metric health from every active test on direct upstream Tables. */ +@Slf4j +public class MetricObservabilityBuilder { + static final double HEALTHY_THRESHOLD = 90.0; + static final double AT_RISK_THRESHOLD = 75.0; + + private final MetricRepository metricRepository; + private final Timer latency; + private final DistributionSummary upstreamTableCount; + private final DistributionSummary activeTestCount; + private final Counter failures; + private final Counter redactedSources; + + public MetricObservabilityBuilder(MetricRepository metricRepository) { + this(metricRepository, Metrics.globalRegistry); + } + + MetricObservabilityBuilder(MetricRepository metricRepository, MeterRegistry meterRegistry) { + this.metricRepository = metricRepository; + latency = + Timer.builder("om_metric_observability_duration") + .description("Time spent computing Metric observability") + .publishPercentileHistogram() + .register(meterRegistry); + upstreamTableCount = + DistributionSummary.builder("om_metric_observability_upstream_tables") + .description("Direct upstream Tables evaluated per Metric observability request") + .register(meterRegistry); + activeTestCount = + DistributionSummary.builder("om_metric_observability_active_tests") + .description("Active tests evaluated per Metric observability request") + .register(meterRegistry); + failures = + Counter.builder("om_metric_observability_failures_total") + .description("Metric observability computations that could not be completed") + .register(meterRegistry); + redactedSources = + Counter.builder("om_metric_observability_redacted_sources_total") + .description("Metric upstream sources redacted from response details") + .register(meterRegistry); + } + + public MetricObservability build(UUID metricId) { + return build(metricId, null, null); + } + + public MetricObservability build(UUID metricId, Set visibleAssetIds) { + return build(metricId, null, visibleAssetIds); + } + + public MetricObservability build( + UUID metricId, List linkedAssets, Set visibleAssetIds) { + MetricObservability result; + boolean failed = false; + long startedAt = System.nanoTime(); + try { + result = compute(metricId, linkedAssets, visibleAssetIds); + } catch (RuntimeException exception) { + failed = true; + LOG.warn("Failed to compute Metric observability for {}", metricId, exception); + result = unavailable(); + } + recordTelemetry(result, System.nanoTime() - startedAt, failed); + return result; + } + + void recordTelemetry(MetricObservability result, long durationNanos, boolean failed) { + latency.record(durationNanos, TimeUnit.NANOSECONDS); + if (failed) { + failures.increment(); + } + if (result == null) { + return; + } + upstreamTableCount.record(valueOrZero(result.getUpstreamAssetCount())); + MetricTestStatusCounts counts = result.getStatusCounts(); + if (counts != null) { + activeTestCount.record( + valueOrZero(counts.getPassed()) + + valueOrZero(counts.getFailed()) + + valueOrZero(counts.getAborted()) + + valueOrZero(counts.getQueued()) + + valueOrZero(counts.getMissing())); + } + if (result.getSourceCoverage() != null) { + redactedSources.increment(valueOrZero(result.getSourceCoverage().getRestrictedTables())); + } + } + + private static int valueOrZero(Integer value) { + return value == null ? 0 : value; + } + + private MetricObservability compute( + UUID metricId, List prefetchedLinkedAssets, Set visibleAssetIds) { + Metric metric = metricRepository.get(null, metricId, metricRepository.getFields("id")); + List linkedAssets = + prefetchedLinkedAssets == null + ? metricRepository.getAssetsWithDirection(metricId) + : List.copyOf(prefetchedLinkedAssets); + List upstreamTables = directUpstreamTables(linkedAssets); + List observations = loadObservations(upstreamTables); + Set visibleUpstream = visibleAssets(upstreamTables, visibleAssetIds); + Set visibleLinked = visibleLinkedAssetIds(linkedAssets, visibleAssetIds); + List incidents = loadIncidents(observations, visibleUpstream); + return summarize( + metric.getEntityReference(), + linkedAssets, + upstreamTables, + observations, + incidents, + visibleUpstream, + visibleLinked) + .withEvaluatedAt(System.currentTimeMillis()); + } + + private Set visibleLinkedAssetIds( + List linkedAssets, Set visibleAssetIds) { + Set visible = new HashSet<>(); + for (MetricAssetDirection linked : linkedAssets) { + UUID id = linked.getAsset().getId(); + if (visibleAssetIds == null || visibleAssetIds.contains(id)) { + visible.add(id); + } + } + return visible; + } + + private List directUpstreamTables(List linkedAssets) { + return linkedAssets.stream() + .filter(linked -> MetricAssetDirection.Direction.UPSTREAM.equals(linked.getDirection())) + .map(MetricAssetDirection::getAsset) + .filter(asset -> TABLE.equals(asset.getType())) + .sorted(Comparator.comparing(EntityReference::getId)) + .toList(); + } + + private Set visibleAssets(List upstreamTables, Set visibleAssetIds) { + Set visible = new HashSet<>(); + for (EntityReference table : upstreamTables) { + if (visibleAssetIds == null || visibleAssetIds.contains(table.getId())) { + visible.add(table.getId()); + } + } + return visible; + } + + private List loadObservations(List upstreamTables) { + Map tableBySuite = tableBySuite(upstreamTables); + Map> results = latestResults(new ArrayList<>(tableBySuite.keySet())); + Map suiteByTest = suiteByTest(tableBySuite.keySet()); + Map testCases = activeTestCases(suiteByTest.keySet()); + Map definitions = definitions(testCases.values()); + List observations = new ArrayList<>(); + for (TestCase testCase : testCases.values()) { + UUID suiteId = suiteByTest.get(testCase.getId()); + EntityReference table = tableBySuite.get(suiteId); + if (table != null) { + observations.add(toObservation(table, testCase, definitions, results.get(suiteId))); + } + } + return observations; + } + + private Map tableBySuite(List tables) { + if (tables.isEmpty()) { + return Map.of(); + } + List tableIds = tables.stream().map(table -> table.getId().toString()).toList(); + Map tablesById = + tables.stream().collect(Collectors.toMap(EntityReference::getId, Function.identity())); + Map result = new LinkedHashMap<>(); + for (CollectionDAO.EntityRelationshipObject relationship : + Entity.getCollectionDAO() + .relationshipDAO() + .findToBatch(tableIds, Relationship.CONTAINS.ordinal(), TABLE, TEST_SUITE)) { + result.put( + UUID.fromString(relationship.getToId()), + tablesById.get(UUID.fromString(relationship.getFromId()))); + } + return retainActiveSuites(result); + } + + private Map retainActiveSuites(Map tableBySuite) { + List active = + Entity.getEntityReferencesByIds( + TEST_SUITE, new ArrayList<>(tableBySuite.keySet()), Include.NON_DELETED); + Set activeIds = active.stream().map(EntityReference::getId).collect(Collectors.toSet()); + return tableBySuite.entrySet().stream() + .filter(entry -> activeIds.contains(entry.getKey())) + .collect( + Collectors.toMap( + Map.Entry::getKey, Map.Entry::getValue, (left, right) -> left, LinkedHashMap::new)); + } + + private Map suiteByTest(Set suiteIds) { + if (suiteIds.isEmpty()) { + return Map.of(); + } + List ids = suiteIds.stream().map(UUID::toString).toList(); + Map result = new LinkedHashMap<>(); + for (CollectionDAO.EntityRelationshipObject relationship : + Entity.getCollectionDAO() + .relationshipDAO() + .findToBatch(ids, Relationship.CONTAINS.ordinal(), TEST_SUITE, TEST_CASE)) { + result.putIfAbsent( + UUID.fromString(relationship.getToId()), UUID.fromString(relationship.getFromId())); + } + return result; + } + + private Map activeTestCases(Set testCaseIds) { + if (testCaseIds.isEmpty()) { + return Map.of(); + } + List tests = + Entity.getCollectionDAO() + .testCaseDAO() + .findEntitiesByIds(new ArrayList<>(testCaseIds), Include.NON_DELETED); + TestCaseRepository testCaseRepository = + (TestCaseRepository) Entity.getEntityRepository(TEST_CASE); + testCaseRepository.setFieldsInBulk(testCaseRepository.getFields(TEST_DEFINITION), tests); + return tests.stream().collect(Collectors.toMap(TestCase::getId, Function.identity())); + } + + private Map definitions(Iterable tests) { + Set ids = new LinkedHashSet<>(); + for (TestCase test : tests) { + if (test.getTestDefinition() != null) { + ids.add(test.getTestDefinition().getId()); + } + } + if (ids.isEmpty()) { + return Map.of(); + } + List definitions = + Entity.getCollectionDAO() + .testDefinitionDAO() + .findEntitiesByIds(new ArrayList<>(ids), Include.NON_DELETED); + return definitions.stream() + .collect(Collectors.toMap(TestDefinition::getId, Function.identity())); + } + + private Map> latestResults(List suiteIds) { + if (suiteIds.isEmpty()) { + return Map.of(); + } + TestCaseResultRepository repository = + (TestCaseResultRepository) Entity.getEntityTimeSeriesRepository(TEST_CASE_RESULT); + return repository.listResultSummariesForTestSuites(suiteIds); + } + + private Observation toObservation( + EntityReference table, + TestCase testCase, + Map definitions, + List summaries) { + ResultSummary result = latestFor(testCase.getFullyQualifiedName(), summaries); + TestDefinition definition = + testCase.getTestDefinition() == null + ? null + : definitions.get(testCase.getTestDefinition().getId()); + String dimension = + definition == null || definition.getDataQualityDimension() == null + ? DataQualityDimensions.NO_DIMENSION.value() + : definition.getDataQualityDimension().value(); + return new Observation(table, testCase, dimension, result); + } + + private ResultSummary latestFor(String testCaseFqn, List summaries) { + return listOrEmpty(summaries).stream() + .filter(summary -> testCaseFqn.equals(summary.getTestCaseName())) + .max(Comparator.comparing(ResultSummary::getTimestamp)) + .orElse(null); + } + + List loadIncidents(List observations, Set visibleAssets) { + Map observationByHash = new HashMap<>(); + List testCaseFqns = new ArrayList<>(); + for (Observation observation : observations) { + if (visibleAssets.contains(observation.asset().getId())) { + String fqn = observation.testCase().getFullyQualifiedName(); + observationByHash.put(FullyQualifiedName.buildHash(fqn), observation); + testCaseFqns.add(fqn); + } + } + if (testCaseFqns.isEmpty()) { + return List.of(); + } + List incidents = new ArrayList<>(); + Set seen = new HashSet<>(); + for (CollectionDAO.LatestRecordWithFQNHash record : + Entity.getCollectionDAO() + .testCaseResolutionStatusTimeSeriesDao() + .getLatestRecordBatch(testCaseFqns)) { + Observation observation = observationByHash.get(record.getEntityFQNHash()); + TestCaseResolutionStatus status = + JsonUtils.readValue(record.getJson(), TestCaseResolutionStatus.class); + if (observation != null && isUnresolved(status) && seen.add(status.getStateId())) { + incidents.add(toIncident(status, observation)); + } + } + return incidents; + } + + private boolean isUnresolved(TestCaseResolutionStatus status) { + return status != null + && status.getStateId() != null + && !TestCaseResolutionStatusTypes.Resolved.equals(status.getTestCaseResolutionStatusType()); + } + + private MetricIncident toIncident(TestCaseResolutionStatus status, Observation observation) { + return new MetricIncident() + .withId(status.getStateId()) + .withTestCase(observation.testCase().getEntityReference()) + .withAsset(observation.asset()) + .withSeverity(status.getSeverity() == null ? null : status.getSeverity().value()) + .withStatus(status.getTestCaseResolutionStatusType().value()) + .withTimestamp(status.getTimestamp()); + } + + static MetricObservability summarize( + EntityReference metric, + List linkedAssets, + List upstreamTables, + List observations, + List incidents, + Set visibleAssets) { + return summarize( + metric, + linkedAssets, + upstreamTables, + observations, + incidents, + visibleAssets, + visibleAssets); + } + + static MetricObservability summarize( + EntityReference metric, + List linkedAssets, + List upstreamTables, + List observations, + List incidents, + Set visibleAssets, + Set visibleLinkedAssets) { + RollupAccumulator accumulator = new RollupAccumulator(visibleAssets); + observations.forEach(accumulator::add); + Double score = accumulator.score(); + MetricHealth health = healthFor(score); + int restricted = upstreamTables.size() - visibleAssets.size(); + MetricObservabilityReasonCode reason = + reasonFor(linkedAssets, upstreamTables, score, health, restricted); + return new MetricObservability() + .withMetric(metric) + .withHealth(health) + .withScore(score) + .withReasonCode(reason) + .withRollupReason(reason.value()) + .withAssets(accumulator.assetRollups(upstreamTables)) + .withLinkedAssets(visibleLinkedAssets(linkedAssets, visibleLinkedAssets)) + .withDimensions(accumulator.dimensionRollups()) + .withTests(accumulator.testResults()) + .withIncidents(incidents) + .withStatusCounts(accumulator.statusCounts()) + .withSourceCoverage(accumulator.coverage(upstreamTables, restricted)) + .withLatestRunTime(accumulator.latestRunTime()) + .withPartial(restricted > 0) + .withUpstreamAssetCount(upstreamTables.size()) + .withEvaluatedAssetCount(accumulator.evaluatedAssetCount()); + } + + private static List visibleLinkedAssets( + List linkedAssets, Set visibleAssets) { + return linkedAssets.stream() + .filter(linked -> visibleAssets.contains(linked.getAsset().getId())) + .toList(); + } + + private static MetricObservabilityReasonCode reasonFor( + List linkedAssets, + List upstreamTables, + Double score, + MetricHealth health, + int restricted) { + MetricObservabilityReasonCode reason; + if (linkedAssets.isEmpty()) { + reason = MetricObservabilityReasonCode.NO_LINKED_ASSETS; + } else if (upstreamTables.isEmpty()) { + reason = MetricObservabilityReasonCode.NO_UPSTREAM_TABLES; + } else if (restricted > 0) { + reason = MetricObservabilityReasonCode.PARTIAL_DETAILS; + } else if (score == null) { + reason = MetricObservabilityReasonCode.NO_TERMINAL_RESULTS; + } else { + reason = MetricObservabilityReasonCode.fromValue(health.value()); + } + return reason; + } + + private MetricObservability unavailable() { + return new MetricObservability() + .withHealth(MetricHealth.UNKNOWN) + .withReasonCode(MetricObservabilityReasonCode.UNAVAILABLE) + .withRollupReason(MetricObservabilityReasonCode.UNAVAILABLE.value()) + .withEvaluatedAt(System.currentTimeMillis()); + } + + static MetricHealth healthFor(Double score) { + MetricHealth health; + if (score == null) { + health = MetricHealth.UNKNOWN; + } else if (score >= HEALTHY_THRESHOLD) { + health = MetricHealth.HEALTHY; + } else if (score >= AT_RISK_THRESHOLD) { + health = MetricHealth.AT_RISK; + } else { + health = MetricHealth.DEGRADED; + } + return health; + } + + static record Observation( + EntityReference asset, TestCase testCase, String dimension, ResultSummary result) {} + + private static final class RollupAccumulator { + private final Set visibleAssets; + private final Map sourceCounts = new LinkedHashMap<>(); + private final Map dimensionCounts = new LinkedHashMap<>(); + private final List testResults = new ArrayList<>(); + private int passed; + private int failed; + private int aborted; + private int queued; + private int missing; + private Long latestRunTime; + + private RollupAccumulator(Set visibleAssets) { + this.visibleAssets = visibleAssets; + } + + private void add(Observation observation) { + SourceCounts source = + sourceCounts.computeIfAbsent( + observation.asset().getId(), ignored -> new SourceCounts(observation.asset())); + source.activeTests++; + ResultSummary result = observation.result(); + if (result == null || result.getStatus() == null) { + missing++; + addVisibleTest(observation); + } else if (TestCaseStatus.Queued.equals(result.getStatus())) { + queued++; + addVisibleTest(observation); + } else if (isTerminal(result.getStatus())) { + addTerminal(observation, source); + } else { + missing++; + addVisibleTest(observation); + } + } + + private boolean isTerminal(TestCaseStatus status) { + return TestCaseStatus.Success.equals(status) + || TestCaseStatus.Failed.equals(status) + || TestCaseStatus.Aborted.equals(status); + } + + private void addTerminal(Observation observation, SourceCounts source) { + TestCaseStatus status = observation.result().getStatus(); + if (TestCaseStatus.Success.equals(status)) { + passed++; + source.passed++; + } else if (TestCaseStatus.Failed.equals(status)) { + failed++; + source.failed++; + } else if (TestCaseStatus.Aborted.equals(status)) { + aborted++; + source.aborted++; + } + source.latestRun = max(source.latestRun, observation.result().getTimestamp()); + latestRunTime = max(latestRunTime, observation.result().getTimestamp()); + dimensionCounts + .computeIfAbsent(observation.dimension(), ignored -> new StatusCounter()) + .add(status); + addVisibleTest(observation); + } + + private void addVisibleTest(Observation observation) { + if (visibleAssets.contains(observation.asset().getId())) { + ResultSummary result = observation.result(); + testResults.add( + new MetricTestResult() + .withTestCase(observation.testCase().getEntityReference()) + .withAsset(observation.asset()) + .withDimension(observation.dimension()) + .withStatus( + result == null || result.getStatus() == null + ? null + : result.getStatus().value()) + .withTimestamp(result == null ? null : result.getTimestamp())); + } + } + + private Double score() { + int terminal = passed + failed + aborted; + return terminal == 0 ? null : (passed / (double) terminal) * 100.0; + } + + private List assetRollups(List upstreamTables) { + List rollups = new ArrayList<>(); + for (EntityReference table : upstreamTables) { + if (visibleAssets.contains(table.getId())) { + SourceCounts counts = sourceCounts.getOrDefault(table.getId(), new SourceCounts(table)); + rollups.add(counts.toRollup()); + } + } + return rollups; + } + + private List dimensionRollups() { + return dimensionCounts.entrySet().stream() + .map(entry -> entry.getValue().toDimension(entry.getKey())) + .toList(); + } + + private MetricTestStatusCounts statusCounts() { + return new MetricTestStatusCounts() + .withPassed(passed) + .withFailed(failed) + .withAborted(aborted) + .withQueued(queued) + .withMissing(missing) + .withTerminal(passed + failed + aborted); + } + + private MetricSourceCoverage coverage( + List upstreamTables, int restrictedTables) { + int testedTables = + (int) sourceCounts.values().stream().filter(source -> source.activeTests > 0).count(); + double percentage = + upstreamTables.isEmpty() ? 0.0 : (testedTables / (double) upstreamTables.size()) * 100.0; + return new MetricSourceCoverage() + .withUpstreamTables(upstreamTables.size()) + .withTestedTables(testedTables) + .withVisibleTables(visibleAssets.size()) + .withRestrictedTables(restrictedTables) + .withCoveragePercent(percentage) + .withPartial(restrictedTables > 0); + } + + private int evaluatedAssetCount() { + return (int) sourceCounts.values().stream().filter(SourceCounts::hasTerminal).count(); + } + + private List testResults() { + return List.copyOf(testResults); + } + + private Long latestRunTime() { + return latestRunTime; + } + } + + private static final class SourceCounts { + private final EntityReference asset; + private int activeTests; + private int passed; + private int failed; + private int aborted; + private Long latestRun; + + private SourceCounts(EntityReference asset) { + this.asset = asset; + } + + private boolean hasTerminal() { + return passed + failed + aborted > 0; + } + + private MetricAssetRollup toRollup() { + int terminal = passed + failed + aborted; + Double score = terminal == 0 ? null : (passed / (double) terminal) * 100.0; + return new MetricAssetRollup() + .withAsset(asset) + .withScore(score) + .withHealth(healthFor(score)) + .withTotal(terminal) + .withPassed(passed) + .withFailed(failed) + .withAborted(aborted) + .withLatestRunTime(latestRun) + .withRedacted(false); + } + } + + private static final class StatusCounter { + private int passed; + private int failed; + private int aborted; + + private void add(TestCaseStatus status) { + if (TestCaseStatus.Success.equals(status)) { + passed++; + } else if (TestCaseStatus.Failed.equals(status)) { + failed++; + } else if (TestCaseStatus.Aborted.equals(status)) { + aborted++; + } + } + + private MetricDimensionRollup toDimension(String dimension) { + int total = passed + failed + aborted; + double score = total == 0 ? 0.0 : (passed / (double) total) * 100.0; + return new MetricDimensionRollup() + .withDimension(dimension) + .withTotal(total) + .withPassed(passed) + .withFailed(failed) + .withAborted(aborted) + .withScore(score); + } + } + + private static Long max(Long left, Long right) { + Long result = left; + if (right != null && (left == null || right > left)) { + result = right; + } + return result; + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricRepository.java index 00d3abedac82..5d2a6068566d 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/MetricRepository.java @@ -26,16 +26,25 @@ import static org.openmetadata.schema.type.Include.NON_DELETED; import static org.openmetadata.service.Entity.METRIC; import static org.openmetadata.service.Entity.TEAM; +import static org.openmetadata.service.Entity.USER; import static org.openmetadata.service.exception.CatalogExceptionMessage.notReviewer; import java.io.IOException; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; -import java.util.TreeSet; import java.util.UUID; +import java.util.function.Predicate; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.csv.CSVRecord; @@ -45,10 +54,15 @@ import org.openmetadata.csv.CsvExportProgressCallback; import org.openmetadata.csv.CsvImportProgressCallback; import org.openmetadata.csv.EntityCsv; +import org.openmetadata.schema.api.data.MetricAssetDirection; import org.openmetadata.schema.api.data.MetricDimension; import org.openmetadata.schema.api.data.MetricExpression; +import org.openmetadata.schema.api.data.MetricHierarchyContext; +import org.openmetadata.schema.api.data.MetricHierarchyItem; import org.openmetadata.schema.api.data.MetricMeasure; +import org.openmetadata.schema.api.data.MetricObservability; import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; import org.openmetadata.schema.entity.teams.Team; import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.EntityStatus; @@ -57,14 +71,20 @@ import org.openmetadata.schema.type.MetricGranularity; import org.openmetadata.schema.type.MetricType; import org.openmetadata.schema.type.MetricUnitOfMeasurement; +import org.openmetadata.schema.type.Paging; import org.openmetadata.schema.type.Relationship; import org.openmetadata.schema.type.TagLabel; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; import org.openmetadata.schema.type.change.ChangeSource; import org.openmetadata.schema.type.csv.CsvDocumentation; import org.openmetadata.schema.type.csv.CsvFile; import org.openmetadata.schema.type.csv.CsvHeader; import org.openmetadata.schema.type.csv.CsvImportResult; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.schema.utils.ResultList; import org.openmetadata.service.Entity; +import org.openmetadata.service.events.lifecycle.EntityLifecycleEventDispatcher; import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.resources.metrics.MetricResource; import org.openmetadata.service.security.AuthorizationException; @@ -75,9 +95,23 @@ @Slf4j public class MetricRepository extends EntityRepository { - private static final String UPDATE_FIELDS = "relatedMetrics,assets,dimensions,measures,filters"; - private static final String PATCH_FIELDS = "relatedMetrics,assets,dimensions,measures,filters"; + private static final String UPDATE_FIELDS = + "relatedMetrics,dimensions,measures,filters,parent,metricGroup"; + private static final String PATCH_FIELDS = + "relatedMetrics,dimensions,measures,filters,parent,metricGroup"; static final String FIELD_ASSETS = "assets"; + static final String FIELD_PARENT = "parent"; + static final String FIELD_CHILDREN = "children"; + static final String FIELD_CHILDREN_COUNT = "childrenCount"; + static final String FIELD_METRIC_GROUP = "metricGroup"; + private static final int ASSET_SCAN_BATCH_SIZE = 200; + private static final int HIERARCHY_SCAN_BATCH_SIZE = 200; + static final int MAX_OBSERVABILITY_ASSET_DETAILS = 1_000; + private static final String HIERARCHY_FIELDS = + "owners,experts,reviewers,parent,childrenCount,metricGroup,domains,tags"; + + private final MetricObservabilityBuilder observabilityBuilder = + new MetricObservabilityBuilder(this); public MetricRepository() { super( @@ -90,8 +124,16 @@ public MetricRepository() { supportsSearch = true; renameAllowed = true; - // Register bulk field fetchers for efficient database operations + // Asset relationships are served and mutated only through the bounded /assets APIs. Keeping + // this relationship-derived model property out of generic fields also prevents fields=assets + // from rebuilding an unbounded list on Metric GET/list requests. + allowedFields.remove(FIELD_ASSETS); + fieldFetchers.put("relatedMetrics", this::fetchAndSetRelatedMetrics); + fieldFetchers.put(FIELD_PARENT, this::fetchAndSetParents); + fieldFetchers.put(FIELD_CHILDREN, this::fetchAndSetChildren); + fieldFetchers.put(FIELD_CHILDREN_COUNT, this::fetchAndSetChildrenCount); + fieldFetchers.put(FIELD_METRIC_GROUP, this::fetchAndSetMetricGroups); } @Override @@ -126,6 +168,115 @@ public void prepare(Metric metric, boolean update) { validateRelatedTerms(metric, metric.getRelatedMetrics()); validateCustomUnitOfMeasurement(metric); metric.setAssets(EntityUtil.populateEntityReferences(metric.getAssets())); + validateSelfParentReference(metric); + if (metric.getParent() != null) { + metric.setParent(Entity.getEntityReference(metric.getParent().withType(METRIC), NON_DELETED)); + } + resolveHierarchyGroup(metric); + validateHierarchy(metric); + } + + private void resolveHierarchyGroup(Metric metric) { + EntityReference requestedGroup = resolveGroup(metric.getMetricGroup()); + EntityReference inheritedGroup = groupForParent(metric.getParent()); + metric.setMetricGroup( + effectiveHierarchyGroup(metric.getParent(), requestedGroup, inheritedGroup)); + } + + static EntityReference effectiveHierarchyGroup( + EntityReference parent, EntityReference requestedGroup, EntityReference inheritedGroup) { + return parent == null ? requestedGroup : inheritedGroup; + } + + static void validateSelfParentReference(Metric metric) { + EntityReference parent = metric.getParent(); + if (parent == null) { + return; + } + String metricFqn = + metric.getFullyQualifiedName() == null ? metric.getName() : metric.getFullyQualifiedName(); + String parentFqn = + parent.getFullyQualifiedName() == null ? parent.getName() : parent.getFullyQualifiedName(); + if (metricFqn != null && metricFqn.equals(parentFqn)) { + throw new IllegalArgumentException( + String.format( + "Invalid hierarchy: Metric '%s' cannot be its own parent", metric.getName())); + } + } + + private EntityReference resolveGroup(EntityReference group) { + return group == null + ? null + : Entity.getEntityReference(group.withType(Entity.METRIC_GROUP), NON_DELETED); + } + + private EntityReference groupForParent(EntityReference parent) { + EntityReference result = null; + if (parent != null) { + List groups = + findFrom(parent.getId(), METRIC, Relationship.HAS, Entity.METRIC_GROUP); + result = groups.isEmpty() ? null : groups.getFirst(); + } + return result; + } + + /** + * Rejects a parent assignment that would make the metric its own ancestor. Metric fully qualified + * names are flat, so unlike glossary terms there is no FQN prefix to compare — the ancestor chain + * has to be walked one CONTAINS edge at a time. The visited set both terminates the walk and + * catches pre-existing cycles in the stored data. + */ + private void validateHierarchy(Metric metric) { + EntityReference parent = metric.getParent(); + if (parent == null) { + return; + } + if (metric.getId() != null && metric.getId().equals(parent.getId())) { + throw new IllegalArgumentException( + String.format( + "Invalid hierarchy: Metric '%s' cannot be its own parent", metric.getName())); + } + if (metric.getName() != null && metric.getName().equals(parent.getName())) { + throw new IllegalArgumentException( + String.format( + "Invalid hierarchy: Metric '%s' cannot be its own parent", metric.getName())); + } + if (metric.getId() == null || parent.getId() == null) { + return; + } + Set visited = new HashSet<>(); + visited.add(metric.getId()); + UUID ancestorId = parent.getId(); + while (ancestorId != null) { + if (visited.contains(ancestorId)) { + throw new IllegalArgumentException( + String.format( + "Circular reference detected: Cannot set parent relationship as it would create a cycle. " + + "Metric '%s' (or one of its descendants) already exists in the parent chain.", + metric.getName())); + } + visited.add(ancestorId); + List ancestors = + daoCollection + .relationshipDAO() + .findFrom(ancestorId, METRIC, Relationship.CONTAINS.ordinal(), METRIC); + ancestorId = ancestors.isEmpty() ? null : ancestors.getFirst().getId(); + } + } + + /** + * A metric with no reviewers has nothing to approve, so it starts life Approved. With reviewers + * it starts as Draft and MetricApprovalWorkflow drives it through review. Unlike glossary terms + * there is no reviewer inheritance — a metric's parent does not lend it reviewers. + */ + @Override + protected void setDefaultStatus(Metric entity, boolean update) { + if (!update + || entity.getEntityStatus() == null + || entity.getEntityStatus() == EntityStatus.UNPROCESSED) { + entity.setEntityStatus( + nullOrEmpty(entity.getReviewers()) ? EntityStatus.APPROVED : EntityStatus.DRAFT); + } } private void validateCustomUnitOfMeasurement(Metric metric) { @@ -137,10 +288,8 @@ private void validateCustomUnitOfMeasurement(Metric metric) { throw new IllegalArgumentException( "customUnitOfMeasurement is required when unitOfMeasurement is OTHER"); } - // Trim and normalize metric.setCustomUnitOfMeasurement(customUnit.trim()); } else { - // Clear custom unit if not OTHER to maintain consistency metric.setCustomUnitOfMeasurement(null); } } @@ -151,12 +300,50 @@ public void setFields( metric.setRelatedMetrics( fields.contains("relatedMetrics") ? getRelatedMetrics(metric) : metric.getRelatedMetrics()); metric.setAssets(fields.contains(FIELD_ASSETS) ? getAssets(metric) : metric.getAssets()); + metric.setParent(fields.contains(FIELD_PARENT) ? getParent(metric) : metric.getParent()); + metric.setChildren( + fields.contains(FIELD_CHILDREN) ? getChildren(metric) : metric.getChildren()); + metric.setChildrenCount( + fields.contains(FIELD_CHILDREN_COUNT) + ? getChildrenCount(metric) + : metric.getChildrenCount()); + metric.setMetricGroup( + fields.contains(FIELD_METRIC_GROUP) ? getMetricGroup(metric) : metric.getMetricGroup()); + } + + /** + * The group a metric belongs to, derived from the group's HAS edge. Groups own the membership + * list, so this is read-only on the metric — adding a metric to a group is done through the + * group's own endpoints. + */ + private EntityReference getMetricGroup(Metric metric) { + String groupId = + daoCollection.metricDAO().findActiveGroupId(metric.getId(), Relationship.HAS.ordinal()); + return groupId == null + ? null + : Entity.getEntityReferenceById(Entity.METRIC_GROUP, UUID.fromString(groupId), NON_DELETED); } @Override protected void clearFields(Metric entity, EntityUtil.Fields fields) { entity.setRelatedMetrics(fields.contains("relatedMetrics") ? entity.getRelatedMetrics() : null); entity.setAssets(fields.contains(FIELD_ASSETS) ? entity.getAssets() : null); + entity.setParent(fields.contains(FIELD_PARENT) ? entity.getParent() : null); + entity.setChildren(fields.contains(FIELD_CHILDREN) ? entity.getChildren() : null); + entity.setChildrenCount( + fields.contains(FIELD_CHILDREN_COUNT) ? entity.getChildrenCount() : null); + entity.setMetricGroup(fields.contains(FIELD_METRIC_GROUP) ? entity.getMetricGroup() : null); + } + + private Integer getChildrenCount(Metric metric) { + return daoCollection + .relationshipDAO() + .countNonDeletedChildMetrics(metric.getId(), Relationship.CONTAINS.ordinal()); + } + + @Override + protected List getChildren(Metric metric) { + return findTo(metric.getId(), METRIC, Relationship.CONTAINS, METRIC); } /** @@ -167,18 +354,103 @@ private List getAssets(Metric metric) { return findTo(metric.getId(), METRIC, Relationship.APPLIED_TO, null); } - // Individual field fetchers registered in constructor private void fetchAndSetRelatedMetrics(List metrics, EntityUtil.Fields fields) { if (!fields.contains("relatedMetrics") || metrics == null || metrics.isEmpty()) { return; } - // Use bulk relationship fetching for related metrics setFieldFromMap(true, metrics, batchFetchRelatedMetrics(metrics), Metric::setRelatedMetrics); } + private void fetchAndSetParents(List metrics, EntityUtil.Fields fields) { + if (!fields.contains(FIELD_PARENT) || nullOrEmpty(metrics)) { + return; + } + List records = + daoCollection + .relationshipDAO() + .findFromBatch( + entityListToStrings(metrics), Relationship.CONTAINS.ordinal(), METRIC, NON_DELETED); + Map parents = new HashMap<>(); + for (CollectionDAO.EntityRelationshipObject record : records) { + parents.put( + UUID.fromString(record.getToId()), + Entity.getEntityReferenceById(METRIC, UUID.fromString(record.getFromId()), NON_DELETED)); + } + for (Metric metric : metrics) { + metric.setParent(parents.get(metric.getId())); + } + } + + @Override + protected void fetchAndSetChildren(List metrics, EntityUtil.Fields fields) { + if (!fields.contains(FIELD_CHILDREN) || nullOrEmpty(metrics)) { + return; + } + Map> children = new HashMap<>(); + for (Metric metric : metrics) { + children.put(metric.getId(), new ArrayList<>()); + } + List records = + daoCollection + .relationshipDAO() + .findToBatch( + entityListToStrings(metrics), Relationship.CONTAINS.ordinal(), METRIC, METRIC); + for (CollectionDAO.EntityRelationshipObject record : records) { + UUID parentId = UUID.fromString(record.getFromId()); + EntityReference child = + Entity.getEntityReferenceById(METRIC, UUID.fromString(record.getToId()), NON_DELETED); + children.get(parentId).add(child); + } + for (Metric metric : metrics) { + metric.setChildren(children.get(metric.getId())); + } + } + + private void fetchAndSetMetricGroups(List metrics, EntityUtil.Fields fields) { + if (!fields.contains(FIELD_METRIC_GROUP) || nullOrEmpty(metrics)) { + return; + } + Map groups = new HashMap<>(); + for (CollectionDAO.EntityRelationshipObject record : + daoCollection + .metricDAO() + .findActiveGroups(entityListToStrings(metrics), Relationship.HAS.ordinal())) { + groups.put( + UUID.fromString(record.getToId()), + Entity.getEntityReferenceById( + Entity.METRIC_GROUP, UUID.fromString(record.getFromId()), NON_DELETED)); + } + for (Metric metric : metrics) { + metric.setMetricGroup(groups.get(metric.getId())); + } + } + + private void fetchAndSetChildrenCount(List metrics, EntityUtil.Fields fields) { + if (!fields.contains(FIELD_CHILDREN_COUNT) || nullOrEmpty(metrics)) { + return; + } + Map counts = new HashMap<>(); + for (CollectionDAO.EntityRelationshipCount record : + daoCollection + .relationshipDAO() + .countNonDeletedChildMetricsBatch( + entityListToStrings(metrics), Relationship.CONTAINS.ordinal())) { + counts.put(record.getId(), record.getCount()); + } + for (Metric metric : metrics) { + metric.setChildrenCount(counts.getOrDefault(metric.getId(), 0)); + } + } + @Override protected List getFieldsStrippedFromStorageJson() { - return List.of("relatedMetrics", "assets"); + return List.of( + "relatedMetrics", + "assets", + FIELD_PARENT, + "children", + FIELD_CHILDREN_COUNT, + FIELD_METRIC_GROUP); } @Override @@ -186,15 +458,53 @@ public void storeEntity(Metric metric, boolean update) { store(metric, update); } + @Override + protected EntityDAO entityDAOForWrite() { + CollectionDAO transactionDAO = RepositoryTransactionContext.currentDAO(); + return transactionDAO == null ? dao : transactionDAO.metricDAO(); + } + @Override public void storeEntities(List entities) { storeMany(entities); } + @Override + public List createManyEntitiesForImport(List entities, String impersonatedBy) { + List created = super.createManyEntitiesForImport(entities, impersonatedBy); + reconcileImportedHierarchyGroups(created); + return created; + } + + @Override + public List updateManyEntitiesForImport( + List originals, List updates, String updatedBy, String impersonatedBy) { + List updated = + super.updateManyEntitiesForImport(originals, updates, updatedBy, impersonatedBy); + reconcileImportedHierarchyGroups(updated); + return updated; + } + + private void reconcileImportedHierarchyGroups(List metrics) { + if (nullOrEmpty(metrics)) { + return; + } + MetricGroupRepository groupRepository = + (MetricGroupRepository) Entity.getEntityRepository(Entity.METRIC_GROUP); + for (Metric metric : metrics) { + if (metric.getParent() == null) { + MetricGroupRepository.MembershipChange change = + groupRepository.assignHierarchyGroup(metric.getId(), metric.getMetricGroup()); + groupRepository.publishMembershipChange(change); + } + } + } + @Override protected void clearEntitySpecificRelationshipsForMany(List entities) { if (entities.isEmpty()) return; List ids = entities.stream().map(Metric::getId).toList(); + deleteFromMany(ids, METRIC, Relationship.EXPERT, USER); deleteFromMany(ids, Entity.METRIC, Relationship.RELATED_TO, Entity.METRIC); deleteToMany(ids, Entity.METRIC, Relationship.RELATED_TO, Entity.METRIC); // Mirror storeRelationships' re-add of the APPLIED_TO edges so the batch import/update path @@ -206,10 +516,18 @@ protected void clearEntitySpecificRelationshipsForMany(List entities) { List assetCarryingIds = entities.stream().filter(metric -> metric.getAssets() != null).map(Metric::getId).toList(); deleteFromMany(assetCarryingIds, Entity.METRIC, Relationship.APPLIED_TO, null); + // Only the to-side (metric-as-child) CONTAINS edge is cleared, so storeRelationships can + // re-add the parent link. Clearing the from-side would orphan the metric's own children and + // also drop the metric -> dataContract CONTAINS edges, which are not re-added here. + deleteToMany(ids, Entity.METRIC, Relationship.CONTAINS, Entity.METRIC); + deleteToMany(ids, Entity.METRIC, Relationship.HAS, Entity.METRIC_GROUP); } @Override public void storeRelationships(Metric metric) { + for (EntityReference expert : listOrEmpty(metric.getExperts())) { + addRelationship(metric.getId(), expert.getId(), METRIC, USER, Relationship.EXPERT); + } for (EntityReference relatedMetric : listOrEmpty(metric.getRelatedMetrics())) { addRelationship( metric.getId(), relatedMetric.getId(), METRIC, METRIC, Relationship.RELATED_TO, true); @@ -218,6 +536,36 @@ public void storeRelationships(Metric metric) { addRelationship( metric.getId(), asset.getId(), METRIC, asset.getType(), Relationship.APPLIED_TO); } + if (metric.getParent() != null) { + addRelationship( + metric.getParent().getId(), metric.getId(), METRIC, METRIC, Relationship.CONTAINS); + } + replaceGroupMembership(metric); + } + + private void replaceGroupMembership(Metric metric) { + for (EntityReference group : + findFrom(metric.getId(), METRIC, Relationship.HAS, Entity.METRIC_GROUP)) { + if (!sameReferenceById(group, metric.getMetricGroup())) { + deleteRelationship( + group.getId(), Entity.METRIC_GROUP, metric.getId(), METRIC, Relationship.HAS); + } + } + if (metric.getMetricGroup() != null) { + addRelationship( + metric.getMetricGroup().getId(), + metric.getId(), + Entity.METRIC_GROUP, + METRIC, + Relationship.HAS); + } + } + + @Override + public void restorePatchAttributes(Metric original, Metric updated) { + super.restorePatchAttributes(original, updated); + // children/childrenCount are derived from CONTAINS edges and cannot be patched directly + updated.withChildren(original.getChildren()).withChildrenCount(original.getChildrenCount()); } private List getRelatedMetrics(Metric metric) { @@ -321,7 +669,10 @@ protected void createEntity(CSVPrinter printer, List csvRecords) thro .withDomains(getDomains(printer, csvRecord, 15)) .withDataProducts(getEntityReferences(printer, csvRecord, 16, Entity.DATA_PRODUCT)) .withEntityStatus(getEntityStatus(printer, csvRecord, 17)) - .withExtension(getExtension(printer, csvRecord, 18)); + .withExtension(getExtension(printer, csvRecord, 18)) + .withParent(getEntityReference(printer, csvRecord, 19, METRIC)) + .withExperts(getEntityReferences(printer, csvRecord, 20, USER)) + .withMetricGroup(getEntityReference(printer, csvRecord, 21, Entity.METRIC_GROUP)); if (processRecord) { createEntity(printer, csvRecord, metric); @@ -360,6 +711,13 @@ protected void addRecord(CsvFile csvFile, Metric entity) { addField( recordList, entity.getEntityStatus() == null ? null : entity.getEntityStatus().value()); addExtension(recordList, entity.getExtension()); + addField( + recordList, + entity.getParent() == null ? null : entity.getParent().getFullyQualifiedName()); + addEntityReferences(recordList, entity.getExperts()); + addField( + recordList, + entity.getMetricGroup() == null ? null : entity.getMetricGroup().getFullyQualifiedName()); addRecord(csvFile, recordList); } @@ -523,7 +881,59 @@ public void entitySpecificUpdate(boolean consolidatingChanges) { compareAndUpdate( "filters", () -> recordChange("filters", original.getFilters(), updated.getFilters())); compareAndUpdate("relatedMetrics", () -> updateRelatedMetrics(original, updated)); - compareAndUpdate(FIELD_ASSETS, () -> updateAssets(original, updated)); + compareAndUpdate(FIELD_PARENT, () -> updateParent(original, updated)); + compareAndUpdateAny( + () -> updateMetricGroup(original, updated), FIELD_PARENT, FIELD_METRIC_GROUP); + } + + private void updateMetricGroup(Metric original, Metric updated) { + if (!sameReferenceById(original.getMetricGroup(), updated.getMetricGroup())) { + MetricGroupRepository groupRepository = + (MetricGroupRepository) Entity.getEntityRepository(Entity.METRIC_GROUP); + MetricGroupRepository.MembershipChange change = + groupRepository.assignHierarchyGroupInCurrentTransaction( + updated.getId(), updated.getMetricGroup()); + deferReactOperation(() -> groupRepository.publishMembershipChange(change)); + recordChange( + FIELD_METRIC_GROUP, + original.getMetricGroup(), + updated.getMetricGroup(), + true, + MetricRepository::sameReferenceById); + } + } + + /** + * Swaps the CONTAINS edge to the new parent. Metric fully qualified names are flat, so — unlike + * glossary terms — reparenting rewrites no FQNs and cascades to no descendants. + */ + private void updateParent(Metric original, Metric updated) { + EntityReference originalParent = original.getParent(); + EntityReference updatedParent = updated.getParent(); + if (sameReferenceById(originalParent, updatedParent)) { + return; + } + validateHierarchy(updated); + if (originalParent != null) { + deleteRelationship( + originalParent.getId(), METRIC, original.getId(), METRIC, Relationship.CONTAINS); + } + if (updatedParent != null) { + addRelationship( + updatedParent.getId(), updated.getId(), METRIC, METRIC, Relationship.CONTAINS); + } + recordChange( + FIELD_PARENT, originalParent, updatedParent, true, MetricRepository::sameReferenceById); + // Both parents' search documents carry children/childrenCount, so refresh them or the counts + // drift until the next full reindex. + refreshParentDocument(originalParent); + refreshParentDocument(updatedParent); + } + + private void refreshParentDocument(EntityReference parent) { + if (parent != null) { + EntityLifecycleEventDispatcher.getInstance().onEntityUpdated(parent, null); + } } private void updateRelatedMetrics(Metric original, Metric updated) { @@ -540,57 +950,662 @@ private void updateRelatedMetrics(Metric original, Metric updated) { updatedRelatedMetrics, true); } + } - /** - * Diffs the metric→asset APPLIED_TO edges on update/patch. Applied-to assets are - * heterogeneous (tables, dashboards, ...), and updateToRelationships inserts additions under - * the single passed target type — so the diff runs once per asset type over the union of - * original and updated types. - */ - private void updateAssets(Metric original, Metric updated) { - List originalAssets = typedAssets(original.getAssets()); - List updatedAssets = typedAssets(updated.getAssets()); - Set assetTypes = new TreeSet<>(); - originalAssets.forEach(asset -> assetTypes.add(asset.getType())); - updatedAssets.forEach(asset -> assetTypes.add(asset.getType())); - for (String assetType : assetTypes) { - updateToRelationships( - FIELD_ASSETS, - METRIC, - original.getId(), - Relationship.APPLIED_TO, - assetType, - ofType(originalAssets, assetType), - ofType(updatedAssets, assetType), - false); + public MetricObservability getObservability(UUID metricId) { + return observabilityBuilder.build(metricId); + } + + public MetricObservability getObservability(UUID metricId, Set visibleAssetIds) { + return observabilityBuilder.build(metricId, visibleAssetIds); + } + + public MetricObservability getObservability( + UUID metricId, List linkedAssets, Set visibleAssetIds) { + return observabilityBuilder.build(metricId, linkedAssets, visibleAssetIds); + } + + public ResultList listHierarchy(int limit, int offset, String query) { + String nameLike = MetricGroupRepository.buildNameLike(query); + HierarchyScan scan = scanUnrestrictedHierarchyRows(limit, offset, nameLike); + List rows = scan.rows(); + Map metrics = loadMetricsById(hierarchyIds(rows, METRIC)); + metrics.replaceAll( + (id, metric) -> sanitizeHierarchyMetric(metric, ignored -> true, ignored -> true)); + Map groups = loadGroupsById(hierarchyIds(rows, Entity.METRIC_GROUP)); + return buildHierarchyResult(scan, limit, offset, metrics, groups); + } + + public ResultList listHierarchy( + int limit, + int offset, + String query, + Predicate canViewMetric, + Predicate canViewGroup) { + CollectionDAO.MetricDAO metricDAO = daoCollection.metricDAO(); + String nameLike = MetricGroupRepository.buildNameLike(query); + HierarchyScan scan = + scanHierarchyRows(metricDAO, limit, offset, query, nameLike, canViewMetric, canViewGroup); + List rows = scan.rows(); + Map metrics = loadMetricsById(hierarchyIds(rows, METRIC)); + metrics.replaceAll( + (id, metric) -> + sanitizeHierarchyMetricWithVisibleCount(metric, canViewMetric, canViewGroup)); + Map groups = + loadGroupsById(hierarchyIds(rows, Entity.METRIC_GROUP), canViewMetric); + return buildHierarchyResult(scan, limit, offset, metrics, groups); + } + + HierarchyScan scanUnrestrictedHierarchyRows(int limit, int offset, String nameLike) { + CollectionDAO.MetricDAO metricDAO = daoCollection.metricDAO(); + List rows = + metricDAO.listHierarchy( + Relationship.CONTAINS.ordinal(), Relationship.HAS.ordinal(), nameLike, limit, offset); + int total = + metricDAO.countHierarchy( + Relationship.CONTAINS.ordinal(), Relationship.HAS.ordinal(), nameLike); + return new HierarchyScan(rows, total); + } + + private ResultList buildHierarchyResult( + HierarchyScan scan, + int limit, + int offset, + Map metrics, + Map groups) { + List data = new ArrayList<>(); + for (CollectionDAO.MetricDAO.HierarchyRow row : scan.rows()) { + data.add(toHierarchyItem(row, metrics, groups)); + } + Paging paging = new Paging().withOffset(offset).withLimit(limit).withTotal(scan.total()); + return new ResultList<>(data, paging); + } + + private HierarchyScan scanHierarchyRows( + CollectionDAO.MetricDAO metricDAO, + int limit, + int offset, + String query, + String nameLike, + Predicate canViewMetric, + Predicate canViewGroup) { + List page = new ArrayList<>(); + int databaseOffset = 0; + int visible = 0; + List batch; + do { + batch = + metricDAO.listHierarchy( + Relationship.CONTAINS.ordinal(), + Relationship.HAS.ordinal(), + nameLike, + HIERARCHY_SCAN_BATCH_SIZE, + databaseOffset); + Map metricReferences = + loadReferences(hierarchyIds(batch, METRIC), METRIC); + Map groupReferences = + loadReferences(hierarchyIds(batch, Entity.METRIC_GROUP), Entity.METRIC_GROUP); + for (CollectionDAO.MetricDAO.HierarchyRow row : batch) { + EntityReference reference = + METRIC.equals(row.entityType()) + ? metricReferences.get(row.id()) + : groupReferences.get(row.id()); + if (reference != null + && hierarchyRowVisible(row, reference, query, canViewMetric, canViewGroup)) { + if (visible >= offset && page.size() < limit) { + page.add(row); + } + visible++; + } } + databaseOffset += batch.size(); + } while (batch.size() == HIERARCHY_SCAN_BATCH_SIZE); + return new HierarchyScan(page, visible); + } + + private boolean hierarchyRowVisible( + CollectionDAO.MetricDAO.HierarchyRow row, + EntityReference reference, + String query, + Predicate canViewMetric, + Predicate canViewGroup) { + if (METRIC.equals(row.entityType())) { + return canViewMetric.test(reference) + && subtreeMatchesQuery(reference.getId(), query, canViewMetric); } + if (!canViewGroup.test(reference)) { + return false; + } + if (MetricGroupRepository.referenceMatchesQuery(reference, query)) { + return true; + } + MetricGroupRepository groupRepository = + (MetricGroupRepository) Entity.getEntityRepository(Entity.METRIC_GROUP); + return groupRepository.hasVisibleMemberMatching(reference.getId(), query, canViewMetric); + } - /** References with a null/blank type (bad or legacy data) cannot be diffed; skip them. */ - private List typedAssets(List refs) { - List valid = new ArrayList<>(); - for (EntityReference ref : listOrEmpty(refs)) { - if (ref != null && !nullOrEmpty(ref.getType())) { - valid.add(ref); + private boolean subtreeMatchesQuery( + UUID rootId, String query, Predicate canViewMetric) { + if (nullOrEmpty(query) || query.trim().isEmpty()) { + return true; + } + Set ids = new LinkedHashSet<>(); + ArrayDeque pending = new ArrayDeque<>(List.of(rootId)); + while (!pending.isEmpty()) { + UUID current = pending.removeFirst(); + if (ids.add(current)) { + daoCollection + .metricDAO() + .listDescendantSeedIds(current, Relationship.CONTAINS.ordinal()) + .stream() + .map(UUID::fromString) + .forEach(pending::addLast); + } + } + return loadReferences(new ArrayList<>(ids), METRIC).values().stream() + .anyMatch( + metric -> + canViewMetric.test(metric) + && MetricGroupRepository.referenceMatchesQuery(metric, query)); + } + + private List hierarchyIds( + List rows, String entityType) { + return rows.stream() + .filter(row -> entityType.equals(row.entityType())) + .map(CollectionDAO.MetricDAO.HierarchyRow::id) + .toList(); + } + + static MetricHierarchyItem toHierarchyItem( + CollectionDAO.MetricDAO.HierarchyRow row, + Map metrics, + Map groups) { + MetricHierarchyItem item = + new MetricHierarchyItem().withKind(MetricHierarchyItem.Kind.fromValue(row.entityType())); + if (METRIC.equals(row.entityType())) { + item.setMetric(metrics.get(row.id())); + } else { + item.setGroup(groups.get(row.id())); + } + return item; + } + + private Map loadMetricsById(List ids) { + List metrics = daoCollection.metricDAO().findEntitiesByIds(ids, NON_DELETED); + setFieldsInBulk(getFields(HIERARCHY_FIELDS), metrics); + return metrics.stream().collect(Collectors.toMap(Metric::getId, metric -> metric)); + } + + private Map loadGroupsById( + List ids, Predicate canViewMetric) { + Map groups = loadGroupsById(ids); + MetricGroupRepository repository = metricGroupRepository(); + groups + .values() + .forEach( + group -> + group.setMetricCount(repository.visibleMetricCount(group.getId(), canViewMetric))); + return groups; + } + + private Map loadGroupsById(List ids) { + List groups = daoCollection.metricGroupDAO().findEntitiesByIds(ids, NON_DELETED); + MetricGroupRepository repository = metricGroupRepository(); + repository.setFieldsInBulk(repository.getFields("owners,domains,tags,metricCount"), groups); + return groups.stream() + .map( + group -> { + MetricGroup sanitized = JsonUtils.deepCopy(group, MetricGroup.class); + sanitized.setMetrics(null); + return sanitized; + }) + .collect(Collectors.toMap(MetricGroup::getId, group -> group)); + } + + private MetricGroupRepository metricGroupRepository() { + return (MetricGroupRepository) Entity.getEntityRepository(Entity.METRIC_GROUP); + } + + public MetricHierarchyContext getHierarchyContext( + UUID metricId, int childLimit, int childOffset, int siblingLimit, int siblingOffset) { + return getHierarchyContext( + metricId, + childLimit, + childOffset, + siblingLimit, + siblingOffset, + ignored -> true, + ignored -> true); + } + + public MetricHierarchyContext getHierarchyContext( + UUID metricId, + int childLimit, + int childOffset, + int siblingLimit, + int siblingOffset, + Predicate canViewMetric, + Predicate canViewGroup) { + Metric current = get(null, metricId, getFields(HIERARCHY_FIELDS)); + List ancestors = getAncestors(current, canViewMetric, canViewGroup); + MetricPage children = childPage(current, childLimit, childOffset, canViewMetric, canViewGroup); + MetricPage siblings = + siblingPage(current, siblingLimit, siblingOffset, canViewMetric, canViewGroup); + Metric sanitizedCurrent = sanitizeHierarchyMetric(current, canViewMetric, canViewGroup); + sanitizedCurrent.setChildrenCount(children.paging().getTotal()); + return new MetricHierarchyContext() + .withGroup(loadGroup(current.getMetricGroup(), canViewGroup, canViewMetric)) + .withCurrent(sanitizedCurrent) + .withAncestors(ancestors) + .withChildren(children.data()) + .withChildrenPaging(children.paging()) + .withSiblings(siblings.data()) + .withSiblingPaging(siblings.paging()); + } + + private List getAncestors( + Metric metric, + Predicate canViewMetric, + Predicate canViewGroup) { + List ancestors = new ArrayList<>(); + EntityReference parent = metric.getParent(); + Set visited = new HashSet<>(); + while (parent != null && visited.add(parent.getId())) { + Metric ancestor = get(null, parent.getId(), getFields(HIERARCHY_FIELDS)); + if (canViewMetric.test(ancestor.getEntityReference())) { + ancestors.add( + sanitizeHierarchyMetricWithVisibleCount(ancestor, canViewMetric, canViewGroup)); + } + parent = ancestor.getParent(); + } + Collections.reverse(ancestors); + return ancestors; + } + + private MetricGroup loadGroup( + EntityReference reference, + Predicate canViewGroup, + Predicate canViewMetric) { + MetricGroup result = null; + if (reference != null && canViewGroup.test(reference)) { + MetricGroupRepository repository = + (MetricGroupRepository) Entity.getEntityRepository(Entity.METRIC_GROUP); + result = + repository.get( + null, reference.getId(), repository.getFields("owners,domains,tags,metricCount")); + result = JsonUtils.deepCopy(result, MetricGroup.class); + result.setMetrics(null); + result.setMetricCount(repository.visibleMetricCount(result.getId(), canViewMetric)); + } + return result; + } + + private MetricPage childPage( + Metric current, + int limit, + int offset, + Predicate canViewMetric, + Predicate canViewGroup) { + return scanMetricPage( + (batchLimit, batchOffset) -> + daoCollection + .metricDAO() + .listChildIds( + current.getId(), Relationship.CONTAINS.ordinal(), batchLimit, batchOffset), + limit, + offset, + canViewMetric, + canViewGroup); + } + + private MetricPage siblingPage( + Metric current, + int limit, + int offset, + Predicate canViewMetric, + Predicate canViewGroup) { + MetricIdPageLoader loader = (batchLimit, batchOffset) -> List.of(); + if (current.getParent() != null) { + loader = + (batchLimit, batchOffset) -> + daoCollection + .metricDAO() + .listSiblingIds( + current.getParent().getId(), + current.getId(), + Relationship.CONTAINS.ordinal(), + batchLimit, + batchOffset); + } else if (current.getMetricGroup() != null) { + loader = (batchLimit, batchOffset) -> groupRootSiblingIds(current, batchLimit, batchOffset); + } + return scanMetricPage(loader, limit, offset, canViewMetric, canViewGroup); + } + + private List groupRootSiblingIds(Metric current, int limit, int offset) { + return daoCollection + .metricGroupDAO() + .listRootMemberIds( + current.getMetricGroup().getId(), + current.getId(), + Relationship.HAS.ordinal(), + Relationship.CONTAINS.ordinal(), + limit, + offset); + } + + private MetricPage scanMetricPage( + MetricIdPageLoader loader, + int limit, + int offset, + Predicate canViewMetric, + Predicate canViewGroup) { + List page = new ArrayList<>(); + int databaseOffset = 0; + int visible = 0; + List batch; + do { + batch = loader.load(HIERARCHY_SCAN_BATCH_SIZE, databaseOffset); + List ids = batch.stream().map(UUID::fromString).toList(); + Map references = loadReferences(ids, METRIC); + for (UUID id : ids) { + EntityReference reference = references.get(id); + if (reference != null && canViewMetric.test(reference)) { + if (visible >= offset && page.size() < limit) { + page.add(id); + } + visible++; } } - return valid; + databaseOffset += batch.size(); + } while (batch.size() == HIERARCHY_SCAN_BATCH_SIZE); + return metricPage(page, limit, offset, visible, canViewMetric, canViewGroup); + } + + private Map loadReferences(List ids, String entityType) { + if (ids.isEmpty()) { + return Map.of(); + } + return Entity.getEntityReferencesByIds(entityType, ids, NON_DELETED).stream() + .collect(Collectors.toMap(EntityReference::getId, reference -> reference)); + } + + private MetricPage metricPage( + List ids, + int limit, + int offset, + int total, + Predicate canViewMetric, + Predicate canViewGroup) { + Map metrics = loadMetricsById(ids); + List ordered = + ids.stream() + .map(metrics::get) + .filter(Objects::nonNull) + .map( + metric -> + sanitizeHierarchyMetricWithVisibleCount(metric, canViewMetric, canViewGroup)) + .toList(); + Paging paging = new Paging().withOffset(offset).withLimit(limit).withTotal(total); + return new MetricPage(ordered, paging); + } + + private record MetricPage(List data, Paging paging) {} + + record HierarchyScan(List rows, int total) {} + + @FunctionalInterface + private interface MetricIdPageLoader { + List load(int limit, int offset); + } + + static Metric sanitizeHierarchyMetric( + Metric metric, + Predicate canViewMetric, + Predicate canViewGroup) { + Metric sanitized = JsonUtils.deepCopy(metric, Metric.class); + if (sanitized.getParent() != null && !canViewMetric.test(sanitized.getParent())) { + sanitized.setParent(null); + } + if (sanitized.getMetricGroup() != null && !canViewGroup.test(sanitized.getMetricGroup())) { + sanitized.setMetricGroup(null); + } + return sanitized; + } + + private Metric sanitizeHierarchyMetricWithVisibleCount( + Metric metric, + Predicate canViewMetric, + Predicate canViewGroup) { + Metric sanitized = sanitizeHierarchyMetric(metric, canViewMetric, canViewGroup); + sanitized.setChildrenCount(visibleChildCount(metric.getId(), canViewMetric)); + return sanitized; + } + + int visibleChildCount(UUID metricId, Predicate canViewMetric) { + int databaseOffset = 0; + int visible = 0; + List batch; + do { + batch = + daoCollection + .metricDAO() + .listChildIds( + metricId, + Relationship.CONTAINS.ordinal(), + HIERARCHY_SCAN_BATCH_SIZE, + databaseOffset); + List ids = batch.stream().map(UUID::fromString).toList(); + visible += countVisibleReferences(loadReferences(ids, METRIC).values(), canViewMetric); + databaseOffset += batch.size(); + } while (batch.size() == HIERARCHY_SCAN_BATCH_SIZE); + return visible; + } + + public List hierarchySubtree(UUID rootMetricId) { + Set metricIds = new LinkedHashSet<>(); + ArrayDeque pending = new ArrayDeque<>(List.of(rootMetricId)); + while (!pending.isEmpty()) { + UUID current = pending.removeFirst(); + if (metricIds.add(current)) { + daoCollection + .metricDAO() + .listDescendantSeedIds(current, Relationship.CONTAINS.ordinal()) + .stream() + .map(UUID::fromString) + .forEach(pending::addLast); + } } + return Entity.getEntityReferencesByIds(METRIC, new ArrayList<>(metricIds), NON_DELETED); + } + + static int countVisibleReferences( + Collection references, Predicate canViewEntity) { + return (int) references.stream().filter(canViewEntity).count(); + } + + public BulkOperationResult bulkAddAssets(String metricName, BulkAssets request, String userName) { + Metric metric = getByName(null, metricName, getFields("id")); + return bulkAssetsOperation( + metric.getId(), METRIC, Relationship.APPLIED_TO, request, true, userName); + } - /** Mutable on purpose: updateToRelationships sorts the lists it receives. */ - private List ofType(List refs, String assetType) { - List matching = new ArrayList<>(); - for (EntityReference ref : refs) { - if (assetType.equals(ref.getType())) { - matching.add(ref); + public BulkOperationResult bulkRemoveAssets( + String metricName, BulkAssets request, String userName) { + Metric metric = getByName(null, metricName, getFields("id")); + return bulkAssetsOperation( + metric.getId(), METRIC, Relationship.APPLIED_TO, request, false, userName); + } + + /** + * Classifies each linked asset by where it sits relative to the metric in the lineage graph. + * Direction is derived from lineage rather than stored, so linking an asset never has to say + * which way the data flows — an asset the metric reads from is upstream, one that reads the + * metric is downstream, and one with no lineage edge either way is unrelated. + * + *

Observability is deliberately capped before relationship hydration. Callers must use the + * paginated assets endpoint when a metric exceeds this detail limit instead of creating an + * unbounded request and response. + */ + public List getAssetsWithDirection(UUID metricId) { + int linkedAssetCount = + daoCollection + .relationshipDAO() + .countFindTo(metricId, METRIC, List.of(Relationship.APPLIED_TO.ordinal())); + if (linkedAssetCount > MAX_OBSERVABILITY_ASSET_DETAILS) { + throw new IllegalArgumentException( + String.format( + "Metric observability supports at most %,d linked assets. Use the paginated " + + "/assets endpoint to inspect larger asset sets.", + MAX_OBSERVABILITY_ASSET_DETAILS)); + } + return scanAssets( + metricId, null, null, null, ignored -> true, 0, MAX_OBSERVABILITY_ASSET_DETAILS) + .data(); + } + + public ResultList listAssets( + UUID metricId, + int limit, + int offset, + String query, + String entityType, + MetricAssetDirection.Direction direction) { + return listAssets(metricId, limit, offset, query, entityType, direction, ignored -> true); + } + + public ResultList listAssets( + UUID metricId, + int limit, + int offset, + String query, + String entityType, + MetricAssetDirection.Direction direction, + Predicate isVisible) { + AssetScan scan = scanAssets(metricId, query, entityType, direction, isVisible, offset, limit); + Paging paging = new Paging().withOffset(offset).withLimit(limit).withTotal(scan.total()); + return new ResultList<>(scan.data(), paging); + } + + private AssetScan scanAssets( + UUID metricId, + String query, + String entityType, + MetricAssetDirection.Direction direction, + Predicate isVisible, + int requestedOffset, + int requestedLimit) { + List page = new ArrayList<>(); + int relationshipOffset = 0; + int matched = 0; + List records; + do { + records = linkedAssetRecords(metricId, relationshipOffset); + for (MetricAssetDirection asset : directionsFor(metricId, records)) { + if (isVisible.test(asset.getAsset()) && matchesAsset(asset, query, entityType, direction)) { + if (matched >= requestedOffset && page.size() < requestedLimit) { + page.add(asset); + } + matched++; } } - return matching; + relationshipOffset += records.size(); + } while (records.size() == ASSET_SCAN_BATCH_SIZE); + return new AssetScan(page, matched); + } + + private List linkedAssetRecords( + UUID metricId, int offset) { + return daoCollection + .relationshipDAO() + .findToWithOffset( + metricId, + METRIC, + List.of(Relationship.APPLIED_TO.ordinal()), + offset, + ASSET_SCAN_BATCH_SIZE); + } + + private List directionsFor( + UUID metricId, List records) { + List assets = + Entity.getEntityRelationshipRepository().getEntityReferences(records, NON_DELETED); + if (assets.isEmpty()) { + return List.of(); } + List ids = assets.stream().map(asset -> asset.getId().toString()).toList(); + Set upstreamIds = + toIds( + daoCollection + .metricDAO() + .findUpstreamAssetIds(metricId, ids, Relationship.UPSTREAM.ordinal())); + Set downstreamIds = + toIds( + daoCollection + .metricDAO() + .findDownstreamAssetIds(metricId, ids, Relationship.UPSTREAM.ordinal())); + return assets.stream().map(asset -> withDirection(asset, upstreamIds, downstreamIds)).toList(); + } + + private MetricAssetDirection withDirection( + EntityReference asset, Set upstreamIds, Set downstreamIds) { + MetricAssetDirection.Direction direction = + assetDirection(asset.getId(), upstreamIds, downstreamIds); + return new MetricAssetDirection() + .withAsset(asset) + .withDirection(direction) + .withAffectsHealth( + Entity.TABLE.equals(asset.getType()) + && MetricAssetDirection.Direction.UPSTREAM.equals(direction)); } + private boolean matchesAsset( + MetricAssetDirection asset, + String query, + String entityType, + MetricAssetDirection.Direction direction) { + boolean matchesType = nullOrEmpty(entityType) || entityType.equals(asset.getAsset().getType()); + boolean matchesDirection = direction == null || direction.equals(asset.getDirection()); + return matchesType && matchesDirection && matchesQuery(asset.getAsset(), query); + } + + private boolean matchesQuery(EntityReference asset, String query) { + boolean matches = true; + if (!nullOrEmpty(query)) { + String needle = query.trim().toLowerCase(Locale.ROOT); + matches = + containsIgnoreCase(asset.getName(), needle) + || containsIgnoreCase(asset.getDisplayName(), needle) + || containsIgnoreCase(asset.getFullyQualifiedName(), needle); + } + return matches; + } + + private boolean containsIgnoreCase(String value, String lowerCaseNeedle) { + return value != null && value.toLowerCase(Locale.ROOT).contains(lowerCaseNeedle); + } + + static MetricAssetDirection.Direction assetDirection( + UUID assetId, Set upstreamIds, Set downstreamIds) { + MetricAssetDirection.Direction direction = MetricAssetDirection.Direction.UNRELATED; + if (upstreamIds.contains(assetId)) { + direction = MetricAssetDirection.Direction.UPSTREAM; + } else if (downstreamIds.contains(assetId)) { + direction = MetricAssetDirection.Direction.DOWNSTREAM; + } + return direction; + } + + private Set toIds(List ids) { + Set result = new HashSet<>(); + ids.stream().map(UUID::fromString).forEach(result::add); + return result; + } + + private record AssetScan(List data, int total) {} + public List getDistinctCustomUnitsOfMeasurement() { - // Execute efficient database query to get distinct custom units return daoCollection.metricDAO().getDistinctCustomUnitsOfMeasurement(); } @@ -637,9 +1652,36 @@ private Map> batchFetchRelatedMetrics(List m return relatedMetricsMap; } + @Override + protected void postCreate(Metric metric) { + super.postCreate(metric); + refreshMetricGroup(metric.getMetricGroup()); + } + + @Override + protected void postDelete(Metric metric, boolean hardDelete) { + super.postDelete(metric, hardDelete); + refreshMetricGroup(metric.getMetricGroup()); + } + + private void refreshMetricGroup(EntityReference group) { + if (group != null) { + EntityLifecycleEventDispatcher.getInstance().onEntityUpdated(group, null); + } + } + + static boolean sameReferenceById(EntityReference left, EntityReference right) { + return left == right + || (left != null && right != null && Objects.equals(left.getId(), right.getId())); + } + @Override public void postUpdate(Metric original, Metric updated) { super.postUpdate(original, updated); + refreshMetricGroup(original.getMetricGroup()); + if (!sameReferenceById(original.getMetricGroup(), updated.getMetricGroup())) { + refreshMetricGroup(updated.getMetricGroup()); + } if (original.getEntityStatus() == EntityStatus.IN_REVIEW) { if (updated.getEntityStatus() == EntityStatus.APPROVED) { closeApprovalTask(updated, "Approved the metric"); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/RepositoryTransactionContext.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/RepositoryTransactionContext.java new file mode 100644 index 000000000000..77f730d9ff2c --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/RepositoryTransactionContext.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import java.util.Objects; + +final class RepositoryTransactionContext { + private static final ThreadLocal CURRENT_DAO = new ThreadLocal<>(); + + private RepositoryTransactionContext() {} + + static CollectionDAO currentDAO() { + return CURRENT_DAO.get(); + } + + static CollectionDAO requireCurrentDAO() { + CollectionDAO currentDAO = currentDAO(); + if (currentDAO == null) { + throw new IllegalStateException("No repository transaction is active"); + } + return currentDAO; + } + + static void runWith(CollectionDAO transactionDAO, Runnable operation) { + CollectionDAO previousDAO = CURRENT_DAO.get(); + CURRENT_DAO.set(Objects.requireNonNull(transactionDAO)); + try { + operation.run(); + } finally { + restore(previousDAO); + } + } + + private static void restore(CollectionDAO previousDAO) { + if (previousDAO == null) { + CURRENT_DAO.remove(); + } else { + CURRENT_DAO.set(previousDAO); + } + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupMapper.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupMapper.java new file mode 100644 index 000000000000..af4a113ecabd --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupMapper.java @@ -0,0 +1,38 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.resources.metrics; + +import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty; +import static org.openmetadata.service.util.EntityUtil.getEntityReference; + +import java.util.List; +import org.openmetadata.schema.api.data.CreateMetricGroup; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.service.Entity; +import org.openmetadata.service.mapper.EntityMapper; + +public class MetricGroupMapper implements EntityMapper { + @Override + public MetricGroup createToEntity(CreateMetricGroup create, String user) { + return copy(new MetricGroup(), create, user) + .withMetrics(toMetricReferences(create.getMetrics())); + } + + private List toMetricReferences(List metricFqns) { + return nullOrEmpty(metricFqns) + ? null + : metricFqns.stream().map(fqn -> getEntityReference(Entity.METRIC, fqn)).toList(); + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupResource.java new file mode 100644 index 000000000000..a02a28bd42d7 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricGroupResource.java @@ -0,0 +1,651 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.resources.metrics; + +import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.json.JsonPatch; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.PATCH; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.SecurityContext; +import jakarta.ws.rs.core.UriInfo; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.openmetadata.schema.api.data.CreateMetricGroup; +import org.openmetadata.schema.api.data.RestoreEntity; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.ApiStatus; +import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.schema.type.ResourcePermission; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; +import org.openmetadata.schema.type.api.BulkResponse; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.schema.utils.ResultList; +import org.openmetadata.service.Entity; +import org.openmetadata.service.exception.EntityNotFoundException; +import org.openmetadata.service.jdbi3.ListFilter; +import org.openmetadata.service.jdbi3.MetricGroupRepository; +import org.openmetadata.service.limits.Limits; +import org.openmetadata.service.resources.Collection; +import org.openmetadata.service.resources.EntityResource; +import org.openmetadata.service.security.AuthorizationException; +import org.openmetadata.service.security.Authorizer; +import org.openmetadata.service.security.policyevaluator.OperationContext; +import org.openmetadata.service.security.policyevaluator.ResourceContext; + +@Path("/v1/metricGroups") +@Tag( + name = "Metric Groups", + description = + "A `Metric Group` is a named collection of Metrics, such as `Profitability` or " + + "`Supply Chain`. Groups organize metrics for browsing and governance without owning " + + "them — deleting a group leaves its metrics intact and merely ungrouped.") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Collection(name = "metricGroups") +public class MetricGroupResource extends EntityResource { + public static final String COLLECTION_PATH = "/v1/metricGroups/"; + private final MetricGroupMapper mapper = new MetricGroupMapper(); + static final String FIELDS = "owners,followers,tags,extension,domains,metricCount"; + + public MetricGroupResource(Authorizer authorizer, Limits limits) { + super(Entity.METRIC_GROUP, authorizer, limits); + } + + @Override + protected List getEntitySpecificOperations() { + return Collections.emptyList(); + } + + public static class MetricGroupList extends ResultList { + /* Required for serde */ + } + + public static class MetricGroupMembersList extends ResultList { + /* Required for serde */ + } + + @GET + @Operation( + operationId = "listMetricGroups", + summary = "List metric groups", + description = "Get a list of metric groups.", + responses = { + @ApiResponse( + responseCode = "200", + description = "List of metric groups", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroupList.class))) + }) + public ResultList list( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter( + description = "Fields requested in the returned resource", + schema = @Schema(type = "string", example = FIELDS)) + @QueryParam("fields") + String fieldsParam, + @DefaultValue("10") + @Min(value = 0, message = "must be greater than or equal to 0") + @Max(value = 1000000, message = "must be less than or equal to 1000000") + @QueryParam("limit") + int limitParam, + @Parameter(description = "Returns list of metric groups before this cursor") + @QueryParam("before") + String before, + @Parameter(description = "Returns list of metric groups after this cursor") + @QueryParam("after") + String after, + @Parameter( + description = "Include all, deleted, or non-deleted entities.", + schema = @Schema(implementation = Include.class)) + @QueryParam("include") + @DefaultValue("non-deleted") + Include include) { + ListFilter filter = new ListFilter(include); + return super.listInternal( + uriInfo, securityContext, fieldsParam, filter, limitParam, before, after); + } + + @GET + @Path("/{id}") + @Operation( + operationId = "getMetricGroupByID", + summary = "Get a metric group by Id", + responses = { + @ApiResponse( + responseCode = "200", + description = "The metric group", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroup.class))), + @ApiResponse( + responseCode = "404", + description = "Metric group for instance {id} is not found") + }) + public MetricGroup get( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Id of the metric group", schema = @Schema(type = "UUID")) + @PathParam("id") + UUID id, + @Parameter( + description = "Fields requested in the returned resource", + schema = @Schema(type = "string", example = FIELDS)) + @QueryParam("fields") + String fieldsParam, + @Parameter( + description = "Include all, deleted, or non-deleted entities.", + schema = @Schema(implementation = Include.class)) + @QueryParam("include") + @DefaultValue("non-deleted") + Include include) { + return getInternal(uriInfo, securityContext, id, fieldsParam, include); + } + + @GET + @Path("/{id}/metrics") + @Operation( + operationId = "listMetricGroupMembers", + summary = "List Metrics in a Metric Group", + description = "Returns roots and inherited descendants using offset pagination.") + public ResultList listMetrics( + @Context SecurityContext securityContext, + @PathParam("id") UUID id, + @Parameter(description = "Case-insensitive Metric name search") @QueryParam("q") String query, + @Parameter(description = "Return hierarchy roots only") + @DefaultValue("false") + @QueryParam("rootOnly") + boolean rootOnly, + @DefaultValue("20") @Min(1) @Max(1000) @QueryParam("limit") int limit, + @DefaultValue("0") @Min(0) @QueryParam("offset") int offset) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.VIEW_BASIC); + authorizer.authorize(securityContext, operationContext, getResourceContextById(id)); + ResourcePermission metricPermission = + authorizer.getPermission( + securityContext, securityContext.getUserPrincipal().getName(), Entity.METRIC); + ResultList result; + if (MetricResource.hasUnconditionalView(metricPermission)) { + result = repository.listMetrics(id, limit, offset, query, rootOnly); + } else { + result = + repository.listMetrics( + id, + limit, + offset, + query, + rootOnly, + metric -> canAccessMetric(securityContext, metric, MetadataOperation.VIEW_BASIC)); + } + return result; + } + + @GET + @Path("/name/{fqn}") + @Operation( + operationId = "getMetricGroupByFQN", + summary = "Get a metric group by fully qualified name", + responses = { + @ApiResponse( + responseCode = "200", + description = "The metric group", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroup.class))), + @ApiResponse( + responseCode = "404", + description = "Metric group for instance {fqn} is not found") + }) + public MetricGroup getByName( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Fully qualified name of the metric group") @PathParam("fqn") + String fqn, + @Parameter( + description = "Fields requested in the returned resource", + schema = @Schema(type = "string", example = FIELDS)) + @QueryParam("fields") + String fieldsParam, + @Parameter( + description = "Include all, deleted, or non-deleted entities.", + schema = @Schema(implementation = Include.class)) + @QueryParam("include") + @DefaultValue("non-deleted") + Include include) { + return getByNameInternal(uriInfo, securityContext, fqn, fieldsParam, include); + } + + @GET + @Path("/{id}/versions") + @Operation( + operationId = "listAllMetricGroupVersions", + summary = "List metric group versions", + responses = { + @ApiResponse( + responseCode = "200", + description = "List of metric group versions", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = EntityHistory.class))) + }) + public EntityHistory listVersions( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Id of the metric group", schema = @Schema(type = "UUID")) + @PathParam("id") + UUID id) { + return super.listVersionsInternal(securityContext, id); + } + + @GET + @Path("/{id}/versions/{version}") + @Operation( + operationId = "getSpecificMetricGroupVersion", + summary = "Get a version of the metric group", + responses = { + @ApiResponse( + responseCode = "200", + description = "The metric group version", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroup.class))) + }) + public MetricGroup getVersion( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Id of the metric group", schema = @Schema(type = "UUID")) + @PathParam("id") + UUID id, + @Parameter(description = "Metric group version number", schema = @Schema(type = "string")) + @PathParam("version") + String version) { + return super.getVersionInternal(securityContext, id, version); + } + + @POST + @Operation( + operationId = "createMetricGroup", + summary = "Create a metric group", + responses = { + @ApiResponse( + responseCode = "200", + description = "The metric group", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroup.class))) + }) + public Response create( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Valid CreateMetricGroup create) { + MetricGroup metricGroup = + mapper.createToEntity(create, securityContext.getUserPrincipal().getName()); + repository.prepareInternal(metricGroup, false); + authorizeMembershipMutation(securityContext, null, metricGroup); + return withoutMembers(create(uriInfo, securityContext, metricGroup)); + } + + @PUT + @Operation( + operationId = "createOrUpdateMetricGroup", + summary = "Create or update a metric group", + responses = { + @ApiResponse( + responseCode = "200", + description = "The metric group", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroup.class))) + }) + public Response createOrUpdate( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Valid CreateMetricGroup create) { + MetricGroup metricGroup = + mapper.createToEntity(create, securityContext.getUserPrincipal().getName()); + repository.prepareInternal(metricGroup, true); + MetricGroup original = + repository.findByNameOrNull(metricGroup.getFullyQualifiedName(), Include.NON_DELETED); + if (original != null) { + original = repository.getWithMembers(original.getId(), Include.NON_DELETED); + } + authorizeMembershipMutation(securityContext, original, metricGroup); + return withoutMembers(createOrUpdate(uriInfo, securityContext, metricGroup)); + } + + @PATCH + @Path("/{id}") + @Operation(operationId = "patchMetricGroup", summary = "Update a metric group") + @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) + public Response patch( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Id of the metric group", schema = @Schema(type = "UUID")) + @PathParam("id") + UUID id, + @Valid JsonPatch patch) { + MetricGroup original = repository.getWithMembers(id, Include.NON_DELETED); + MetricGroup updated = JsonUtils.applyPatch(original, patch, MetricGroup.class); + repository.prepareInternal(updated, true); + authorizeMembershipMutation(securityContext, original, updated); + return withoutMembers(patchInternal(uriInfo, securityContext, id, patch)); + } + + @PUT + @Path("/{name}/metrics/add") + @Operation( + operationId = "bulkAddMetricsToGroup", + summary = "Add metrics to a group", + description = "Add the given metrics to the group identified by name.", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BulkOperationResult.class))), + @ApiResponse(responseCode = "400", description = "All operations failed") + }) + public Response bulkAddMetrics( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Name of the metric group") @PathParam("name") String name, + @Valid BulkAssets request) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.EDIT_ALL); + authorizer.authorize(securityContext, operationContext, getResourceContextByName(name)); + AuthorizedBulk authorized = authorizeBulkMetrics(securityContext, request); + BulkOperationResult result = + authorized.request().getAssets().isEmpty() + ? emptyBulkResult(request) + : repository.bulkAddMetrics( + name, authorized.request(), securityContext.getUserPrincipal().getName()); + return buildBulkOperationResponse(mergeAuthorizationFailures(result, authorized.failures())); + } + + @PUT + @Path("/{name}/metrics/remove") + @Operation( + operationId = "bulkRemoveMetricsFromGroup", + summary = "Remove metrics from a group", + description = "Remove the given metrics from the group identified by name.", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BulkOperationResult.class))), + @ApiResponse(responseCode = "400", description = "All operations failed") + }) + public Response bulkRemoveMetrics( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Name of the metric group") @PathParam("name") String name, + @Valid BulkAssets request) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.EDIT_ALL); + authorizer.authorize(securityContext, operationContext, getResourceContextByName(name)); + AuthorizedBulk authorized = authorizeBulkMetrics(securityContext, request); + BulkOperationResult result = + authorized.request().getAssets().isEmpty() + ? emptyBulkResult(request) + : repository.bulkRemoveMetrics( + name, authorized.request(), securityContext.getUserPrincipal().getName()); + return buildBulkOperationResponse(mergeAuthorizationFailures(result, authorized.failures())); + } + + @DELETE + @Path("/{id}") + @Operation( + operationId = "deleteMetricGroup", + summary = "Delete a metric group by Id", + description = + "Delete a metric group. Its metrics are left intact and become ungrouped, because a " + + "group organizes metrics rather than owning them.", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse( + responseCode = "404", + description = "Metric group for instance {id} is not found") + }) + public Response delete( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Hard delete the entity. (Default = `false`)") + @QueryParam("hardDelete") + @DefaultValue("false") + boolean hardDelete, + @Parameter(description = "Id of the metric group", schema = @Schema(type = "UUID")) + @PathParam("id") + UUID id) { + MetricGroup membershipSnapshot = membershipSnapshot(id); + Response response = delete(uriInfo, securityContext, id, false, hardDelete); + repository.refreshMembersAfterGroupLifecycle(membershipSnapshot); + return withoutMembers(response); + } + + @DELETE + @Path("/name/{fqn}") + @Operation( + operationId = "deleteMetricGroupByFQN", + summary = "Delete a metric group by fully qualified name", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse( + responseCode = "404", + description = "Metric group for instance {fqn} is not found") + }) + public Response delete( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Hard delete the entity. (Default = `false`)") + @QueryParam("hardDelete") + @DefaultValue("false") + boolean hardDelete, + @Parameter(description = "Fully qualified name of the metric group") @PathParam("fqn") + String fqn) { + MetricGroup membershipSnapshot = membershipSnapshot(fqn); + Response response = deleteByName(uriInfo, securityContext, fqn, false, hardDelete); + repository.refreshMembersAfterGroupLifecycle(membershipSnapshot); + return withoutMembers(response); + } + + @PUT + @Path("/restore") + @Operation( + operationId = "restoreMetricGroup", + summary = "Restore a soft deleted metric group", + responses = { + @ApiResponse( + responseCode = "200", + description = "Successfully restored the metric group", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricGroup.class))) + }) + public Response restore( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Valid RestoreEntity restore) { + return withoutMembers(restoreEntity(uriInfo, securityContext, restore.getId())); + } + + private MetricGroup membershipSnapshot(UUID id) { + return repository.getWithMembers(id, Include.ALL); + } + + private MetricGroup membershipSnapshot(String fqn) { + return repository.getByNameWithMembers(fqn, Include.ALL); + } + + static Response withoutMembers(Response response) { + if (response.hasEntity() && response.getEntity() instanceof MetricGroup metricGroup) { + metricGroup.setMetrics(null); + } + return response; + } + + Response buildBulkOperationResponse(BulkOperationResult result) { + if (result.getStatus() == ApiStatus.FAILURE) { + return Response.status(Response.Status.BAD_REQUEST).entity(result).build(); + } + return Response.ok().entity(result).build(); + } + + private boolean canAccessMetric( + SecurityContext securityContext, EntityReference metric, MetadataOperation operation) { + try { + authorizer.authorize( + securityContext, + new OperationContext(Entity.METRIC, operation), + new ResourceContext<>(Entity.METRIC, metric.getId(), metric.getFullyQualifiedName())); + return true; + } catch (AuthorizationException + | EntityNotFoundException + | IllegalArgumentException exception) { + return false; + } + } + + private void authorizeMembershipMutation( + SecurityContext securityContext, MetricGroup original, MetricGroup updated) { + for (EntityReference metric : membershipMutationTargets(original, updated)) { + authorizer.authorize( + securityContext, + new OperationContext(Entity.METRIC, MetadataOperation.EDIT_ALL), + new ResourceContext<>(Entity.METRIC, metric.getId(), metric.getFullyQualifiedName())); + } + } + + static List membershipMutationTargets( + MetricGroup original, MetricGroup updated) { + Map originalMembers = new LinkedHashMap<>(); + Map updatedMembers = new LinkedHashMap<>(); + for (EntityReference metric : listOrEmpty(original == null ? null : original.getMetrics())) { + originalMembers.put(metric.getId(), metric); + } + for (EntityReference metric : listOrEmpty(updated.getMetrics())) { + updatedMembers.put(metric.getId(), metric); + } + List affected = new ArrayList<>(); + originalMembers.forEach( + (id, metric) -> { + if (!updatedMembers.containsKey(id)) { + affected.add(metric); + } + }); + updatedMembers.forEach( + (id, metric) -> { + if (!originalMembers.containsKey(id)) { + affected.add(metric); + } + }); + return affected; + } + + private AuthorizedBulk authorizeBulkMetrics(SecurityContext securityContext, BulkAssets request) { + List allowed = new ArrayList<>(); + List failures = new ArrayList<>(); + for (EntityReference requested : listOrEmpty(request.getAssets())) { + boolean authorized = true; + try { + for (EntityReference metric : repository.hierarchySubtree(requested)) { + if (!canAccessMetric(securityContext, metric, MetadataOperation.EDIT_ALL)) { + authorized = false; + break; + } + } + } catch (EntityNotFoundException | IllegalArgumentException exception) { + authorized = true; + } + if (authorized) { + allowed.add(requested); + } else { + failures.add( + new BulkResponse() + .withRequest(requested) + .withMessage("Not authorized to edit the complete Metric hierarchy")); + } + } + return new AuthorizedBulk( + new BulkAssets().withAssets(allowed).withDryRun(request.getDryRun()), failures); + } + + private BulkOperationResult emptyBulkResult(BulkAssets request) { + return new BulkOperationResult() + .withDryRun(Boolean.TRUE.equals(request.getDryRun())) + .withStatus(ApiStatus.SUCCESS); + } + + private BulkOperationResult mergeAuthorizationFailures( + BulkOperationResult result, List authorizationFailures) { + List failures = new ArrayList<>(listOrEmpty(result.getFailedRequest())); + failures.addAll(authorizationFailures); + result.setFailedRequest(failures); + result.setNumberOfRowsFailed(result.getNumberOfRowsFailed() + authorizationFailures.size()); + result.setNumberOfRowsProcessed( + result.getNumberOfRowsProcessed() + authorizationFailures.size()); + if (result.getNumberOfRowsPassed() == 0 && !failures.isEmpty()) { + result.setStatus(ApiStatus.FAILURE); + } else if (!failures.isEmpty()) { + result.setStatus(ApiStatus.PARTIAL_SUCCESS); + } + return result; + } + + private record AuthorizedBulk(BulkAssets request, List failures) {} +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricMapper.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricMapper.java index 5acd73154cc8..7cf2a21588c7 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricMapper.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricMapper.java @@ -1,16 +1,34 @@ +/* + * Copyright 2021 Collate + * 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. + */ + package org.openmetadata.service.resources.metrics; +import static org.openmetadata.service.util.EntityUtil.getEntityReference; import static org.openmetadata.service.util.EntityUtil.getEntityReferences; import org.openmetadata.schema.api.data.CreateMetric; import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.service.Entity; import org.openmetadata.service.mapper.EntityMapper; +import org.openmetadata.service.util.EntityUtil; public class MetricMapper implements EntityMapper { @Override public Metric createToEntity(CreateMetric create, String user) { return copy(new Metric(), create, user) + .withExperts( + EntityUtil.validateAndPopulateEntityReferences( + getEntityReferences(Entity.USER, create.getExperts()))) .withMetricExpression(create.getMetricExpression()) .withGranularity(create.getGranularity()) .withRelatedMetrics(getEntityReferences(Entity.METRIC, create.getRelatedMetrics())) @@ -20,6 +38,8 @@ public Metric createToEntity(CreateMetric create, String user) { .withCustomUnitOfMeasurement(create.getCustomUnitOfMeasurement()) .withDimensions(create.getDimensions()) .withMeasures(create.getMeasures()) - .withFilters(create.getFilters()); + .withFilters(create.getFilters()) + .withParent(getEntityReference(Entity.METRIC, create.getParent())) + .withMetricGroup(getEntityReference(Entity.METRIC_GROUP, create.getMetricGroup())); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricResource.java index ee554fbd9bb9..ee55bc75fdda 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/metrics/MetricResource.java @@ -13,6 +13,10 @@ package org.openmetadata.service.resources.metrics; +import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; +import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty; +import static org.openmetadata.schema.type.Include.NON_DELETED; + import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -45,28 +49,48 @@ import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.UriInfo; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.UUID; import org.openmetadata.schema.api.VoteRequest; import org.openmetadata.schema.api.data.CreateMetric; +import org.openmetadata.schema.api.data.MetricAssetDirection; +import org.openmetadata.schema.api.data.MetricHierarchyContext; +import org.openmetadata.schema.api.data.MetricHierarchyItem; +import org.openmetadata.schema.api.data.MetricObservability; import org.openmetadata.schema.api.data.RestoreEntity; import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.type.ApiStatus; import org.openmetadata.schema.type.ChangeEvent; import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.Include; import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.schema.type.Permission; +import org.openmetadata.schema.type.ResourcePermission; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; +import org.openmetadata.schema.type.api.BulkResponse; import org.openmetadata.schema.type.csv.CsvImportResult; import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.schema.utils.ResultList; import org.openmetadata.service.Entity; +import org.openmetadata.service.exception.CatalogExceptionMessage; +import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.jdbi3.ListFilter; import org.openmetadata.service.jdbi3.MetricRepository; import org.openmetadata.service.jdbi3.MetricRepository.MetricCsv; import org.openmetadata.service.limits.Limits; import org.openmetadata.service.resources.Collection; import org.openmetadata.service.resources.EntityResource; +import org.openmetadata.service.security.AuthorizationException; import org.openmetadata.service.security.Authorizer; +import org.openmetadata.service.security.policyevaluator.OperationContext; +import org.openmetadata.service.security.policyevaluator.ResourceContext; import org.openmetadata.service.util.CSVExportResponse; @Path("/v1/metrics") @@ -82,7 +106,8 @@ public class MetricResource extends EntityResource { public static final String COLLECTION_PATH = "/v1/metrics/"; private final MetricMapper mapper = new MetricMapper(); static final String FIELDS = - "owners,reviewers,relatedMetrics,followers,tags,extension,domains,dataProducts"; + "owners,experts,reviewers,relatedMetrics,followers,tags,extension,domains,dataProducts,parent,children,childrenCount,metricGroup"; + private static final String ROOT_METRICS_PARENT = "null"; public MetricResource(Authorizer authorizer, Limits limits) { super(Entity.METRIC, authorizer, limits); @@ -98,6 +123,61 @@ public static class MetricsList extends ResultList { /* Required for serde */ } + public static class MetricHierarchyList extends ResultList { + /* Required for serde */ + } + + public static class MetricAssetsList extends ResultList { + /* Required for serde */ + } + + @GET + @Path("/hierarchy") + @Operation( + operationId = "listMetricHierarchy", + summary = "List top-level Metric hierarchy entries", + description = + "Returns Metric Groups and standalone root Metrics in one stable, offset-paged list.") + public ResultList listHierarchy( + @Context SecurityContext securityContext, + @Parameter(description = "Case-insensitive name search") @QueryParam("q") String query, + @DefaultValue("20") @Min(1) @Max(1000) @QueryParam("limit") int limit, + @DefaultValue("0") @Min(0) @QueryParam("offset") int offset) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.VIEW_BASIC); + authorizer.authorize(securityContext, operationContext, getResourceContext()); + ResultList result; + if (canListHierarchyWithoutFiltering(securityContext)) { + result = repository.listHierarchy(limit, offset, query); + } else { + result = + repository.listHierarchy( + limit, + offset, + query, + metric -> canAccessEntity(securityContext, metric, MetadataOperation.VIEW_BASIC), + group -> canAccessEntity(securityContext, group, MetadataOperation.VIEW_BASIC)); + } + return result; + } + + private boolean canListHierarchyWithoutFiltering(SecurityContext securityContext) { + String user = securityContext.getUserPrincipal().getName(); + return hasUnconditionalView(authorizer.getPermission(securityContext, user, Entity.METRIC)) + && hasUnconditionalView( + authorizer.getPermission(securityContext, user, Entity.METRIC_GROUP)); + } + + static boolean hasUnconditionalView(ResourcePermission resourcePermission) { + return resourcePermission != null + && listOrEmpty(resourcePermission.getPermissions()).stream() + .anyMatch( + permission -> + MetadataOperation.VIEW_BASIC.equals(permission.getOperation()) + && Permission.Access.ALLOW.equals(permission.getAccess()) + && permission.getRule() == null); + } + @GET @Operation( operationId = "listMetrics", @@ -140,12 +220,54 @@ public ResultList list( schema = @Schema(implementation = Include.class)) @QueryParam("include") @DefaultValue("non-deleted") - Include include) { + Include include, + @Parameter( + description = + "Filter by hierarchy position. Omit to list every metric, pass the literal " + + "`null` to list only metrics that have no parent, or pass a parent " + + "metric's fully qualified name to list its immediate children.", + schema = @Schema(type = "string", example = "net_sales")) + @QueryParam("parent") + String parent, + @Parameter( + description = "Filter metrics by approval status.", + schema = @Schema(type = "string", example = "Approved")) + @QueryParam("entityStatus") + String entityStatus) { ListFilter filter = new ListFilter(include); + addHierarchyFilter(filter, parent); + if (!nullOrEmpty(entityStatus)) { + filter.addQueryParam("entityStatus", entityStatus); + } return super.listInternal( uriInfo, securityContext, fieldsParam, filter, limitParam, before, after); } + Response buildBulkOperationResponse(BulkOperationResult result) { + if (result.getStatus() == ApiStatus.FAILURE) { + return Response.status(Response.Status.BAD_REQUEST).entity(result).build(); + } + return Response.ok().entity(result).build(); + } + + /** + * Metric fully qualified names are flat, so the generic {@code parent} ListFilter key — which + * builds an fqnHash prefix condition — would match nothing. The parent FQN is resolved to an id + * up front and handed to MetricDAO under a key that filters on CONTAINS edges instead. + */ + void addHierarchyFilter(ListFilter filter, String parent) { + if (nullOrEmpty(parent)) { + return; + } + if (ROOT_METRICS_PARENT.equals(parent)) { + filter.addQueryParam("rootMetrics", Boolean.TRUE.toString()); + } else { + EntityReference parentRef = + Entity.getEntityReferenceByName(Entity.METRIC, parent, NON_DELETED); + filter.addQueryParam("parentMetricId", parentRef.getId().toString()); + } + } + @GET @Path("/{id}") @Operation( @@ -190,6 +312,31 @@ public Metric get( return getInternal(uriInfo, securityContext, id, fieldsParam, include, includeRelations); } + @GET + @Path("/{id}/hierarchy") + @Operation( + operationId = "getMetricHierarchyContext", + summary = "Get the hierarchy context for one Metric") + public MetricHierarchyContext getHierarchyContext( + @Context SecurityContext securityContext, + @PathParam("id") UUID id, + @DefaultValue("20") @Min(0) @Max(1000) @QueryParam("childLimit") int childLimit, + @DefaultValue("0") @Min(0) @QueryParam("childOffset") int childOffset, + @DefaultValue("20") @Min(0) @Max(1000) @QueryParam("siblingLimit") int siblingLimit, + @DefaultValue("0") @Min(0) @QueryParam("siblingOffset") int siblingOffset) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.VIEW_BASIC); + authorizer.authorize(securityContext, operationContext, getResourceContextById(id)); + return repository.getHierarchyContext( + id, + childLimit, + childOffset, + siblingLimit, + siblingOffset, + metric -> canAccessEntity(securityContext, metric, MetadataOperation.VIEW_BASIC), + group -> canAccessEntity(securityContext, group, MetadataOperation.VIEW_BASIC)); + } + @GET @Path("/name/{fqn}") @Operation( @@ -311,6 +458,8 @@ public Response create( @Context SecurityContext securityContext, @Valid CreateMetric create) { Metric metric = mapper.createToEntity(create, securityContext.getUserPrincipal().getName()); + repository.prepareInternal(metric, false); + authorizeHierarchyDestinations(securityContext, null, metric); return create(uriInfo, securityContext, metric); } @@ -334,9 +483,21 @@ public Response createOrUpdate( @Context SecurityContext securityContext, @Valid CreateMetric create) { Metric metric = mapper.createToEntity(create, securityContext.getUserPrincipal().getName()); + preauthorizeHierarchyUpdate(securityContext, metric); return createOrUpdate(uriInfo, securityContext, metric); } + private void preauthorizeHierarchyUpdate(SecurityContext securityContext, Metric metric) { + repository.setFullyQualifiedName(metric); + Metric original = + repository.findByNameOrNull(metric.getFullyQualifiedName(), Include.NON_DELETED); + repository.prepareInternal(metric, true); + if (original != null) { + original = repository.get(null, original.getId(), repository.getFields("parent,metricGroup")); + } + authorizeHierarchyChange(securityContext, original, metric); + } + @PUT @Path("/bulk") @Operation( @@ -364,6 +525,11 @@ public Response bulkCreateOrUpdate( @Context SecurityContext securityContext, @DefaultValue("false") @QueryParam("async") boolean async, List createRequests) { + for (CreateMetric create : listOrEmpty(createRequests)) { + preauthorizeHierarchyUpdate( + securityContext, + mapper.createToEntity(create, securityContext.getUserPrincipal().getName())); + } return processBulkRequest(uriInfo, securityContext, createRequests, mapper, async); } @@ -527,6 +693,10 @@ public Response updateMetric( @ExampleObject("[{op:remove, path:/a},{op:add, path: /b, value: val}]") })) JsonPatch patch) { + validateMetricPatch(patch); + if (patchMutatesHierarchy(patch)) { + preauthorizeHierarchyPatch(securityContext, id, patch); + } return patchInternal(uriInfo, securityContext, id, patch); } @@ -556,9 +726,108 @@ public Response updateMetric( @ExampleObject("[{op:remove, path:/a},{op:add, path: /b, value: val}]") })) JsonPatch patch) { + validateMetricPatch(patch); + if (patchMutatesHierarchy(patch)) { + preauthorizeHierarchyPatch(securityContext, fqn, patch); + } return patchInternal(uriInfo, securityContext, fqn, patch); } + private void preauthorizeHierarchyPatch( + SecurityContext securityContext, UUID metricId, JsonPatch patch) { + Metric original = repository.get(null, metricId, repository.getFields("parent,metricGroup")); + authorizePatchedHierarchy(securityContext, original, patch); + } + + private void preauthorizeHierarchyPatch( + SecurityContext securityContext, String metricFqn, JsonPatch patch) { + Metric original = + repository.getByName(null, metricFqn, repository.getFields("parent,metricGroup")); + authorizePatchedHierarchy(securityContext, original, patch); + } + + private void authorizePatchedHierarchy( + SecurityContext securityContext, Metric original, JsonPatch patch) { + Metric updated = JsonUtils.applyPatch(original, patch, Metric.class); + repository.prepareInternal(updated, true); + authorizeHierarchyChange(securityContext, original, updated); + } + + private void authorizeHierarchyChange( + SecurityContext securityContext, Metric original, Metric updated) { + boolean changed = original == null || hierarchyMembershipChanged(original, updated); + if (changed) { + if (original != null) { + authorizeHierarchyMutation(securityContext, original.getId()); + } + authorizeHierarchyDestinations(securityContext, original, updated); + } + } + + void authorizeHierarchyDestinations( + SecurityContext securityContext, Metric original, Metric updated) { + for (EntityReference destination : hierarchyDestinations(original, updated)) { + authorizer.authorize( + securityContext, + new OperationContext(destination.getType(), MetadataOperation.EDIT_ALL), + new ResourceContext<>( + destination.getType(), destination.getId(), destination.getFullyQualifiedName())); + } + } + + static List hierarchyDestinations(Metric original, Metric updated) { + List destinations = new ArrayList<>(); + if (original == null || hierarchyMembershipChanged(original, updated)) { + if (updated.getParent() != null) { + destinations.add(updated.getParent()); + } + if (updated.getMetricGroup() != null) { + destinations.add(updated.getMetricGroup()); + } + } + return destinations; + } + + private void authorizeHierarchyMutation(SecurityContext securityContext, UUID metricId) { + for (EntityReference metric : repository.hierarchySubtree(metricId)) { + authorizer.authorize( + securityContext, + new OperationContext(Entity.METRIC, MetadataOperation.EDIT_ALL), + new ResourceContext<>(Entity.METRIC, metric.getId(), metric.getFullyQualifiedName())); + } + } + + static boolean hierarchyMembershipChanged(Metric original, Metric updated) { + return !sameReference(original.getParent(), updated.getParent()) + || !sameReference(original.getMetricGroup(), updated.getMetricGroup()); + } + + private static boolean sameReference(EntityReference left, EntityReference right) { + return left == right + || (left != null && right != null && Objects.equals(left.getId(), right.getId())); + } + + static boolean patchMutatesHierarchy(JsonPatch patch) { + Set fields = JsonUtils.extractPatchedFields(patch); + return fields.contains("parent") || fields.contains("metricGroup"); + } + + static void validateMetricPatch(JsonPatch patch) { + Set fields = JsonUtils.extractPatchedFields(patch); + if (fields.contains("assets")) { + throw new IllegalArgumentException( + CatalogExceptionMessage.readOnlyAttribute(Entity.METRIC, "assets")); + } + if (fields.contains("children")) { + throw new IllegalArgumentException( + CatalogExceptionMessage.readOnlyAttribute(Entity.METRIC, "children")); + } + if (fields.contains("childrenCount")) { + throw new IllegalArgumentException( + CatalogExceptionMessage.readOnlyAttribute(Entity.METRIC, "childrenCount")); + } + } + @PUT @Path("/{id}/followers") @Operation( @@ -660,13 +929,19 @@ public Response updateVote( public Response delete( @Context UriInfo uriInfo, @Context SecurityContext securityContext, + @Parameter( + description = + "Recursively delete this metric and its child metrics. (Default = `false`)") + @QueryParam("recursive") + @DefaultValue("false") + boolean recursive, @Parameter(description = "Hard delete the entity. (Default = `false`)") @QueryParam("hardDelete") @DefaultValue("false") boolean hardDelete, @Parameter(description = "Id of the Metric", schema = @Schema(type = "UUID")) @PathParam("id") UUID id) { - return delete(uriInfo, securityContext, id, false, hardDelete); + return delete(uriInfo, securityContext, id, recursive, hardDelete); } @DELETE @@ -682,13 +957,19 @@ public Response delete( public Response deleteByIdAsync( @Context UriInfo uriInfo, @Context SecurityContext securityContext, + @Parameter( + description = + "Recursively delete this metric and its child metrics. (Default = `false`)") + @QueryParam("recursive") + @DefaultValue("false") + boolean recursive, @Parameter(description = "Hard delete the entity. (Default = `false`)") @QueryParam("hardDelete") @DefaultValue("false") boolean hardDelete, @Parameter(description = "Id of the Metric", schema = @Schema(type = "UUID")) @PathParam("id") UUID id) { - return deleteByIdAsync(uriInfo, securityContext, id, false, hardDelete); + return deleteByIdAsync(uriInfo, securityContext, id, recursive, hardDelete); } @DELETE @@ -708,12 +989,18 @@ public Response delete( @QueryParam("hardDelete") @DefaultValue("false") boolean hardDelete, + @Parameter( + description = + "Recursively delete this metric and its child metrics. (Default = `false`)") + @QueryParam("recursive") + @DefaultValue("false") + boolean recursive, @Parameter( description = "Fully qualified name of the Metric", schema = @Schema(type = "string")) @PathParam("fqn") String fqn) { - return deleteByName(uriInfo, securityContext, fqn, false, hardDelete); + return deleteByName(uriInfo, securityContext, fqn, recursive, hardDelete); } @PUT @@ -738,6 +1025,234 @@ public Response restore( return restoreEntity(uriInfo, securityContext, restore.getId()); } + @PUT + @Path("/{name}/assets/add") + @Operation( + operationId = "bulkAddMetricAssets", + summary = "Link data assets to a metric", + description = "Link the given data assets to the metric identified by name.", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BulkOperationResult.class))), + @ApiResponse( + responseCode = "400", + description = "All operations failed", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BulkOperationResult.class))), + @ApiResponse(responseCode = "404", description = "Metric for instance {name} is not found") + }) + public Response bulkAddAssets( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Name of the Metric", schema = @Schema(type = "string")) + @PathParam("name") + String name, + @Valid BulkAssets request) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.EDIT_ALL); + authorizer.authorize(securityContext, operationContext, getResourceContextByName(name)); + AuthorizedBulk authorized = authorizeAssets(securityContext, request); + BulkOperationResult result = + authorized.request().getAssets().isEmpty() + ? emptyBulkResult(request) + : repository.bulkAddAssets( + name, authorized.request(), securityContext.getUserPrincipal().getName()); + return buildBulkOperationResponse(mergeAuthorizationFailures(result, authorized.failures())); + } + + @PUT + @Path("/{name}/assets/remove") + @Operation( + operationId = "bulkRemoveMetricAssets", + summary = "Unlink data assets from a metric", + description = "Unlink the given data assets from the metric identified by name.", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BulkOperationResult.class))), + @ApiResponse( + responseCode = "400", + description = "All operations failed", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BulkOperationResult.class))), + @ApiResponse(responseCode = "404", description = "Metric for instance {name} is not found") + }) + public Response bulkRemoveAssets( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Name of the Metric", schema = @Schema(type = "string")) + @PathParam("name") + String name, + @Valid BulkAssets request) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.EDIT_ALL); + authorizer.authorize(securityContext, operationContext, getResourceContextByName(name)); + AuthorizedBulk authorized = authorizeAssets(securityContext, request); + BulkOperationResult result = + authorized.request().getAssets().isEmpty() + ? emptyBulkResult(request) + : repository.bulkRemoveAssets( + name, authorized.request(), securityContext.getUserPrincipal().getName()); + return buildBulkOperationResponse(mergeAuthorizationFailures(result, authorized.failures())); + } + + @GET + @Path("/{id}/assets") + @Operation( + operationId = "getMetricAssets", + summary = "List a metric's linked assets with their lineage direction", + description = + "List the data assets linked to a metric. Each asset is annotated with whether it is " + + "upstream of the metric, downstream of it, or has no lineage edge to it.", + responses = { + @ApiResponse( + responseCode = "200", + description = "Linked assets with direction", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricAssetsList.class))), + @ApiResponse(responseCode = "404", description = "Metric for instance {id} is not found") + }) + public ResultList getAssets( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Id of the metric", schema = @Schema(type = "UUID")) @PathParam("id") + UUID id, + @DefaultValue("20") @Min(1) @Max(1000) @QueryParam("limit") int limit, + @DefaultValue("0") @Min(0) @QueryParam("offset") int offset, + @Parameter(description = "Case-insensitive asset name search") @QueryParam("q") String query, + @Parameter(description = "Filter by linked entity type") @QueryParam("entityType") + String assetEntityType, + @Parameter(description = "Filter by lineage direction") @QueryParam("direction") + MetricAssetDirection.Direction direction) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.VIEW_BASIC); + authorizer.authorize(securityContext, operationContext, getResourceContextById(id)); + repository.get(null, id, repository.getFields("id")); + return repository.listAssets( + id, + limit, + offset, + query, + assetEntityType, + direction, + asset -> canViewAsset(securityContext, asset)); + } + + @GET + @Path("/{id}/observability") + @Operation( + operationId = "getMetricObservability", + summary = "Get a metric's health rollup", + description = + "Compute the metric's health from the data quality of the upstream assets it is computed " + + "on, together with a plain-English explanation of how that health was reached. " + + "Downstream assets consume the metric rather than feed it, so they are excluded.", + responses = { + @ApiResponse( + responseCode = "200", + description = "The metric's health rollup", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MetricObservability.class))), + @ApiResponse(responseCode = "404", description = "Metric for instance {id} is not found") + }) + public MetricObservability getObservability( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "Id of the metric", schema = @Schema(type = "UUID")) @PathParam("id") + UUID id) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.VIEW_BASIC); + authorizer.authorize(securityContext, operationContext, getResourceContextById(id)); + repository.get(null, id, repository.getFields("id")); + List linkedAssets = repository.getAssetsWithDirection(id); + Set visibleAssets = new HashSet<>(); + for (MetricAssetDirection linked : linkedAssets) { + if (canViewAsset(securityContext, linked.getAsset())) { + visibleAssets.add(linked.getAsset().getId()); + } + } + return repository.getObservability(id, linkedAssets, visibleAssets); + } + + private boolean canViewAsset(SecurityContext securityContext, EntityReference asset) { + return canAccessEntity(securityContext, asset, MetadataOperation.VIEW_BASIC); + } + + private boolean canAccessEntity( + SecurityContext securityContext, EntityReference entity, MetadataOperation operation) { + boolean result = true; + try { + OperationContext operationContext = new OperationContext(entity.getType(), operation); + authorizer.authorize( + securityContext, + operationContext, + new ResourceContext<>(entity.getType(), entity.getId(), entity.getFullyQualifiedName())); + } catch (AuthorizationException + | EntityNotFoundException + | IllegalArgumentException exception) { + result = false; + } + return result; + } + + private AuthorizedBulk authorizeAssets(SecurityContext securityContext, BulkAssets request) { + List allowed = new ArrayList<>(); + List failures = new ArrayList<>(); + for (EntityReference asset : listOrEmpty(request.getAssets())) { + if (canViewAsset(securityContext, asset)) { + allowed.add(asset); + } else { + failures.add( + new BulkResponse() + .withRequest(asset) + .withMessage("Not authorized to view the requested asset")); + } + } + BulkAssets authorized = new BulkAssets().withAssets(allowed).withDryRun(request.getDryRun()); + return new AuthorizedBulk(authorized, failures); + } + + BulkOperationResult emptyBulkResult(BulkAssets request) { + return new BulkOperationResult() + .withDryRun(Boolean.TRUE.equals(request.getDryRun())) + .withStatus(ApiStatus.SUCCESS); + } + + BulkOperationResult mergeAuthorizationFailures( + BulkOperationResult result, List authorizationFailures) { + List failures = new ArrayList<>(listOrEmpty(result.getFailedRequest())); + failures.addAll(authorizationFailures); + result.setFailedRequest(failures); + result.setNumberOfRowsFailed(result.getNumberOfRowsFailed() + authorizationFailures.size()); + result.setNumberOfRowsProcessed( + result.getNumberOfRowsProcessed() + authorizationFailures.size()); + if (result.getNumberOfRowsPassed() == 0 && !failures.isEmpty()) { + result.setStatus(ApiStatus.FAILURE); + } else if (!failures.isEmpty()) { + result.setStatus(ApiStatus.PARTIAL_SUCCESS); + } + return result; + } + + private record AuthorizedBulk(BulkAssets request, List failures) {} + @GET @Path("/customUnits") @Operation( @@ -755,6 +1270,9 @@ public Response restore( array = @ArraySchema(schema = @Schema(type = "string")))) }) public Response getCustomUnitsOfMeasurement(@Context SecurityContext securityContext) { + OperationContext operationContext = + new OperationContext(entityType, MetadataOperation.VIEW_BASIC); + authorizer.authorize(securityContext, operationContext, getResourceContext()); List customUnits = repository.getDistinctCustomUnitsOfMeasurement(); return Response.ok(customUnits).build(); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchClient.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchClient.java index cb1a242aad36..6391b0fccba7 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchClient.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchClient.java @@ -729,7 +729,7 @@ public interface SearchClient "tier", "changeDescription"); - Set FIELDS_TO_REMOVE_WHEN_NULL = Set.of("tier", "certification"); + Set FIELDS_TO_REMOVE_WHEN_NULL = Set.of("tier", "certification", "metricGroup"); boolean isClientAvailable(); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchIndexFactory.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchIndexFactory.java index 1dff47dada83..67f8998e4ce4 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchIndexFactory.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchIndexFactory.java @@ -29,6 +29,7 @@ import org.openmetadata.schema.entity.data.Glossary; import org.openmetadata.schema.entity.data.GlossaryTerm; import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; import org.openmetadata.schema.entity.data.MlModel; import org.openmetadata.schema.entity.data.Page; import org.openmetadata.schema.entity.data.Pipeline; @@ -100,6 +101,7 @@ import org.openmetadata.service.search.indexes.McpServiceIndex; import org.openmetadata.service.search.indexes.MessagingServiceIndex; import org.openmetadata.service.search.indexes.MetadataServiceIndex; +import org.openmetadata.service.search.indexes.MetricGroupIndex; import org.openmetadata.service.search.indexes.MetricIndex; import org.openmetadata.service.search.indexes.MlModelIndex; import org.openmetadata.service.search.indexes.MlModelServiceIndex; @@ -167,6 +169,7 @@ public SearchIndex buildIndex(String entityType, Object entity) { case Entity.USER -> new UserIndex((User) entity); case Entity.TEAM -> new TeamIndex((Team) entity); case Entity.METRIC -> new MetricIndex((Metric) entity); + case Entity.METRIC_GROUP -> new MetricGroupIndex((MetricGroup) entity); case Entity.GLOSSARY -> new GlossaryIndex((Glossary) entity); case Entity.GLOSSARY_TERM -> new GlossaryTermIndex((GlossaryTerm) entity); case Entity.RELATIONSHIP_TYPE -> new RelationshipTypeIndex((RelationshipType) entity); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchUtils.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchUtils.java index 47166a6acff5..35a4295a32af 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchUtils.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/SearchUtils.java @@ -766,6 +766,7 @@ public static String mapEntityTypesToIndexNames(String indexName) { case "api_endpoint_search_index", Entity.API_ENDPOINT -> Entity.API_ENDPOINT; case "api_collection_search_index", Entity.API_COLLECTION -> Entity.API_COLLECTION; case "metric_search_index", Entity.METRIC -> Entity.METRIC; + case "metric_group_search_index", Entity.METRIC_GROUP -> Entity.METRIC_GROUP; case "search_entity_search_index", Entity.SEARCH_INDEX -> Entity.SEARCH_INDEX; case "tag_search_index", Entity.TAG -> Entity.TAG; case "glossary_term_search_index", Entity.GLOSSARY_TERM -> Entity.GLOSSARY_TERM; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricGroupIndex.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricGroupIndex.java new file mode 100644 index 000000000000..87e75a7d40e6 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricGroupIndex.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.search.indexes; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.service.Entity; + +public class MetricGroupIndex implements TaggableIndex { + private static final String FIELD_METRIC_COUNT = "metricCount"; + private static final Set EXCLUDED_FIELDS = Set.of("metrics"); + + final MetricGroup metricGroup; + + public MetricGroupIndex(MetricGroup metricGroup) { + this.metricGroup = metricGroup; + } + + @Override + public Object getEntity() { + return metricGroup; + } + + @Override + public String getEntityTypeName() { + return Entity.METRIC_GROUP; + } + + /** + * {@code metricCount} is computed on read rather than stored, so it has to be requested + * explicitly or it never reaches the document. The member list itself is excluded: the list page + * loads a group's metrics on demand, so indexing an unbounded membership array would cost + * document size for nothing. + */ + @Override + public Set getRequiredReindexFields() { + Set fields = new HashSet<>(TaggableIndex.super.getRequiredReindexFields()); + fields.add(FIELD_METRIC_COUNT); + return Collections.unmodifiableSet(fields); + } + + @Override + public Set getExcludedFields() { + return EXCLUDED_FIELDS; + } + + public Map buildSearchIndexDocInternal(Map doc) { + // Null indexes as `missing` for an integer field, which breaks numeric range and sort queries + // that assume the field is always present. + doc.put( + FIELD_METRIC_COUNT, + metricGroup.getMetricCount() != null ? metricGroup.getMetricCount() : 0); + return doc; + } + + public static Map getFields() { + return SearchIndex.getDefaultFields(); + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricIndex.java b/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricIndex.java index 1e23c5ad95dc..cd5bd9323fdc 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricIndex.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/search/indexes/MetricIndex.java @@ -1,5 +1,6 @@ package org.openmetadata.service.search.indexes; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -11,6 +12,9 @@ import org.openmetadata.service.Entity; public class MetricIndex implements TaggableIndex, LineageIndex { + private static final String FIELD_CHILDREN_COUNT = "childrenCount"; + private static final Set EXCLUDED_FIELDS = Set.of(Entity.FIELD_CHILDREN); + final Metric metric; public MetricIndex(Metric metric) { @@ -27,6 +31,27 @@ public String getEntityTypeName() { return Entity.METRIC; } + /** + * The hierarchy fields are computed on read rather than stored, so both the reindex pipeline and + * the live single-entity update path have to request them explicitly or they never reach the + * document. {@code children} is deliberately absent: the list view loads a metric's children on + * demand through {@code GET /v1/metrics?parent={fqn}}, so indexing an unbounded child list would + * cost document size for nothing. + */ + @Override + public Set getRequiredReindexFields() { + Set fields = new HashSet<>(TaggableIndex.super.getRequiredReindexFields()); + fields.add(Entity.FIELD_PARENT); + fields.add(FIELD_CHILDREN_COUNT); + fields.add("metricGroup"); + return Collections.unmodifiableSet(fields); + } + + @Override + public Set getExcludedFields() { + return EXCLUDED_FIELDS; + } + @SuppressWarnings("unchecked") public Map buildSearchIndexDocInternal(Map doc) { Set fqnParts = @@ -36,25 +61,36 @@ public Map buildSearchIndexDocInternal(Map doc) addDimensionFQNParts(fqnParts, metric.getDimensions()); addMeasureFQNParts(fqnParts, metric.getMeasures()); doc.put("fqnParts", fqnParts); + // Null indexes as `missing` for an integer field, which breaks the numeric range and sort + // queries that assume the field is always present. + doc.put( + FIELD_CHILDREN_COUNT, metric.getChildrenCount() != null ? metric.getChildrenCount() : 0); + doc.put("metricGroup", metric.getMetricGroup()); return doc; } private void addDimensionFQNParts(Set fqnParts, List dimensions) { - if (CommonUtil.nullOrEmpty(dimensions)) return; + if (CommonUtil.nullOrEmpty(dimensions)) { + return; + } for (MetricDimension dimension : dimensions) { addChildFQNParts(fqnParts, dimension.getFullyQualifiedName()); } } private void addMeasureFQNParts(Set fqnParts, List measures) { - if (CommonUtil.nullOrEmpty(measures)) return; + if (CommonUtil.nullOrEmpty(measures)) { + return; + } for (MetricMeasure measure : measures) { addChildFQNParts(fqnParts, measure.getFullyQualifiedName()); } } private void addChildFQNParts(Set fqnParts, String fqn) { - if (fqn == null) return; + if (fqn == null) { + return; + } fqnParts.addAll(getFQNParts(fqn)); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskWorkflowHandler.java b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskWorkflowHandler.java index e060fc4afb86..8807fb15d90e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskWorkflowHandler.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskWorkflowHandler.java @@ -29,6 +29,7 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.openmetadata.schema.EntityInterface; @@ -80,12 +81,26 @@ @Slf4j public class TaskWorkflowHandler { + static final int DEFAULT_RUNTIME_TASK_READINESS_ATTEMPTS = 6; + static final long DEFAULT_RUNTIME_TASK_READINESS_DELAY_MILLIS = 50L; + static final long DEFAULT_RUNTIME_TASK_READINESS_WAIT_MILLIS = + (DEFAULT_RUNTIME_TASK_READINESS_ATTEMPTS - 1) * DEFAULT_RUNTIME_TASK_READINESS_DELAY_MILLIS; + /** Suggestion payload {@code source} marking a suggestion an agent produced. */ private static final String AGENT_SUGGESTION_SOURCE = "Agent"; private static TaskWorkflowHandler instance; + private final int runtimeTaskReadinessAttempts; + private final long runtimeTaskReadinessDelayMillis; + + private TaskWorkflowHandler() { + this(DEFAULT_RUNTIME_TASK_READINESS_ATTEMPTS, DEFAULT_RUNTIME_TASK_READINESS_DELAY_MILLIS); + } - private TaskWorkflowHandler() {} + TaskWorkflowHandler(int runtimeTaskReadinessAttempts, long runtimeTaskReadinessDelayMillis) { + this.runtimeTaskReadinessAttempts = Math.max(1, runtimeTaskReadinessAttempts); + this.runtimeTaskReadinessDelayMillis = Math.max(0L, runtimeTaskReadinessDelayMillis); + } public static synchronized TaskWorkflowHandler getInstance() { if (instance == null) { @@ -127,6 +142,8 @@ public Task resolveTask( TaskWorkflowLifecycleResolver.findTransition(task, transitionId); TaskResolutionType effectiveResolutionType = resolveResolutionType(task, requestedResolutionType, selectedTransition); + validateResolutionComment(selectedTransition, comment); + validateMetricRejectionComment(task, effectiveResolutionType, comment); LOG.info( "[TaskWorkflowHandler] Resolving task: id='{}', transitionId='{}', resolutionType='{}', user='{}'", taskId, @@ -160,6 +177,32 @@ public Task resolveTask( } } + static void validateMetricRejectionComment( + Task task, TaskResolutionType resolutionType, String comment) { + if (isMetricApprovalRejection(task, resolutionType) && (comment == null || comment.isBlank())) { + throw new IllegalArgumentException("A rejection comment is required"); + } + } + + static void validateResolutionComment(TaskAvailableTransition transition, String comment) { + if (transition != null + && Boolean.TRUE.equals(transition.getRequiresComment()) + && (comment == null || comment.isBlank())) { + throw new IllegalArgumentException("A rejection comment is required"); + } + } + + private static boolean isMetricApprovalRejection(Task task, TaskResolutionType resolutionType) { + return isMetricApprovalTask(task) && resolutionType == TaskResolutionType.Rejected; + } + + private static boolean isMetricApprovalTask(Task task) { + return task != null + && task.getType() == TaskEntityType.RequestApproval + && task.getAbout() != null + && Entity.METRIC.equals(task.getAbout().getType()); + } + /** * Resolve a task that is managed by a Flowable workflow. */ @@ -176,6 +219,18 @@ private Task resolveWorkflowTask( WorkflowHandler workflowHandler = WorkflowHandler.getInstance(); TaskRepository taskRepository = (TaskRepository) Entity.getEntityRepository(Entity.TASK); List payloadAssignees = extractAssigneesFromPayload(resolvedPayload); + boolean requiresRuntimeTaskReadiness = isMetricApprovalTask(task); + + if (requiresRuntimeTaskReadiness && TaskRepository.isTerminalStatus(task.getStatus())) { + throw new IllegalStateException( + String.format("Task '%s' is already in status '%s'", taskId, task.getStatus())); + } + if (requiresRuntimeTaskReadiness && !awaitActiveRuntimeTask(workflowHandler, taskId)) { + throw new IllegalStateException( + String.format( + "Flowable runtime task for workflow-managed task '%s' is unavailable; retry the resolution", + taskId)); + } if (payloadAssignees != null && !payloadAssignees.isEmpty()) { task = persistWorkflowAssignees(taskRepository, task, payloadAssignees, user); @@ -219,12 +274,15 @@ private Task resolveWorkflowTask( if (!workflowSuccess) { if (!workflowHandler.hasActiveRuntimeTask(taskId)) { - // Report M1: two clients racing the same task, or a stale resolve arriving after - // Flowable already advanced past this node. Return a 409 CONFLICT via a typed - // WebServiceException so the caller learns the state changed under them — the - // generic exception mapper would otherwise surface these as 500s. Kept narrow - // (only these two resolve-race sites) so unrelated IllegalStateException bugs - // still surface as 500. + // Workflow-managed Metric tasks must not bypass their approval workflow when the runtime + // task disappears between the readiness check and resolution. + if (requiresRuntimeTaskReadiness) { + throw TaskStateConflictException.of( + String.format( + "Flowable runtime task for workflow-managed Metric task '%s' disappeared while resolving transition '%s'; the task was not finalized", + taskId, + transitionId != null ? transitionId : defaultWorkflowResult(resolutionType))); + } if (resolutionType == null) { throw TaskStateConflictException.of( String.format( @@ -273,6 +331,29 @@ private Task resolveWorkflowTask( task, resolutionType, selectedTransition, newValue, resolvedPayload, comment, user); } + private boolean awaitActiveRuntimeTask(WorkflowHandler workflowHandler, UUID taskId) { + boolean isActive = workflowHandler.hasActiveRuntimeTask(taskId); + int attempt = 1; + while (!isActive && attempt < runtimeTaskReadinessAttempts && waitForRuntimeTaskRetry(taskId)) { + isActive = workflowHandler.hasActiveRuntimeTask(taskId); + attempt++; + } + return isActive; + } + + private boolean waitForRuntimeTaskRetry(UUID taskId) { + boolean completed = true; + try { + TimeUnit.MILLISECONDS.sleep(runtimeTaskReadinessDelayMillis); + } catch (InterruptedException exception) { + Thread.currentThread().interrupt(); + completed = false; + LOG.warn( + "[TaskWorkflowHandler] Interrupted while waiting for Flowable runtime task '{}'", taskId); + } + return completed; + } + private Task persistWorkflowAssignees( TaskRepository taskRepository, Task task, List assignees, String user) { try { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityFieldUtils.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityFieldUtils.java index 22f1622d5d48..695fded3d310 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityFieldUtils.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/EntityFieldUtils.java @@ -109,7 +109,9 @@ public static void setEntityField( JsonPatch patch = JsonUtils.getJsonPatch(originalJson, updatedJson); if (!originalJson.equals(updatedJson)) { EntityRepository entityRepository = Entity.getEntityRepository(entityType); - entityRepository.patch(null, entity.getId(), user, patch, null, impersonatedBy); + // Workflow patches must bypass session consolidation because replaying an asynchronously + // loaded entity can restore stale relationship values over a concurrent user patch. + entityRepository.patch(null, entity.getId(), user, patch, null, "*", impersonatedBy); ChangeEvent changeEvent = new ChangeEvent() .withId(UUID.randomUUID()) diff --git a/openmetadata-service/src/main/resources/json/data/governance/workflows/MetricApprovalWorkflow.json b/openmetadata-service/src/main/resources/json/data/governance/workflows/MetricApprovalWorkflow.json new file mode 100644 index 000000000000..1a767b7ea51f --- /dev/null +++ b/openmetadata-service/src/main/resources/json/data/governance/workflows/MetricApprovalWorkflow.json @@ -0,0 +1,425 @@ +{ + "name": "MetricApprovalWorkflow", + "fullyQualifiedName": "MetricApprovalWorkflow", + "displayName": "Metric Approval Workflow", + "description": "When a Metric is Created or Updated, this Workflow will be triggered for the Metric to be Approved.", + "config": { + "storeStageStatus": true + }, + "trigger": { + "type": "eventBasedEntity", + "config": { + "entityTypes": ["metric"], + "events": ["Created", "Updated"], + "exclude": ["entityStatus"], + "include": [], + "filter": {} + }, + "output": ["relatedEntity", "updatedBy"] + }, + "nodes": [ + { + "type": "startEvent", + "subType": "startEvent", + "name": "MetricCreated", + "displayName": "Metric Created or Updated" + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "AutoApprovedByReviewerEnd", + "displayName": "Auto-Approved by Reviewer" + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "ApprovedEnd", + "displayName": "Metric Status: Approved" + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "ApprovedEndAfterApproval", + "displayName": "Metric Status: Approved" + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "RejectedEnd", + "displayName": "Metric Status: Rejected" + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "DraftEnd", + "displayName": "Metric Status: Draft" + }, + { + "type": "automatedTask", + "subType": "checkEntityAttributesTask", + "name": "CheckIfMetricUpdatedByIsReviewer", + "displayName": "Check if Metric Updated By is Reviewer", + "config": { + "rules": "{\"and\":[{\"isReviewer\":{\"var\":\"updatedBy\"}}]}" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToApprovedByReviewer", + "displayName": "Set Status to 'Approved' (By Reviewer)", + "config": { + "fieldName": "status", + "fieldValue": "Approved" + }, + "inputNamespaceMap": { + "relatedEntity": "global", + "updatedBy": "global" + } + }, + { + "type": "automatedTask", + "subType": "checkEntityAttributesTask", + "name": "CheckMetricHasReviewers", + "displayName": "Check if Metric has Reviewers", + "config": { + "rules": "{\"and\":[{\"some\":[{\"var\":\"reviewers\"},{\"!=\":[{\"var\":\"fullyQualifiedName\"},null]}]}]}" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "checkEntityAttributesTask", + "name": "CheckMetricIsReadyToBeReviewed", + "displayName": "Check if Metric is Ready to be Reviewed", + "config": { + "rules": "{\"and\":[{\"!!\":[{\"var\":\"description\"}]}]}" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToInReview", + "displayName": "Set Status to 'In Review'", + "config": { + "fieldName": "status", + "fieldValue": "In Review" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToDraft", + "displayName": "Set Status to 'Draft'", + "config": { + "fieldName": "status", + "fieldValue": "Draft" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "userTask", + "subType": "userApprovalTask", + "name": "ApproveMetric", + "displayName": "Create User Approval Task", + "config": { + "assignees": { + "addReviewers": true, + "addOwners": false, + "candidates": [] + }, + "approvalThreshold": 1, + "rejectionThreshold": 1, + "stageId": "review", + "stageDisplayName": "Review", + "taskStatus": "Open", + "assigneeStrategy": "reviewers-and-assignees", + "transitionMetadata": [ + { + "id": "approve", + "label": "Approve", + "targetStageId": "approved", + "targetTaskStatus": "Approved", + "resolutionType": "Approved", + "formRef": "approve", + "requiresComment": false + }, + { + "id": "reject", + "label": "Reject", + "targetStageId": "rejected", + "targetTaskStatus": "Rejected", + "resolutionType": "Rejected", + "formRef": "reject", + "requiresComment": true + } + ] + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "checkEntityAttributesTask", + "name": "CheckIfMetricIsNew", + "displayName": "Check if Metric is New", + "config": { + "rules": "{\"and\":[{\"==\":[{\"var\":\"version\"},0.1]}]}" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToInReviewForUpdate", + "displayName": "Set Status to 'In Review' (Update)", + "config": { + "fieldName": "status", + "fieldValue": "In Review" + }, + "inputNamespaceMap": { + "relatedEntity": "global", + "updatedBy": "global" + } + }, + { + "type": "userTask", + "subType": "userApprovalTask", + "name": "ApprovalForUpdates", + "displayName": "Review Changes for Updates", + "config": { + "assignees": { + "addReviewers": true, + "addOwners": false, + "candidates": [] + }, + "approvalThreshold": 1, + "rejectionThreshold": 1, + "stageId": "review", + "stageDisplayName": "Review", + "taskStatus": "Open", + "assigneeStrategy": "reviewers-and-assignees", + "transitionMetadata": [ + { + "id": "approve", + "label": "Approve", + "targetStageId": "approved", + "targetTaskStatus": "Approved", + "resolutionType": "Approved", + "formRef": "approve", + "requiresComment": false + }, + { + "id": "reject", + "label": "Reject", + "targetStageId": "rejected", + "targetTaskStatus": "Rejected", + "resolutionType": "Rejected", + "formRef": "reject", + "requiresComment": true + } + ] + }, + "inputNamespaceMap": { + "relatedEntity": "global" + }, + "output": ["updatedBy"] + }, + { + "type": "automatedTask", + "subType": "rollbackEntityTask", + "name": "RollbackMetricChanges", + "displayName": "Rollback or Reject Metric Changes", + "config": {}, + "inputNamespaceMap": { + "relatedEntity": "global", + "updatedBy": "ApprovalForUpdates" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToApprovedAfterReview", + "displayName": "Set Status to 'Approved' (After Review)", + "config": { + "fieldName": "status", + "fieldValue": "Approved" + }, + "inputNamespaceMap": { + "relatedEntity": "global", + "updatedBy": "ApprovalForUpdates" + } + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "RollbackEnd", + "displayName": "Changes Rejected or Rolled Back" + }, + { + "type": "endEvent", + "subType": "endEvent", + "name": "ApprovalEnd", + "displayName": "Approved After Unified Review" + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToApprovedAfterApproval", + "displayName": "Set Status to 'Approved'", + "config": { + "fieldName": "status", + "fieldValue": "Approved" + }, + "inputNamespaceMap": { + "relatedEntity": "global", + "updatedBy": "ApproveMetric" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToApproved", + "displayName": "Set Status to 'Approved'", + "config": { + "fieldName": "status", + "fieldValue": "Approved" + }, + "inputNamespaceMap": { + "relatedEntity": "global" + } + }, + { + "type": "automatedTask", + "subType": "setEntityAttributeTask", + "name": "SetMetricStatusToRejected", + "displayName": "Set Status to 'Rejected'", + "config": { + "fieldName": "status", + "fieldValue": "Rejected" + }, + "inputNamespaceMap": { + "relatedEntity": "global", + "updatedBy": "ApproveMetric" + } + } + ], + "edges": [ + { + "from": "MetricCreated", + "to": "CheckMetricHasReviewers" + }, + { + "from": "CheckMetricHasReviewers", + "to": "SetMetricStatusToApproved", + "condition": "false" + }, + { + "from": "CheckMetricHasReviewers", + "to": "CheckIfMetricUpdatedByIsReviewer", + "condition": "true" + }, + { + "from": "CheckIfMetricUpdatedByIsReviewer", + "to": "SetMetricStatusToApprovedByReviewer", + "condition": "true" + }, + { + "from": "CheckIfMetricUpdatedByIsReviewer", + "to": "CheckMetricIsReadyToBeReviewed", + "condition": "false" + }, + { + "from": "SetMetricStatusToApprovedByReviewer", + "to": "AutoApprovedByReviewerEnd" + }, + { + "from": "CheckMetricIsReadyToBeReviewed", + "to": "SetMetricStatusToDraft", + "condition": "false" + }, + { + "from": "SetMetricStatusToDraft", + "to": "DraftEnd" + }, + { + "from": "CheckMetricIsReadyToBeReviewed", + "to": "CheckIfMetricIsNew", + "condition": "true" + }, + { + "from": "CheckIfMetricIsNew", + "to": "SetMetricStatusToInReview", + "condition": "true" + }, + { + "from": "CheckIfMetricIsNew", + "to": "SetMetricStatusToInReviewForUpdate", + "condition": "false" + }, + { + "from": "SetMetricStatusToInReview", + "to": "ApproveMetric" + }, + { + "from": "SetMetricStatusToInReviewForUpdate", + "to": "ApprovalForUpdates" + }, + { + "from": "ApprovalForUpdates", + "to": "SetMetricStatusToApprovedAfterReview", + "condition": "approve" + }, + { + "from": "ApprovalForUpdates", + "to": "RollbackMetricChanges", + "condition": "reject" + }, + { + "from": "RollbackMetricChanges", + "to": "RollbackEnd" + }, + { + "from": "SetMetricStatusToApprovedAfterReview", + "to": "ApprovalEnd" + }, + { + "from": "ApproveMetric", + "to": "SetMetricStatusToApprovedAfterApproval", + "condition": "approve" + }, + { + "from": "ApproveMetric", + "to": "SetMetricStatusToRejected", + "condition": "reject" + }, + { + "from": "SetMetricStatusToApprovedAfterApproval", + "to": "ApprovedEndAfterApproval" + }, + { + "from": "SetMetricStatusToApproved", + "to": "ApprovedEnd" + }, + { + "from": "SetMetricStatusToRejected", + "to": "RejectedEnd" + } + ] +} diff --git a/openmetadata-service/src/main/resources/json/data/metric/metricCsvDocumentation.json b/openmetadata-service/src/main/resources/json/data/metric/metricCsvDocumentation.json index 61901b2210e8..4a466d80deac 100644 --- a/openmetadata-service/src/main/resources/json/data/metric/metricCsvDocumentation.json +++ b/openmetadata-service/src/main/resources/json/data/metric/metricCsvDocumentation.json @@ -114,6 +114,24 @@ "required": false, "description": "Custom property values in key:value format separated by ';'.", "examples": ["externalId:12345"] + }, + { + "name": "parent", + "required": false, + "description": "Fully qualified name of the parent metric this metric is a variant of. The parent must already exist before the child row is imported — rows are processed in file order, so a single file cannot create a parent and its child together.", + "examples": ["net_sales"] + }, + { + "name": "experts", + "required": false, + "description": "User FQNs for subject-matter experts separated by ';'.", + "examples": ["finance.analyst;revenue.owner"] + }, + { + "name": "metricGroup", + "required": false, + "description": "Metric Group FQN. Child metrics inherit their parent's group.", + "examples": ["Profitability"] } ] } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/aicontext/PersonaContextBuilderTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/aicontext/PersonaContextBuilderTest.java index 054daa352894..5bb88d754e26 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/aicontext/PersonaContextBuilderTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/aicontext/PersonaContextBuilderTest.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import jakarta.ws.rs.ServiceUnavailableException; @@ -35,9 +36,12 @@ import java.util.UUID; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; +import org.openmetadata.schema.api.data.MetricAssetDirection; +import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.schema.entity.teams.Persona; import org.openmetadata.schema.type.AIContext; import org.openmetadata.schema.type.ColumnLineage; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.PersonaContextDefinition; import org.openmetadata.schema.type.aicontext.AssetContext; import org.openmetadata.schema.type.aicontext.DataQuality; @@ -45,13 +49,44 @@ import org.openmetadata.schema.type.aicontext.Observability; import org.openmetadata.schema.type.personaContext.ContextRule; import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.schema.utils.ResultList; import org.openmetadata.service.Entity; +import org.openmetadata.service.jdbi3.MetricRepository; import org.openmetadata.service.search.SearchRepository; import org.openmetadata.service.search.SearchResultListMapper; import org.openmetadata.service.search.SearchSortFilter; class PersonaContextBuilderTest { + @Test + void metricKnowledgeLoadsEveryAssetThroughBoundedRepositoryPages() { + UUID metricId = UUID.randomUUID(); + Metric metric = new Metric().withId(metricId).withName("revenue"); + MetricRepository repository = mock(MetricRepository.class); + List firstPage = metricAssets(0, 1000); + List secondPage = metricAssets(1000, 1001); + when(repository.listAssets(metricId, 1000, 0, null, null, null)) + .thenReturn(new ResultList<>(firstPage, 0, 1000, 1001)); + when(repository.listAssets(metricId, 1000, 1000, null, null, null)) + .thenReturn(new ResultList<>(secondPage, 1000, 1000, 1001)); + + PersonaContextBuilder.loadMetricAssets(metric, repository); + + assertEquals(1001, metric.getAssets().size()); + assertEquals( + "service.db.schema.asset-0000", metric.getAssets().getFirst().getFullyQualifiedName()); + assertEquals( + "service.db.schema.asset-1000", metric.getAssets().getLast().getFullyQualifiedName()); + verify(repository).listAssets(metricId, 1000, 0, null, null, null); + verify(repository).listAssets(metricId, 1000, 1000, null, null, null); + } + + @Test + void metricKnowledgeUsesGenericFieldsThatExcludeTheUnboundedAssetRelationship() { + assertEquals( + "owners,tags,relatedMetrics", PersonaContextBuilder.knowledgeFields(Entity.METRIC)); + } + @Test void searchUsesDeepPaginationAndHonorsRuleLimit() throws IOException { SearchRepository repository = mock(SearchRepository.class); @@ -420,6 +455,20 @@ private static List> documents(int start, int end) { return documents; } + private static List metricAssets(int start, int end) { + return IntStream.range(start, end) + .mapToObj( + index -> + new MetricAssetDirection() + .withAsset( + new EntityReference() + .withId(UUID.nameUUIDFromBytes(("asset-" + index).getBytes())) + .withType(Entity.TABLE) + .withFullyQualifiedName( + "service.db.schema.asset-%04d".formatted(index)))) + .toList(); + } + private static Persona persona() { return new Persona() .withId(UUID.fromString("11111111-1111-1111-1111-111111111111")) diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImplTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImplTest.java new file mode 100644 index 000000000000..c7ea42379086 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/impl/RollbackEntityImplTest.java @@ -0,0 +1,288 @@ +/* + * Copyright 2026 Collate + * 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. + */ +package org.openmetadata.service.governance.workflows.elements.nodes.automatedTask.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonReader; +import java.io.StringReader; +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.flowable.common.engine.api.delegate.Expression; +import org.flowable.engine.delegate.DelegateExecution; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedStatic; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.type.ChangeDescription; +import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.EntityStatus; +import org.openmetadata.schema.type.FieldChange; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.service.Entity; +import org.openmetadata.service.exception.EntityNotFoundException; +import org.openmetadata.service.governance.workflows.elements.nodes.automatedTask.impl.RollbackEntityImpl.RejectionOutcome; +import org.openmetadata.service.jdbi3.EntityRepository; +import org.openmetadata.service.resources.feeds.MessageParser; +import org.openmetadata.service.security.policyevaluator.SubjectContext; + +class RollbackEntityImplTest { + private static final String REVIEWER = "reviewer"; + + private final RollbackEntityImpl rollbackEntity = new RollbackEntityImpl(); + + @Test + void rejectionRollsBackToMostRecentApprovedVersionAndSkipsRejectedVersion() { + UUID metricId = UUID.randomUUID(); + Metric olderApproved = metric(metricId, 0.1, EntityStatus.APPROVED, "older definition"); + Metric approved = metric(metricId, 0.2, EntityStatus.APPROVED, "approved definition"); + Metric rejected = metric(metricId, 0.3, EntityStatus.REJECTED, "rejected definition"); + Metric current = metric(metricId, 0.4, EntityStatus.IN_REVIEW, "pending definition"); + EntityRepository repository = + repositoryWithHistory(current, olderApproved, rejected, approved); + + RejectionOutcome outcome = rollbackEntity.applyRejection(repository, current, REVIEWER); + + Metric patched = capturedPatchedMetric(repository, current); + assertEquals("rollback", outcome.action()); + assertEquals(0.2, outcome.toVersion()); + assertEquals(EntityStatus.APPROVED, patched.getEntityStatus()); + assertEquals("approved definition", patched.getDescription()); + } + + @Test + void rejectionWithoutApprovedBaselineSetsRejectedAtAnyCurrentVersion() { + UUID metricId = UUID.randomUUID(); + Metric draft = metric(metricId, 0.1, EntityStatus.DRAFT, "draft definition"); + Metric rejected = metric(metricId, 0.4, EntityStatus.REJECTED, "previous rejection"); + Metric current = metric(metricId, 0.7, EntityStatus.IN_REVIEW, "pending definition"); + EntityRepository repository = repositoryWithHistory(current, rejected, draft); + + RejectionOutcome outcome = rollbackEntity.applyRejection(repository, current, REVIEWER); + + Metric patched = capturedPatchedMetric(repository, current); + assertEquals("reject", outcome.action()); + assertEquals(0.7, outcome.fromVersion()); + assertNull(outcome.toVersion()); + assertEquals(EntityStatus.REJECTED, patched.getEntityStatus()); + assertEquals("pending definition", patched.getDescription()); + } + + @Test + void rejectionSkipsUnreviewedVersionThatInheritedApprovedStatus() { + UUID metricId = UUID.randomUUID(); + Metric approved = reviewedMetric(metricId, 0.2, REVIEWER, "approved definition"); + Metric unreviewed = reviewedMetric(metricId, 0.3, "author", "pending definition"); + Metric current = + reviewedMetric(metricId, 0.4, "author", "pending definition") + .withEntityStatus(EntityStatus.IN_REVIEW); + EntityRepository repository = repositoryWithHistory(current, approved, unreviewed); + + RejectionOutcome outcome = rollbackEntity.applyRejection(repository, current, REVIEWER); + + Metric patched = capturedPatchedMetric(repository, current); + assertEquals(0.2, outcome.toVersion()); + assertEquals(EntityStatus.APPROVED, patched.getEntityStatus()); + assertEquals("approved definition", patched.getDescription()); + } + + @Test + void rejectionRecognizesRecordedApprovalTransition() { + UUID metricId = UUID.randomUUID(); + Metric approved = + reviewedMetric(metricId, 0.2, "former-reviewer", "approved definition") + .withIncrementalChangeDescription( + new ChangeDescription() + .withFieldsUpdated( + List.of( + new FieldChange() + .withName(Entity.FIELD_ENTITY_STATUS) + .withNewValue(EntityStatus.APPROVED.value())))); + Metric current = + reviewedMetric(metricId, 0.3, "author", "pending definition") + .withEntityStatus(EntityStatus.IN_REVIEW); + EntityRepository repository = repositoryWithHistory(current, approved); + + RejectionOutcome outcome = rollbackEntity.applyRejection(repository, current, REVIEWER); + + assertEquals(0.2, outcome.toVersion()); + assertEquals( + "approved definition", capturedPatchedMetric(repository, current).getDescription()); + } + + @Test + void rejectionKeepsApprovedVersionAuthoredByTeamReviewer() { + UUID metricId = UUID.randomUUID(); + EntityReference reviewerTeam = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.TEAM).withName("reviewers"); + Metric approved = + metric(metricId, 0.2, EntityStatus.APPROVED, "team-approved definition") + .withUpdatedBy("team-member") + .withReviewers(List.of(reviewerTeam)); + Metric current = + metric(metricId, 0.3, EntityStatus.IN_REVIEW, "pending definition") + .withUpdatedBy("author") + .withReviewers(List.of(reviewerTeam)); + EntityRepository repository = repositoryWithHistory(current, approved); + SubjectContext reviewerContext = mock(SubjectContext.class); + + try (MockedStatic subjectContexts = mockStatic(SubjectContext.class)) { + subjectContexts + .when(() -> SubjectContext.getSubjectContext("team-member")) + .thenReturn(reviewerContext); + when(reviewerContext.isReviewer(List.of(reviewerTeam))).thenReturn(true); + + RejectionOutcome outcome = rollbackEntity.applyRejection(repository, current, REVIEWER); + + assertEquals(0.2, outcome.toVersion()); + assertEquals( + "team-approved definition", capturedPatchedMetric(repository, current).getDescription()); + } + } + + @Test + void rejectionSkipsTeamReviewerVersionWhenHistoricalAuthorNoLongerExists() { + UUID metricId = UUID.randomUUID(); + Metric olderApproved = metric(metricId, 0.1, EntityStatus.APPROVED, "approved definition"); + EntityReference reviewerTeam = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.TEAM).withName("reviewers"); + Metric unavailableAuthor = + metric(metricId, 0.2, EntityStatus.APPROVED, "unverified definition") + .withUpdatedBy("deleted-member") + .withReviewers(List.of(reviewerTeam)); + Metric current = + metric(metricId, 0.3, EntityStatus.IN_REVIEW, "pending definition") + .withReviewers(List.of(reviewerTeam)); + EntityRepository repository = + repositoryWithHistory(current, olderApproved, unavailableAuthor); + + try (MockedStatic subjectContexts = mockStatic(SubjectContext.class)) { + subjectContexts + .when(() -> SubjectContext.getSubjectContext("deleted-member")) + .thenThrow(EntityNotFoundException.byMessage("deleted user")); + + RejectionOutcome outcome = rollbackEntity.applyRejection(repository, current, REVIEWER); + + assertEquals(0.1, outcome.toVersion()); + assertEquals( + "approved definition", capturedPatchedMetric(repository, current).getDescription()); + } + } + + @Test + void workflowExecutionRejectsWithoutBaselineAndPublishesOutcomeVariables() throws Exception { + UUID metricId = UUID.randomUUID(); + Metric current = metric(metricId, 0.8, EntityStatus.IN_REVIEW, "pending definition"); + EntityRepository repository = repositoryWithHistory(current); + DelegateExecution execution = mock(DelegateExecution.class); + Expression inputNamespaces = mock(Expression.class); + injectField(rollbackEntity, "inputNamespaceMapExpr", inputNamespaces); + when(inputNamespaces.getValue(execution)) + .thenReturn(Map.of("relatedEntity", "global", "updatedBy", "approval")); + when(execution.getVariable("global_relatedEntity")).thenReturn("<#E::metric::orders>"); + when(execution.getVariable("approval_updatedBy")).thenReturn(REVIEWER); + + try (MockedStatic entity = mockStatic(Entity.class)) { + entity + .when( + () -> Entity.getEntity(any(MessageParser.EntityLink.class), eq(""), eq(Include.ALL))) + .thenReturn(current); + entity.when(() -> Entity.getEntityRepository("metric")).thenReturn(repository); + + rollbackEntity.execute(execution); + } + + Metric patched = capturedPatchedMetric(repository, current); + assertEquals(EntityStatus.REJECTED, patched.getEntityStatus()); + verify(execution).setVariable("rollbackAction", "reject"); + verify(execution).setVariable("rollbackFromVersion", 0.8); + verify(execution).setVariable("rollbackEntityId", metricId.toString()); + verify(execution).setVariable("rollbackEntityType", "metric"); + } + + @SuppressWarnings("unchecked") + private EntityRepository repositoryWithHistory( + Metric current, Metric... earlierVersions) { + EntityRepository repository = mock(EntityRepository.class); + List serializedVersions = + List.of(earlierVersions).stream() + .map(JsonUtils::pojoToJson) + .map(Object.class::cast) + .toList(); + when(repository.listVersions(current.getId())) + .thenReturn(new EntityHistory().withVersions(serializedVersions)); + when(repository.getVersion(current.getId(), current.getVersion().toString())) + .thenReturn(current); + for (Metric earlierVersion : earlierVersions) { + when(repository.getVersion(current.getId(), earlierVersion.getVersion().toString())) + .thenReturn(earlierVersion); + } + return repository; + } + + private Metric capturedPatchedMetric(EntityRepository repository, Metric current) { + ArgumentCaptor patchCaptor = ArgumentCaptor.forClass(JsonPatch.class); + verify(repository) + .patch(isNull(), eq(current.getFullyQualifiedName()), eq(REVIEWER), patchCaptor.capture()); + return applyPatch(current, patchCaptor.getValue()); + } + + private Metric applyPatch(Metric source, JsonPatch patch) { + try (JsonReader reader = Json.createReader(new StringReader(JsonUtils.pojoToJson(source)))) { + JsonObject patched = patch.apply(reader.readObject()).asJsonObject(); + return JsonUtils.readValue(patched.toString(), Metric.class); + } + } + + private Metric metric(UUID id, double version, EntityStatus status, String description) { + return new Metric() + .withId(id) + .withName("orders") + .withFullyQualifiedName("orders") + .withVersion(version) + .withEntityStatus(status) + .withDescription(description); + } + + private Metric reviewedMetric(UUID id, double version, String updatedBy, String description) { + return metric(id, version, EntityStatus.APPROVED, description) + .withUpdatedBy(updatedBy) + .withReviewers( + List.of( + new EntityReference() + .withType(Entity.USER) + .withName(REVIEWER) + .withFullyQualifiedName(REVIEWER))); + } + + private void injectField(Object target, String fieldName, Object value) throws Exception { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(target, value); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTaskTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTaskTest.java index f23c7b3995bc..9cd5284c59a6 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTaskTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTaskTest.java @@ -42,6 +42,8 @@ import org.openmetadata.schema.type.Include; import org.openmetadata.schema.type.TaskEntityStatus; import org.openmetadata.schema.type.TaskEntityType; +import org.openmetadata.schema.type.TaskResolution; +import org.openmetadata.schema.type.TaskResolutionType; import org.openmetadata.service.Entity; import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.jdbi3.TaskRepository; @@ -774,6 +776,7 @@ void testIsSupersedableWhenPriorBelongsToEarlierRunOfSameWorkflow() { Task prior = new Task() .withId(UUID.randomUUID()) + .withStatus(TaskEntityStatus.Open) .withWorkflowDefinitionId(workflowDefinitionId) .withWorkflowInstanceId(UUID.randomUUID()); @@ -919,6 +922,21 @@ void testIsSupersedableWhenPriorTaskIsApprovedButNotYetTerminal() { CreateTask.isSupersedablePriorApprovalTask(prior, workflowDefinitionId, UUID.randomUUID())); } + @Test + void testIsNotSupersedableWhenPriorTaskHasApprovedResolution() { + UUID workflowDefinitionId = UUID.randomUUID(); + Task prior = + new Task() + .withId(UUID.randomUUID()) + .withWorkflowDefinitionId(workflowDefinitionId) + .withWorkflowInstanceId(UUID.randomUUID()) + .withStatus(TaskEntityStatus.Approved) + .withResolution(new TaskResolution().withType(TaskResolutionType.Approved)); + + assertFalse( + CreateTask.isSupersedablePriorApprovalTask(prior, workflowDefinitionId, UUID.randomUUID())); + } + // ---- mergeManualGrantReason ---- @Test diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRelationshipDaoContractTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRelationshipDaoContractTest.java new file mode 100644 index 000000000000..6b513f16814b --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRelationshipDaoContractTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2026 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openmetadata.service.jdbi3.locator.ConnectionType.MYSQL; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +import org.openmetadata.service.jdbi3.locator.ConnectionAwareSqlUpdate; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +class EntityRelationshipDaoContractTest { + + @Test + void mysqlRelationshipJsonUsesOneUtf8BindForInsertAndDuplicateUpdate() throws Exception { + Method insert = + CollectionDAO.EntityRelationshipDAO.class.getDeclaredMethod( + "insert", + UUID.class, + UUID.class, + String.class, + String.class, + int.class, + String.class, + String.class); + String mysqlSql = updatesByDialect(insert).get(MYSQL).value(); + + assertTrue(mysqlSql.contains("CONVERT(:json USING utf8mb4)")); + assertTrue(mysqlSql.contains("ON DUPLICATE KEY UPDATE json = VALUES(json)")); + assertEquals(1, mysqlSql.split(":json", -1).length - 1); + } + + private Map updatesByDialect(Method method) { + return Arrays.stream(method.getAnnotationsByType(ConnectionAwareSqlUpdate.class)) + .collect(Collectors.toMap(ConnectionAwareSqlUpdate::connectionType, Function.identity())); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRepositoryRestoreTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRepositoryRestoreTest.java index 0728171d54c2..a6cef6da8bcb 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRepositoryRestoreTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/EntityRepositoryRestoreTest.java @@ -17,9 +17,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.never; @@ -43,6 +45,7 @@ import org.openmetadata.schema.type.Relationship; import org.openmetadata.service.Entity; import org.openmetadata.service.cache.CacheBundle; +import org.openmetadata.service.events.lifecycle.EntityLifecycleEventDispatcher; import org.openmetadata.service.util.EntityUtil.Fields; import org.openmetadata.service.util.EntityUtil.RelationIncludes; @@ -95,6 +98,7 @@ private static class CountingPipelineRepo extends EntityRepository { final Set bulkRestoreInvokedWith = new HashSet<>(); final Set bulkSoftDeleteInvokedWith = new HashSet<>(); final Set bulkHardDeleteInvokedWith = new HashSet<>(); + final List restoreFromSearchSteps = new ArrayList<>(); CountingPipelineRepo(CollectionDAO.PipelineDAO dao) { super("pipelines", Entity.PIPELINE, Pipeline.class, dao, "", ""); @@ -143,6 +147,15 @@ protected void bulkEntitySpecificCleanup(List entities, String deleted bulkEntitySpecificCleanupCalls++; super.bulkEntitySpecificCleanup(entities, deletedBy); } + + @Override + protected void postRestoreFromSearch(Pipeline entity) { + restoreFromSearchSteps.add("postRestoreFromSearch"); + } + + void postCreateMany(List pipelines) { + postCreate(pipelines); + } } @BeforeEach @@ -172,6 +185,35 @@ void restoreChildren_withNoChildren_isNoOp() { assertEquals(0, repo.restoreAdditionalChildrenCalls); } + @Test + void restoreFromSearchRunsTheRepositoryHookAfterSearchDispatch() { + CountingPipelineRepo repo = new CountingPipelineRepo(pipelineDAO); + Pipeline pipeline = + new Pipeline() + .withId(UUID.randomUUID()) + .withName("pipeline") + .withFullyQualifiedName("service.pipeline") + .withDeleted(false); + EntityLifecycleEventDispatcher dispatcher = mock(EntityLifecycleEventDispatcher.class); + doAnswer( + ignored -> { + repo.restoreFromSearchSteps.add("searchDispatch"); + return null; + }) + .when(dispatcher) + .onEntitySoftDeletedOrRestored(pipeline, false, null); + + try (MockedStatic lifecycle = + mockStatic(EntityLifecycleEventDispatcher.class)) { + lifecycle.when(EntityLifecycleEventDispatcher::getInstance).thenReturn(dispatcher); + + repo.restoreFromSearch(pipeline); + } + + assertEquals(List.of("searchDispatch", "postRestoreFromSearch"), repo.restoreFromSearchSteps); + verify(dispatcher).onEntitySoftDeletedOrRestored(pipeline, false, null); + } + @Test void restoreChildren_groupsByTypeAndDispatchesOnceEach() { CountingPipelineRepo repo = new CountingPipelineRepo(pipelineDAO); @@ -265,6 +307,41 @@ void invalidate_clearsRegisteredCacheLayers() { } } + @Test + void postCreateManyClearsNegativeCacheMarkersForEachCreatedEntity() { + CountingPipelineRepo repo = new CountingPipelineRepo(pipelineDAO); + Pipeline first = + new Pipeline() + .withId(UUID.randomUUID()) + .withName("first") + .withFullyQualifiedName("service.first"); + Pipeline duplicate = + new Pipeline() + .withId(first.getId()) + .withName(first.getName()) + .withFullyQualifiedName(first.getFullyQualifiedName()); + Pipeline second = + new Pipeline() + .withId(UUID.randomUUID()) + .withName("second") + .withFullyQualifiedName("service.second"); + EntityLifecycleEventDispatcher dispatcher = mock(EntityLifecycleEventDispatcher.class); + + try (MockedStatic lifecycle = + mockStatic(EntityLifecycleEventDispatcher.class); + MockedStatic cacheBundle = mockStatic(CacheBundle.class)) { + lifecycle.when(EntityLifecycleEventDispatcher::getInstance).thenReturn(dispatcher); + + repo.postCreateMany(List.of(first, duplicate, second)); + + cacheBundle.verify( + () -> CacheBundle.invalidateEntity(Entity.PIPELINE, first.getId(), "service.first")); + cacheBundle.verify( + () -> CacheBundle.invalidateEntity(Entity.PIPELINE, second.getId(), "service.second")); + verify(dispatcher).onEntitiesCreated(argThat(created -> created.size() == 2), eq(null)); + } + } + @Test void remoteInvalidationEvictsLocalEntriesAndAdvancesLoaderEpochs() { UUID id = UUID.randomUUID(); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/GlossaryTermRepositoryBulkFieldsTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/GlossaryTermRepositoryBulkFieldsTest.java new file mode 100644 index 000000000000..1f8636182c1a --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/GlossaryTermRepositoryBulkFieldsTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2026 Collate. + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.openmetadata.service.Entity.GLOSSARY; +import static org.openmetadata.service.Entity.GLOSSARY_TERM; + +import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.openmetadata.schema.entity.data.GlossaryTerm; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.service.Entity; +import org.openmetadata.service.util.EntityUtil.Fields; + +class GlossaryTermRepositoryBulkFieldsTest { + + private CollectionDAO collectionDAO; + private CollectionDAO.EntityRelationshipDAO relationshipDAO; + private GlossaryTermRepository repository; + + @BeforeEach + void setUp() { + collectionDAO = mock(CollectionDAO.class); + relationshipDAO = mock(CollectionDAO.EntityRelationshipDAO.class); + when(collectionDAO.relationshipDAO()).thenReturn(relationshipDAO); + when(collectionDAO.glossaryTermDAO()).thenReturn(mock(CollectionDAO.GlossaryTermDAO.class)); + when(collectionDAO.relationshipTypeDAO()) + .thenReturn(mock(CollectionDAO.RelationshipTypeDAO.class)); + Entity.setCollectionDAO(collectionDAO); + repository = new GlossaryTermRepository(false); + } + + @AfterEach + void tearDown() { + Entity.cleanup(); + } + + @Test + void setFieldsInBulkDoesNotOverwriteFreshBatchedParentReference() { + UUID childId = UUID.randomUUID(); + UUID parentId = UUID.randomUUID(); + UUID glossaryId = UUID.randomUUID(); + EntityReference freshParent = entityReference(parentId, GLOSSARY_TERM, "Renamed.Parent"); + EntityReference staleParent = entityReference(parentId, GLOSSARY_TERM, "Original.Parent"); + EntityReference glossary = entityReference(glossaryId, GLOSSARY, "Glossary"); + GlossaryTerm child = + new GlossaryTerm() + .withId(childId) + .withName("Child") + .withFullyQualifiedName("Renamed.Parent.Child"); + + CollectionDAO.EntityRelationshipObject parentRecord = + relationship(parentId, GLOSSARY_TERM, childId, Relationship.CONTAINS); + CollectionDAO.EntityRelationshipObject glossaryRecord = + relationship(glossaryId, GLOSSARY, childId, Relationship.HAS); + + when(relationshipDAO.findFromBatch( + anyList(), eq(Relationship.CONTAINS.ordinal()), eq(Include.ALL))) + .thenReturn(List.of(parentRecord)); + when(relationshipDAO.findFromBatch( + anyList(), eq(Relationship.HAS.ordinal()), eq(GLOSSARY), eq(Include.ALL))) + .thenReturn(List.of(glossaryRecord)); + when(relationshipDAO.findFromBatch( + anyList(), eq(Relationship.CONTAINS.ordinal()), eq(GLOSSARY_TERM), eq(GLOSSARY_TERM))) + .thenReturn(List.of(parentRecord)); + + try (MockedStatic entityMock = mockStatic(Entity.class, CALLS_REAL_METHODS)) { + entityMock + .when( + () -> + Entity.getEntityReferencesByIds( + eq(GLOSSARY_TERM), eq(List.of(parentId)), eq(Include.ALL))) + .thenReturn(List.of(freshParent)); + entityMock + .when( + () -> + Entity.getEntityReferencesByIds( + eq(GLOSSARY), eq(List.of(glossaryId)), eq(Include.ALL))) + .thenReturn(List.of(glossary)); + entityMock + .when( + () -> Entity.getEntityReferenceById(eq(GLOSSARY_TERM), eq(parentId), eq(Include.ALL))) + .thenReturn(staleParent); + + repository.setFieldsInBulk(new Fields(Set.of("parent")), List.of(child)); + } + + assertEquals("Renamed.Parent", child.getParent().getFullyQualifiedName()); + verify(relationshipDAO, never()) + .findFromBatch( + anyList(), eq(Relationship.CONTAINS.ordinal()), eq(GLOSSARY_TERM), eq(GLOSSARY_TERM)); + } + + private static EntityReference entityReference(UUID id, String type, String fqn) { + return new EntityReference().withId(id).withType(type).withFullyQualifiedName(fqn); + } + + private static CollectionDAO.EntityRelationshipObject relationship( + UUID fromId, String fromEntity, UUID toId, Relationship relationship) { + return CollectionDAO.EntityRelationshipObject.builder() + .fromId(fromId.toString()) + .toId(toId.toString()) + .fromEntity(fromEntity) + .toEntity(GLOSSARY_TERM) + .relation(relationship.ordinal()) + .build(); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/LineageRepositoryTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/LineageRepositoryTest.java index 0f888d046d9d..eca28c0efd86 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/LineageRepositoryTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/LineageRepositoryTest.java @@ -17,6 +17,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.times; @@ -36,6 +37,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.MockedStatic; import org.openmetadata.schema.EntityInterface; +import org.openmetadata.schema.api.data.MetricDimension; +import org.openmetadata.schema.api.data.MetricMeasure; +import org.openmetadata.schema.entity.data.Metric; import org.openmetadata.schema.type.*; import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.search.IndexMapping; @@ -894,4 +898,56 @@ void testDeleteLineageBySource_OpenLineage_UsesPipelinePath() { .deleteLineageBySourcePipeline( entityId, LineageDetails.Source.OPEN_LINEAGE.value(), Relationship.UPSTREAM.ordinal()); } + + @Test + void metricChildNamesPreserveDimensionAndMeasureNamespaces() { + Metric metric = + new Metric() + .withFullyQualifiedName("revenue") + .withDimensions( + List.of( + new MetricDimension() + .withName("region") + .withFullyQualifiedName("revenue.dimension.region"), + new MetricDimension() + .withName("foreign") + .withFullyQualifiedName("anotherMetric.dimension.foreign"))) + .withMeasures( + List.of( + new MetricMeasure() + .withName("amount") + .withFullyQualifiedName("revenue.measure.amount"))); + + assertEquals( + Set.of("dimension.region", "measure.amount"), LineageRepository.metricChildNames(metric)); + } + + @Test + void relationshipWritesRetryTransientDeadlocks() { + Runnable relationshipWrite = mock(Runnable.class); + doThrow(new RuntimeException("Deadlock found when trying to get lock")) + .doNothing() + .when(relationshipWrite) + .run(); + + assertDoesNotThrow( + () -> LineageRepository.executeRelationshipWriteWithDeadlockRetry(relationshipWrite)); + + verify(relationshipWrite, times(2)).run(); + } + + @Test + void relationshipWritesDoNotRetryOtherFailures() { + Runnable relationshipWrite = mock(Runnable.class); + RuntimeException failure = new RuntimeException("Relationship validation failed"); + doThrow(failure).when(relationshipWrite).run(); + + RuntimeException thrown = + assertThrows( + RuntimeException.class, + () -> LineageRepository.executeRelationshipWriteWithDeadlockRetry(relationshipWrite)); + + assertSame(failure, thrown); + verify(relationshipWrite).run(); + } } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricDaoContractTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricDaoContractTest.java new file mode 100644 index 000000000000..0bb0369257be --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricDaoContractTest.java @@ -0,0 +1,176 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.openmetadata.service.jdbi3.locator.ConnectionType.MYSQL; +import static org.openmetadata.service.jdbi3.locator.ConnectionType.POSTGRES; + +import java.lang.reflect.Method; +import java.sql.ResultSet; +import java.util.Arrays; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.jdbi.v3.sqlobject.statement.SqlQuery; +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.service.jdbi3.locator.ConnectionAwareSqlQuery; +import org.openmetadata.service.jdbi3.locator.ConnectionType; + +class MetricDaoContractTest { + + @Test + void hierarchySqlHasEquivalentMysqlAndPostgresDisplayNameSearch() throws Exception { + Method listHierarchy = + CollectionDAO.MetricDAO.class.getDeclaredMethod( + "listHierarchy", int.class, int.class, String.class, int.class, int.class); + Map queries = queriesByDialect(listHierarchy); + + assertEquals(2, queries.size()); + assertTrue(queries.get(MYSQL).value().contains("JSON_EXTRACT(member.json, '$.displayName')")); + assertTrue(queries.get(POSTGRES).value().contains("member.json ->> 'displayName'")); + queries + .values() + .forEach( + query -> { + assertTrue(query.value().contains("LIMIT :limit OFFSET :offset")); + assertTrue(query.value().contains("JOIN metric_group_entity active_group")); + assertTrue(query.value().contains("active_group.deleted = FALSE")); + }); + } + + @Test + void groupAssignmentLocksMetricsInStableOrder() throws Exception { + Method lock = + CollectionDAO.MetricDAO.class.getDeclaredMethod( + "lockForGroupAssignment", java.util.List.class); + String query = lock.getAnnotation(SqlQuery.class).value(); + + assertTrue(query.contains("ORDER BY id FOR UPDATE")); + assertTrue(query.contains("id IN ()")); + } + + @Test + void singleMetricGroupLookupFiltersSoftDeletedGroupsInSql() throws Exception { + Method lookup = + CollectionDAO.MetricDAO.class.getDeclaredMethod("findActiveGroupId", UUID.class, int.class); + String query = lookup.getAnnotation(SqlQuery.class).value(); + + assertTrue(query.contains("JOIN metric_group_entity")); + assertTrue(query.contains("mg.deleted = FALSE")); + } + + @Test + void batchMetricGroupLookupFiltersSoftDeletedGroupsInSql() throws Exception { + Method lookup = + CollectionDAO.MetricDAO.class.getDeclaredMethod( + "findActiveGroupsInternal", java.util.List.class, int.class); + String query = lookup.getAnnotation(SqlQuery.class).value(); + + assertTrue(query.contains("JOIN metric_group_entity")); + assertTrue(query.contains("mg.deleted = FALSE")); + assertTrue(query.contains("er.deleted = FALSE")); + assertTrue(query.contains("er.toId IN ()")); + } + + @Test + void childrenCountQueriesExcludeSoftDeletedMetricsForSingleAndBatchHydration() throws Exception { + Method single = + CollectionDAO.EntityRelationshipDAO.class.getDeclaredMethod( + "countNonDeletedChildMetrics", UUID.class, int.class); + Method batch = + CollectionDAO.EntityRelationshipDAO.class.getDeclaredMethod( + "countNonDeletedChildMetricsBatch", java.util.List.class, int.class); + String singleQuery = single.getAnnotation(SqlQuery.class).value(); + String batchQuery = batch.getAnnotation(SqlQuery.class).value(); + + assertTrue(singleQuery.contains("JOIN metric_entity me ON er.toId = me.id")); + assertTrue(singleQuery.contains("er.fromEntity = 'metric'")); + assertTrue(singleQuery.contains("er.toEntity = 'metric'")); + assertTrue(singleQuery.contains("me.deleted = false OR me.deleted IS NULL")); + assertTrue(batchQuery.contains("JOIN metric_entity me ON er.toId = me.id")); + assertTrue(batchQuery.contains("er.fromId IN ()")); + assertTrue(batchQuery.contains("me.deleted = false OR me.deleted IS NULL")); + assertTrue(batchQuery.contains("GROUP BY er.fromId")); + } + + @Test + void groupMembershipListAndCountUseTheSameDialectSpecificSearchPredicate() throws Exception { + Method listMembers = + CollectionDAO.MetricGroupDAO.class.getDeclaredMethod( + "listMemberJsons", UUID.class, int.class, String.class, int.class, int.class); + Method countMembers = + CollectionDAO.MetricGroupDAO.class.getDeclaredMethod( + "countMembers", UUID.class, int.class, String.class); + Map listQueries = queriesByDialect(listMembers); + Map countQueries = queriesByDialect(countMembers); + + assertEquals(2, listQueries.size()); + assertEquals(2, countQueries.size()); + listQueries.values().forEach(query -> assertTrue(query.value().contains("SELECT me.json"))); + assertTrue( + listQueries.get(MYSQL).value().contains(CollectionDAO.MetricGroupDAO.MEMBER_MATCH_MYSQL)); + assertTrue( + countQueries.get(MYSQL).value().contains(CollectionDAO.MetricGroupDAO.MEMBER_MATCH_MYSQL)); + assertTrue( + listQueries + .get(POSTGRES) + .value() + .contains(CollectionDAO.MetricGroupDAO.MEMBER_MATCH_POSTGRES)); + assertTrue( + countQueries + .get(POSTGRES) + .value() + .contains(CollectionDAO.MetricGroupDAO.MEMBER_MATCH_POSTGRES)); + } + + @Test + void metricHierarchyListFilterUsesRelationshipIdsInsteadOfFqnPrefixes() { + UUID parentId = UUID.randomUUID(); + ListFilter parent = new ListFilter().addQueryParam("parentMetricId", parentId.toString()); + ListFilter roots = new ListFilter().addQueryParam("rootMetrics", "true"); + + String parentCondition = CollectionDAO.MetricDAO.addHierarchyCondition(parent, "WHERE TRUE"); + String rootCondition = CollectionDAO.MetricDAO.addHierarchyCondition(roots, "WHERE TRUE"); + + assertTrue(parentCondition.contains("er.fromId = :parentMetricId")); + assertTrue(parentCondition.contains("er.relation = " + Relationship.CONTAINS.ordinal())); + assertTrue(rootCondition.contains("NOT EXISTS")); + assertTrue(rootCondition.contains("er.toId = metric_entity.id")); + } + + @Test + void hierarchyRowMapperPreservesTypedIds() throws Exception { + UUID id = UUID.randomUUID(); + ResultSet resultSet = mock(ResultSet.class); + when(resultSet.getString("hierarchy_id")).thenReturn(id.toString()); + when(resultSet.getString("entity_type")).thenReturn("metricGroup"); + + CollectionDAO.MetricDAO.HierarchyRow row = + new CollectionDAO.MetricDAO.HierarchyRowMapper().map(resultSet, null); + + assertEquals(id, row.id()); + assertEquals("metricGroup", row.entityType()); + } + + private Map queriesByDialect(Method method) { + return Arrays.stream(method.getAnnotationsByType(ConnectionAwareSqlQuery.class)) + .collect(Collectors.toMap(ConnectionAwareSqlQuery::connectionType, Function.identity())); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricGroupRepositoryTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricGroupRepositoryTest.java new file mode 100644 index 000000000000..b6725ee58002 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricGroupRepositoryTest.java @@ -0,0 +1,480 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.openmetadata.schema.type.Include.NON_DELETED; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.MockedStatic; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.service.Entity; +import org.openmetadata.service.events.lifecycle.EntityLifecycleEventDispatcher; +import org.openmetadata.service.rdf.RdfUpdater; +import org.openmetadata.service.util.EntityUtil.Fields; +import org.openmetadata.service.util.RequestEntityCache; + +class MetricGroupRepositoryTest { + private CollectionDAO collectionDAO; + private CollectionDAO.MetricGroupDAO groupDAO; + private CollectionDAO.MetricDAO metricDAO; + private CollectionDAO.EntityRelationshipDAO relationshipDAO; + private MetricGroupRepository repository; + + @BeforeEach + void setUp() { + collectionDAO = mock(CollectionDAO.class); + groupDAO = mock(CollectionDAO.MetricGroupDAO.class); + metricDAO = mock(CollectionDAO.MetricDAO.class); + relationshipDAO = mock(CollectionDAO.EntityRelationshipDAO.class); + when(collectionDAO.metricGroupDAO()).thenReturn(groupDAO); + when(collectionDAO.metricDAO()).thenReturn(metricDAO); + when(collectionDAO.relationshipDAO()).thenReturn(relationshipDAO); + Entity.setCollectionDAO(collectionDAO); + Entity.setEntityRelationshipRepository(new EntityRelationshipRepository(collectionDAO)); + repository = new MetricGroupRepository(); + } + + @AfterEach + void tearDown() { + Entity.cleanup(); + } + + @Test + void genericFieldsRejectUnboundedMembershipHydration() { + assertFalse(repository.getAllowedFields().contains("metrics")); + assertThrows(IllegalArgumentException.class, () -> repository.getFields("metrics")); + } + + @Test + void metricCountUsesCountQueryWithoutHydratingMembers() { + MetricGroup group = group("large_group"); + when(groupDAO.countNonDeletedMembers(group.getId(), Relationship.HAS.ordinal())) + .thenReturn(12_345); + + repository.setFields(group, new Fields(Set.of("metricCount")), null); + + assertEquals(12_345, group.getMetricCount()); + verify(relationshipDAO, never()) + .findTo(group.getId(), Entity.METRIC_GROUP, Relationship.HAS.ordinal(), Entity.METRIC); + } + + @Test + void metricCountBulkHydrationUsesBoundedDaoChunks() { + List groups = new ArrayList<>(); + for (int index = 0; index < 1001; index++) { + groups.add(group("group_" + index)); + } + when(groupDAO.countNonDeletedMembersBatch(anyList(), anyInt())) + .thenAnswer( + invocation -> + invocation.>getArgument(0).stream() + .map( + id -> + CollectionDAO.EntityRelationshipCount.builder() + .id(UUID.fromString(id)) + .count(7) + .build()) + .toList()); + + repository.setFieldsInBulk(new Fields(Set.of("metricCount")), groups); + + groups.forEach(group -> assertEquals(7, group.getMetricCount())); + ArgumentCaptor> chunks = ArgumentCaptor.forClass(List.class); + verify(groupDAO, times(3)).countNonDeletedMembersBatch(chunks.capture(), anyInt()); + assertEquals(List.of(500, 500, 1), chunks.getAllValues().stream().map(List::size).toList()); + } + + @Test + void visibleMetricCountUsesMemberJsonWithoutASecondEntityLookup() { + UUID groupId = UUID.randomUUID(); + Metric visible = metric("visible"); + Metric hidden = metric("hidden"); + when(groupDAO.countMembers(groupId, Relationship.HAS.ordinal(), "%")).thenReturn(2); + when(groupDAO.listMemberJsons(groupId, Relationship.HAS.ordinal(), "%", 500, 0)) + .thenReturn(List.of(JsonUtils.pojoToJson(visible), JsonUtils.pojoToJson(hidden))); + + int count = + repository.visibleMetricCount( + groupId, reference -> visible.getId().equals(reference.getId())); + + assertEquals(1, count); + verify(groupDAO, times(1)).listMemberJsons(groupId, Relationship.HAS.ordinal(), "%", 500, 0); + } + + @Test + void visibleMetricCountRejectsAnUnboundedPermissionScanBeforeLoadingMembers() { + UUID groupId = UUID.randomUUID(); + when(groupDAO.countMembers(groupId, Relationship.HAS.ordinal(), "%")) + .thenReturn(MetricGroupRepository.MAX_PERMISSION_FILTER_SCAN_SIZE + 1); + + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> repository.visibleMetricCount(groupId, ignored -> true)); + + assertTrue(exception.getMessage().contains("Narrow the query")); + verify(groupDAO, never()).listMemberJsons(groupId, Relationship.HAS.ordinal(), "%", 500, 0); + } + + @Test + void unrestrictedMemberPagingUsesOneBoundedPageAndCountQuery() { + UUID groupId = UUID.randomUUID(); + Metric first = metric("margin"); + Metric second = metric("gross_margin"); + when(groupDAO.listMemberJsons(groupId, Relationship.HAS.ordinal(), "%margin%", 25, 50)) + .thenReturn(List.of(JsonUtils.pojoToJson(first), JsonUtils.pojoToJson(second))); + when(groupDAO.countMembers(groupId, Relationship.HAS.ordinal(), "%margin%")).thenReturn(12_345); + + MetricGroupRepository.MemberScan scan = + repository.scanUnrestrictedMemberIds(groupId, 25, 50, "margin", false); + + assertEquals(List.of(first.getId(), second.getId()), scan.ids()); + assertEquals(12_345, scan.total()); + verify(groupDAO).listMemberJsons(groupId, Relationship.HAS.ordinal(), "%margin%", 25, 50); + verify(groupDAO).countMembers(groupId, Relationship.HAS.ordinal(), "%margin%"); + verify(groupDAO, never()) + .listMemberJsons(groupId, Relationship.HAS.ordinal(), "%margin%", 500, 0); + } + + @Test + void unrestrictedRootPagingUsesRootPageAndCountQueries() { + UUID groupId = UUID.randomUUID(); + Metric root = metric("margin"); + when(groupDAO.listRootMemberJsonsPage( + groupId, Relationship.HAS.ordinal(), Relationship.CONTAINS.ordinal(), "%", 10, 20)) + .thenReturn(List.of(JsonUtils.pojoToJson(root))); + when(groupDAO.countRootMembersPage( + groupId, Relationship.HAS.ordinal(), Relationship.CONTAINS.ordinal(), "%")) + .thenReturn(321); + + MetricGroupRepository.MemberScan scan = + repository.scanUnrestrictedMemberIds(groupId, 10, 20, null, true); + + assertEquals(List.of(root.getId()), scan.ids()); + assertEquals(321, scan.total()); + verify(groupDAO) + .listRootMemberJsonsPage( + groupId, Relationship.HAS.ordinal(), Relationship.CONTAINS.ordinal(), "%", 10, 20); + verify(groupDAO) + .countRootMembersPage( + groupId, Relationship.HAS.ordinal(), Relationship.CONTAINS.ordinal(), "%"); + } + + @Test + void transactionBoundSubtreeAssignmentPropagatesMidMutationFailures() { + EntityReference originalGroup = group("original").getEntityReference(); + EntityReference targetGroup = group("target").getEntityReference(); + EntityReference root = metric("root").getEntityReference(); + EntityReference child = metric("child").getEntityReference(); + CollectionDAO.EntityRelationshipRecord originalMembership = + CollectionDAO.EntityRelationshipRecord.builder() + .id(originalGroup.getId()) + .type(Entity.METRIC_GROUP) + .build(); + when(relationshipDAO.findFrom( + root.getId(), Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of(originalMembership)); + when(relationshipDAO.findFrom( + child.getId(), Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of(originalMembership)); + doThrow(new IllegalStateException("database rejected child membership")) + .when(relationshipDAO) + .insert( + targetGroup.getId(), + child.getId(), + Entity.METRIC_GROUP, + Entity.METRIC, + Relationship.HAS.ordinal()); + + assertThrows( + IllegalStateException.class, + () -> + MetricGroupRepository.assignHierarchyGroup( + relationshipDAO, List.of(root, child), targetGroup)); + + verify(relationshipDAO) + .delete( + originalGroup.getId(), + Entity.METRIC_GROUP, + root.getId(), + Entity.METRIC, + Relationship.HAS.ordinal()); + verify(relationshipDAO) + .insert( + targetGroup.getId(), + root.getId(), + Entity.METRIC_GROUP, + Entity.METRIC, + Relationship.HAS.ordinal()); + verify(relationshipDAO) + .insert( + targetGroup.getId(), + child.getId(), + Entity.METRIC_GROUP, + Entity.METRIC, + Relationship.HAS.ordinal()); + } + + @Test + void currentTransactionAssignmentLocksTheSubtreeInStableOrderBeforeMutation() { + CollectionDAO.MetricDAO metricDAO = mock(CollectionDAO.MetricDAO.class); + EntityReference root = + metric("root") + .withId(UUID.fromString("00000000-0000-0000-0000-000000000002")) + .getEntityReference(); + EntityReference child = + metric("child") + .withId(UUID.fromString("00000000-0000-0000-0000-000000000001")) + .getEntityReference(); + EntityReference targetGroup = group("target").getEntityReference(); + when(relationshipDAO.findFrom( + root.getId(), Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of()); + when(relationshipDAO.findFrom( + child.getId(), Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of()); + + MetricGroupRepository.MembershipChange change = + MetricGroupRepository.assignHierarchyGroupWithLock( + metricDAO, relationshipDAO, List.of(root, child), targetGroup); + + InOrder mutationOrder = inOrder(metricDAO, relationshipDAO); + mutationOrder + .verify(metricDAO) + .lockForGroupAssignment( + List.of( + "00000000-0000-0000-0000-000000000001", "00000000-0000-0000-0000-000000000002")); + mutationOrder + .verify(relationshipDAO) + .findFrom(root.getId(), Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP); + mutationOrder + .verify(relationshipDAO) + .insert( + targetGroup.getId(), + root.getId(), + Entity.METRIC_GROUP, + Entity.METRIC, + Relationship.HAS.ordinal()); + assertEquals(List.of(root, child), change.metrics()); + assertEquals(Set.of(targetGroup), change.groups()); + } + + @Test + void currentTransactionAssignmentReadsTheSubtreeThroughTheTransactionDao() { + UUID rootId = UUID.randomUUID(); + UUID childId = UUID.randomUUID(); + Metric root = metric("root").withId(rootId); + Metric child = metric("child").withId(childId); + EntityReference targetGroup = group("target").getEntityReference(); + CollectionDAO transactionDAO = mock(CollectionDAO.class); + CollectionDAO.MetricDAO transactionMetricDAO = mock(CollectionDAO.MetricDAO.class); + CollectionDAO.EntityRelationshipDAO transactionRelationshipDAO = + mock(CollectionDAO.EntityRelationshipDAO.class); + when(transactionDAO.metricDAO()).thenReturn(transactionMetricDAO); + when(transactionDAO.relationshipDAO()).thenReturn(transactionRelationshipDAO); + when(transactionMetricDAO.listDescendantSeedIds(rootId, Relationship.CONTAINS.ordinal())) + .thenReturn(List.of(childId.toString())); + when(transactionMetricDAO.listDescendantSeedIds(childId, Relationship.CONTAINS.ordinal())) + .thenReturn(List.of()); + when(transactionMetricDAO.findEntitiesByIds(List.of(rootId, childId), NON_DELETED)) + .thenReturn(List.of(root, child)); + when(transactionRelationshipDAO.findFrom( + rootId, Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of()); + when(transactionRelationshipDAO.findFrom( + childId, Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of()); + AtomicReference change = new AtomicReference<>(); + + RepositoryTransactionContext.runWith( + transactionDAO, + () -> change.set(repository.assignHierarchyGroupInCurrentTransaction(rootId, targetGroup))); + + assertEquals( + List.of(root.getEntityReference(), child.getEntityReference()), change.get().metrics()); + verify(transactionMetricDAO) + .lockForGroupAssignment( + List.of(rootId.toString(), childId.toString()).stream().sorted().toList()); + verify(metricDAO, never()).listDescendantSeedIds(rootId, Relationship.CONTAINS.ordinal()); + } + + @Test + void repeatedPreparationAcceptsAnAlreadyExpandedRootSubtree() { + EntityReference root = metric("root").getEntityReference(); + EntityReference child = metric("child").getEntityReference(); + + MetricGroupRepository.validateRequestedHierarchyMembers( + List.of(root, child), Set.of(root.getId(), child.getId())); + } + + @Test + void hierarchySelectionRejectsAChildWithoutItsRoot() { + EntityReference child = metric("child").getEntityReference(); + + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + MetricGroupRepository.validateRequestedHierarchyMembers(List.of(child), Set.of())); + + assertEquals("Metric 'child' is not a hierarchy root", exception.getMessage()); + } + + @Test + void putPreparationRecognizesExistingMembershipByStableNameBeforeIdIsKnown() { + MetricGroup target = new MetricGroup().withName("profitability"); + EntityReference sameByName = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC_GROUP) + .withName("profitability") + .withFullyQualifiedName("profitability"); + EntityReference other = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC_GROUP) + .withName("growth") + .withFullyQualifiedName("growth"); + + assertEquals(true, MetricGroupRepository.referencesTargetGroup(sameByName, target)); + assertEquals(false, MetricGroupRepository.referencesTargetGroup(other, target)); + + target.setId(sameByName.getId()); + target.setName("renamed-after-resolution"); + assertEquals(true, MetricGroupRepository.referencesTargetGroup(sameByName, target)); + } + + @Test + void hardDeleteRetainsMembersForPostCommitRefresh() { + MetricGroup group = group("deleted_group"); + EntityReference member = metric("member").getEntityReference(); + List queriedMembers = new ArrayList<>(List.of(member)); + + MetricGroupRepository.retainMembersForPostDelete(group, queriedMembers); + queriedMembers.clear(); + + assertEquals(List.of(member), group.getMetrics()); + } + + @Test + void restoredGroupSearchDispatchPrecedesItsMemberRefresh() { + MetricGroup group = group("restored_group").withDeleted(false); + EntityReference member = metric("member").getEntityReference(); + group.setMetrics(List.of(member)); + when(relationshipDAO.findFrom( + member.getId(), Entity.METRIC, Relationship.HAS.ordinal(), Entity.METRIC_GROUP)) + .thenReturn(List.of()); + EntityLifecycleEventDispatcher dispatcher = mock(EntityLifecycleEventDispatcher.class); + + try (MockedStatic lifecycle = + mockStatic(EntityLifecycleEventDispatcher.class); + MockedStatic cache = mockStatic(EntityRepository.class); + MockedStatic requestCache = mockStatic(RequestEntityCache.class); + MockedStatic rdf = mockStatic(RdfUpdater.class)) { + lifecycle.when(EntityLifecycleEventDispatcher::getInstance).thenReturn(dispatcher); + + repository.restoreFromSearch(group); + + InOrder restoreDispatch = inOrder(dispatcher); + restoreDispatch.verify(dispatcher).onEntitySoftDeletedOrRestored(group, false, null); + restoreDispatch.verify(dispatcher).onEntityUpdated(member, null); + verify(dispatcher, never()).onEntityUpdated(group.getEntityReference(), null); + cache.verify( + () -> + EntityRepository.invalidateCacheForEntity( + Entity.METRIC, member.getId(), member.getFullyQualifiedName())); + requestCache.verify( + () -> + RequestEntityCache.invalidate( + Entity.METRIC, member.getId(), member.getFullyQualifiedName())); + cache.verify( + () -> + EntityRepository.invalidateCacheForEntity(Entity.METRIC_GROUP, group.getId(), null)); + } + } + + @Test + void replacingMembersRefreshesTheEditedGroupSearchDocument() { + EntityReference originalMember = + metric("original_member").getEntityReference().withType(Entity.METRIC); + EntityReference replacementMember = + metric("replacement_member").getEntityReference().withType(Entity.METRIC); + MetricGroup original = + group("edited_group").withUpdatedBy("admin").withMetrics(List.of(originalMember)); + MetricGroup updated = + new MetricGroup() + .withId(original.getId()) + .withName(original.getName()) + .withFullyQualifiedName(original.getFullyQualifiedName()) + .withUpdatedBy("admin") + .withMetrics(List.of(replacementMember)); + when(relationshipDAO.findFrom( + updated.getMetrics().getFirst().getId(), + Entity.METRIC, + Relationship.HAS.ordinal(), + Entity.METRIC_GROUP)) + .thenReturn(List.of()); + EntityLifecycleEventDispatcher dispatcher = mock(EntityLifecycleEventDispatcher.class); + + try (MockedStatic lifecycle = + mockStatic(EntityLifecycleEventDispatcher.class); + MockedStatic cache = mockStatic(EntityRepository.class); + MockedStatic requestCache = mockStatic(RequestEntityCache.class); + MockedStatic rdf = mockStatic(RdfUpdater.class)) { + lifecycle.when(EntityLifecycleEventDispatcher::getInstance).thenReturn(dispatcher); + MetricGroupRepository.MetricGroupUpdater updater = + repository.new MetricGroupUpdater(original, updated, EntityRepository.Operation.PUT); + + updater.entitySpecificUpdate(false); + updater.runDeferredReactOperations(); + + verify(dispatcher).onEntityUpdated(updated.getEntityReference(), null); + } + } + + private MetricGroup group(String name) { + return new MetricGroup().withId(UUID.randomUUID()).withName(name).withFullyQualifiedName(name); + } + + private Metric metric(String name) { + return new Metric().withId(UUID.randomUUID()).withName(name).withFullyQualifiedName(name); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilderTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilderTest.java new file mode 100644 index 000000000000..823666a9f11f --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricObservabilityBuilderTest.java @@ -0,0 +1,507 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.MockedStatic; +import org.openmetadata.schema.api.data.MetricAssetDirection; +import org.openmetadata.schema.api.data.MetricAssetRollup; +import org.openmetadata.schema.api.data.MetricIncident; +import org.openmetadata.schema.api.data.MetricObservability; +import org.openmetadata.schema.api.data.MetricObservabilityReasonCode; +import org.openmetadata.schema.api.data.MetricSourceCoverage; +import org.openmetadata.schema.api.data.MetricTestStatusCounts; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.tests.ResultSummary; +import org.openmetadata.schema.tests.TestCase; +import org.openmetadata.schema.tests.type.Severity; +import org.openmetadata.schema.tests.type.TestCaseResolutionStatus; +import org.openmetadata.schema.tests.type.TestCaseResolutionStatusTypes; +import org.openmetadata.schema.tests.type.TestCaseStatus; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.MetricHealth; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.service.Entity; +import org.openmetadata.service.util.EntityUtil.Fields; +import org.openmetadata.service.util.FullyQualifiedName; + +/** + * Covers the health banding, which is the one piece of the rollup that is pure arithmetic and + * therefore worth pinning without a database. Everything else in the builder reads real entities + * and is exercised by MetricResourceIT instead. + */ +class MetricObservabilityBuilderTest { + + @ParameterizedTest + @CsvSource({ + "100.0, HEALTHY", + "90.0, HEALTHY", + "89.999, AT_RISK", + "89.0, AT_RISK", + "75.0, AT_RISK", + "74.999, DEGRADED", + "50.0, DEGRADED", + "0.0, DEGRADED" + }) + void healthFor_bandsScoresAtTheDocumentedBoundaries(double score, MetricHealth expected) { + assertEquals(expected, MetricObservabilityBuilder.healthFor(score)); + } + + @Test + void healthFor_unscoredAssetIsUnknownRatherThanZero() { + assertEquals( + MetricHealth.UNKNOWN, + MetricObservabilityBuilder.healthFor(null), + "An asset with no tests must not be treated as a 0% failure"); + } + + @Test + void thresholdsMatchTheDocumentedBands() { + assertEquals(90.0, MetricObservabilityBuilder.HEALTHY_THRESHOLD); + assertEquals(75.0, MetricObservabilityBuilder.AT_RISK_THRESHOLD); + } + + @Test + void telemetryRecordsLatencySourcesTestsFailuresAndRedaction() { + SimpleMeterRegistry registry = new SimpleMeterRegistry(); + MetricObservabilityBuilder builder = new MetricObservabilityBuilder(null, registry); + MetricObservability result = + new MetricObservability() + .withUpstreamAssetCount(4) + .withStatusCounts( + new MetricTestStatusCounts() + .withPassed(2) + .withFailed(1) + .withAborted(1) + .withQueued(2) + .withMissing(3)) + .withSourceCoverage(new MetricSourceCoverage().withRestrictedTables(2)); + + builder.recordTelemetry(result, 5_000_000L, false); + + assertEquals(1, registry.get("om_metric_observability_duration").timer().count()); + assertEquals( + 4.0, registry.get("om_metric_observability_upstream_tables").summary().totalAmount()); + assertEquals(9.0, registry.get("om_metric_observability_active_tests").summary().totalAmount()); + assertEquals( + 2.0, registry.get("om_metric_observability_redacted_sources_total").counter().count()); + assertEquals(0.0, registry.get("om_metric_observability_failures_total").counter().count()); + } + + @Test + void telemetryCountsUnavailableComputationsAsFailures() { + SimpleMeterRegistry registry = new SimpleMeterRegistry(); + MetricObservabilityBuilder builder = new MetricObservabilityBuilder(null, registry); + + MetricObservability result = builder.build(UUID.randomUUID()); + + assertEquals(MetricObservabilityReasonCode.UNAVAILABLE, result.getReasonCode()); + assertEquals(1, registry.get("om_metric_observability_duration").timer().count()); + assertEquals(1.0, registry.get("om_metric_observability_failures_total").counter().count()); + } + + @Test + void buildUsesPrefetchedLinkedAssetsWithoutResolvingLineageAgain() { + UUID metricId = UUID.randomUUID(); + Metric metric = new Metric().withId(metricId).withName("revenue"); + MetricRepository repository = mock(MetricRepository.class); + Fields fields = new Fields(Set.of("id")); + when(repository.getFields("id")).thenReturn(fields); + when(repository.get(null, metricId, fields)).thenReturn(metric); + MetricObservabilityBuilder builder = + new MetricObservabilityBuilder(repository, new SimpleMeterRegistry()); + + MetricObservability result = builder.build(metricId, List.of(), Set.of()); + + assertEquals(MetricHealth.UNKNOWN, result.getHealth()); + verify(repository, never()).getAssetsWithDirection(metricId); + } + + @Test + void loadIncidentsSkipsTheBatchDaoWhenThereAreNoVisibleTests() { + MetricObservabilityBuilder builder = + new MetricObservabilityBuilder(null, new SimpleMeterRegistry()); + + assertTrue(builder.loadIncidents(List.of(), Set.of()).isEmpty()); + } + + @Test + void latestResultSelectionUsesTheNewestMatchingTestCase() throws Exception { + String testCaseFqn = "service.database.schema.table.test"; + ResultSummary older = + new ResultSummary().withStatus(TestCaseStatus.Success).withTimestamp(100L); + ResultSummary newest = + new ResultSummary().withStatus(TestCaseStatus.Failed).withTimestamp(300L); + ResultSummary other = + new ResultSummary() + .withTestCaseName("service.database.schema.table.other") + .withStatus(TestCaseStatus.Success) + .withTimestamp(900L); + older.setTestCaseName(testCaseFqn); + newest.setTestCaseName(testCaseFqn); + MetricObservabilityBuilder builder = + new MetricObservabilityBuilder(null, new SimpleMeterRegistry()); + + assertSame(newest, invokeLatestResult(builder, testCaseFqn, List.of(older, other, newest))); + assertNull(invokeLatestResult(builder, "missing", List.of(older, other, newest))); + } + + @Test + void activeTestCasesHydratesRelationshipDerivedTestDefinitions() throws Exception { + UUID testCaseId = UUID.randomUUID(); + UUID definitionId = UUID.randomUUID(); + TestCase testCase = new TestCase().withId(testCaseId).withName("consistency_test"); + EntityReference definition = + new EntityReference() + .withId(definitionId) + .withName("consistency_definition") + .withType(Entity.TEST_DEFINITION); + CollectionDAO collectionDAO = mock(CollectionDAO.class); + CollectionDAO.TestCaseDAO testCaseDAO = mock(CollectionDAO.TestCaseDAO.class); + TestCaseRepository testCaseRepository = mock(TestCaseRepository.class); + Fields fields = new Fields(Set.of(Entity.TEST_DEFINITION), Entity.TEST_DEFINITION); + when(collectionDAO.testCaseDAO()).thenReturn(testCaseDAO); + when(testCaseDAO.findEntitiesByIds(List.of(testCaseId), Include.NON_DELETED)) + .thenReturn(List.of(testCase)); + when(testCaseRepository.getFields(Entity.TEST_DEFINITION)).thenReturn(fields); + doAnswer( + invocation -> { + testCase.setTestDefinition(definition); + return null; + }) + .when(testCaseRepository) + .setFieldsInBulk(fields, List.of(testCase)); + try (MockedStatic entity = mockStatic(Entity.class, CALLS_REAL_METHODS)) { + entity.when(Entity::getCollectionDAO).thenReturn(collectionDAO); + entity + .when(() -> Entity.getEntityRepository(Entity.TEST_CASE)) + .thenReturn(testCaseRepository); + MetricObservabilityBuilder builder = + new MetricObservabilityBuilder(null, new SimpleMeterRegistry()); + + Map testCases = invokeActiveTestCases(builder, Set.of(testCaseId)); + + assertEquals(definition, testCases.get(testCaseId).getTestDefinition()); + } + } + + @Test + void incidentsExposeSeverityAndStatusWhileFilteringResolvedAndDuplicateStates() { + EntityReference source = table("incident_source"); + MetricObservabilityBuilder.Observation primary = + observation(source, "primary", "Accuracy", TestCaseStatus.Failed, 100L); + MetricObservabilityBuilder.Observation duplicate = + observation(source, "duplicate", "Accuracy", TestCaseStatus.Failed, 200L); + MetricObservabilityBuilder.Observation resolved = + observation(source, "resolved", "Accuracy", TestCaseStatus.Failed, 300L); + UUID sharedStateId = UUID.randomUUID(); + UUID resolvedStateId = UUID.randomUUID(); + TestCaseResolutionStatus openStatus = + resolutionStatus( + sharedStateId, TestCaseResolutionStatusTypes.New, Severity.Severity1, 400L); + TestCaseResolutionStatus duplicateStatus = + resolutionStatus( + sharedStateId, TestCaseResolutionStatusTypes.Ack, Severity.Severity2, 500L); + TestCaseResolutionStatus resolvedStatus = + resolutionStatus( + resolvedStateId, TestCaseResolutionStatusTypes.Resolved, Severity.Severity3, 600L); + CollectionDAO collectionDAO = mock(CollectionDAO.class); + CollectionDAO.TestCaseResolutionStatusTimeSeriesDAO statusDAO = + mock(CollectionDAO.TestCaseResolutionStatusTimeSeriesDAO.class); + when(collectionDAO.testCaseResolutionStatusTimeSeriesDao()).thenReturn(statusDAO); + when(statusDAO.getLatestRecordBatch(anyList())) + .thenReturn( + List.of( + incidentRecord(primary, openStatus), + incidentRecord(duplicate, duplicateStatus), + incidentRecord(resolved, resolvedStatus))); + Entity.setCollectionDAO(collectionDAO); + + try { + MetricObservabilityBuilder builder = + new MetricObservabilityBuilder(null, new SimpleMeterRegistry()); + List incidents = + builder.loadIncidents(List.of(primary, duplicate, resolved), Set.of(source.getId())); + + assertEquals(1, incidents.size()); + MetricIncident incident = incidents.getFirst(); + assertEquals(sharedStateId, incident.getId()); + assertEquals(primary.testCase().getId(), incident.getTestCase().getId()); + assertEquals(source.getId(), incident.getAsset().getId()); + assertEquals(Severity.Severity1.value(), incident.getSeverity()); + assertEquals(TestCaseResolutionStatusTypes.New.value(), incident.getStatus()); + assertEquals(400L, incident.getTimestamp()); + } finally { + Entity.cleanup(); + } + } + + @Test + void summarize_scoresOnlyTerminalResultsAndUsesLatestTerminalRun() { + EntityReference first = table("first"); + EntityReference second = table("second"); + List observations = + List.of( + observation(first, "success", "Accuracy", TestCaseStatus.Success, 100L), + observation(first, "queued", "Accuracy", TestCaseStatus.Queued, 900L), + observation(first, "missing", "Accuracy", null, null), + observation(second, "failed", "Completeness", TestCaseStatus.Failed, 200L), + observation(second, "aborted", "Completeness", TestCaseStatus.Aborted, 300L)); + + MetricObservability result = + MetricObservabilityBuilder.summarize( + metric(), + linked(first, second), + List.of(first, second), + observations, + List.of(), + Set.of(first.getId(), second.getId())); + + assertEquals(100.0 / 3.0, result.getScore(), 0.0001); + assertEquals(MetricHealth.DEGRADED, result.getHealth()); + assertEquals(1, result.getStatusCounts().getPassed()); + assertEquals(1, result.getStatusCounts().getFailed()); + assertEquals(1, result.getStatusCounts().getAborted()); + assertEquals(1, result.getStatusCounts().getQueued()); + assertEquals(1, result.getStatusCounts().getMissing()); + assertEquals(3, result.getStatusCounts().getTerminal()); + assertEquals(300L, result.getLatestRunTime()); + assertEquals(2, result.getDimensions().size()); + assertEquals(5, result.getTests().size()); + MetricAssetRollup failedSource = + result.getAssets().stream() + .filter(rollup -> second.getId().equals(rollup.getAsset().getId())) + .findFirst() + .orElseThrow(); + assertEquals(2, failedSource.getTotal()); + assertEquals(1, failedSource.getFailed()); + assertEquals(1, failedSource.getAborted()); + var completeness = + result.getDimensions().stream() + .filter(rollup -> "Completeness".equals(rollup.getDimension())) + .findFirst() + .orElseThrow(); + assertEquals(2, completeness.getTotal()); + assertEquals(1, completeness.getFailed()); + assertEquals(1, completeness.getAborted()); + } + + @Test + void summarize_keepsGlobalScoreWhileRedactingRestrictedSourceDetails() { + EntityReference visible = table("visible"); + EntityReference restricted = table("restricted"); + List observations = + List.of( + observation(visible, "pass", "Accuracy", TestCaseStatus.Success, 100L), + observation(restricted, "fail", "Accuracy", TestCaseStatus.Failed, 200L)); + + MetricObservability result = + MetricObservabilityBuilder.summarize( + metric(), + linked(visible, restricted), + List.of(visible, restricted), + observations, + List.of(), + Set.of(visible.getId()), + Set.of(visible.getId())); + + assertEquals(50.0, result.getScore()); + assertEquals(2, result.getStatusCounts().getTerminal()); + assertEquals(1, result.getAssets().size()); + assertEquals(visible.getId(), result.getAssets().getFirst().getAsset().getId()); + assertEquals(1, result.getTests().size()); + assertTrue(result.getPartial()); + assertTrue(result.getSourceCoverage().getPartial()); + assertEquals(1, result.getSourceCoverage().getRestrictedTables()); + assertEquals(MetricObservabilityReasonCode.PARTIAL_DETAILS, result.getReasonCode()); + } + + @Test + void summarize_exposesVisibleLinkedAssetsButScoresOnlyUpstreamTables() { + EntityReference upstream = table("upstream"); + EntityReference downstream = table("downstream"); + MetricAssetDirection upstreamLink = link(upstream, MetricAssetDirection.Direction.UPSTREAM); + MetricAssetDirection downstreamLink = + link(downstream, MetricAssetDirection.Direction.DOWNSTREAM); + + MetricObservability result = + MetricObservabilityBuilder.summarize( + metric(), + List.of(upstreamLink, downstreamLink), + List.of(upstream), + List.of(observation(upstream, "pass", "Accuracy", TestCaseStatus.Success, 100L)), + List.of(), + Set.of(upstream.getId()), + Set.of(upstream.getId(), downstream.getId())); + + assertEquals(100.0, result.getScore()); + assertEquals(2, result.getLinkedAssets().size()); + assertTrue( + result.getLinkedAssets().stream().anyMatch(link -> link.getAsset().equals(downstream))); + assertEquals(1, result.getAssets().size()); + } + + @Test + void summarize_withoutTerminalResultsIsUnknownInsteadOfDegraded() { + EntityReference source = table("source"); + MetricObservability result = + MetricObservabilityBuilder.summarize( + metric(), + linked(source), + List.of(source), + List.of( + observation(source, "queued", "Accuracy", TestCaseStatus.Queued, 100L), + observation(source, "missing", "Accuracy", null, null)), + List.of(), + Set.of(source.getId())); + + assertNull(result.getScore()); + assertEquals(MetricHealth.UNKNOWN, result.getHealth()); + assertEquals(MetricObservabilityReasonCode.NO_TERMINAL_RESULTS, result.getReasonCode()); + assertEquals(0, result.getStatusCounts().getTerminal()); + assertEquals(0, result.getDimensions().size()); + MetricAssetRollup sourceRollup = result.getAssets().getFirst(); + assertNull(sourceRollup.getScore()); + assertFalse(sourceRollup.getRedacted()); + } + + @Test + void summarize_treatsAResultWithoutStatusAsMissing() { + EntityReference source = table("source"); + TestCase testCase = + new TestCase() + .withId(UUID.randomUUID()) + .withName("missing_status") + .withFullyQualifiedName("source.missing_status"); + ResultSummary resultWithoutStatus = new ResultSummary().withTimestamp(100L); + + MetricObservability result = + MetricObservabilityBuilder.summarize( + metric(), + linked(source), + List.of(source), + List.of( + new MetricObservabilityBuilder.Observation( + source, testCase, "Accuracy", resultWithoutStatus)), + List.of(), + Set.of(source.getId())); + + assertEquals(1, result.getStatusCounts().getMissing()); + assertEquals(0, result.getStatusCounts().getTerminal()); + assertNull(result.getTests().getFirst().getStatus()); + assertEquals(100L, result.getTests().getFirst().getTimestamp()); + assertEquals(MetricObservabilityReasonCode.NO_TERMINAL_RESULTS, result.getReasonCode()); + } + + private EntityReference metric() { + return new EntityReference() + .withId(UUID.randomUUID()) + .withType("metric") + .withName("metric") + .withFullyQualifiedName("metric"); + } + + private EntityReference table(String name) { + return new EntityReference() + .withId(UUID.randomUUID()) + .withType("table") + .withName(name) + .withFullyQualifiedName(name); + } + + private List linked(EntityReference... assets) { + return List.of(assets).stream() + .map(asset -> link(asset, MetricAssetDirection.Direction.UPSTREAM)) + .toList(); + } + + private MetricAssetDirection link( + EntityReference asset, MetricAssetDirection.Direction direction) { + return new MetricAssetDirection() + .withAsset(asset) + .withDirection(direction) + .withAffectsHealth( + "table".equals(asset.getType()) + && MetricAssetDirection.Direction.UPSTREAM.equals(direction)); + } + + private MetricObservabilityBuilder.Observation observation( + EntityReference asset, String name, String dimension, TestCaseStatus status, Long timestamp) { + TestCase testCase = + new TestCase() + .withId(UUID.randomUUID()) + .withName(name) + .withFullyQualifiedName(asset.getFullyQualifiedName() + "." + name); + ResultSummary summary = + status == null ? null : new ResultSummary().withStatus(status).withTimestamp(timestamp); + return new MetricObservabilityBuilder.Observation(asset, testCase, dimension, summary); + } + + private ResultSummary invokeLatestResult( + MetricObservabilityBuilder builder, String testCaseFqn, List summaries) + throws Exception { + Method latestFor = + MetricObservabilityBuilder.class.getDeclaredMethod("latestFor", String.class, List.class); + latestFor.setAccessible(true); + return (ResultSummary) latestFor.invoke(builder, testCaseFqn, summaries); + } + + @SuppressWarnings("unchecked") + private Map invokeActiveTestCases( + MetricObservabilityBuilder builder, Set testCaseIds) throws Exception { + Method activeTestCases = + MetricObservabilityBuilder.class.getDeclaredMethod("activeTestCases", Set.class); + activeTestCases.setAccessible(true); + return (Map) activeTestCases.invoke(builder, testCaseIds); + } + + private TestCaseResolutionStatus resolutionStatus( + UUID stateId, TestCaseResolutionStatusTypes status, Severity severity, long timestamp) { + return new TestCaseResolutionStatus() + .withStateId(stateId) + .withTestCaseResolutionStatusType(status) + .withSeverity(severity) + .withTimestamp(timestamp); + } + + private CollectionDAO.LatestRecordWithFQNHash incidentRecord( + MetricObservabilityBuilder.Observation observation, TestCaseResolutionStatus status) { + return new CollectionDAO.LatestRecordWithFQNHash( + FullyQualifiedName.buildHash(observation.testCase().getFullyQualifiedName()), + JsonUtils.pojoToJson(status)); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricRepositoryTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricRepositoryTest.java new file mode 100644 index 000000000000..1567dcdf5c20 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/MetricRepositoryTest.java @@ -0,0 +1,429 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.api.data.MetricAssetDirection; +import org.openmetadata.schema.api.data.MetricHierarchyItem; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.EntityStatus; +import org.openmetadata.schema.type.Relationship; +import org.openmetadata.service.Entity; +import org.openmetadata.service.util.EntityUtil.Fields; + +class MetricRepositoryTest { + + @Test + void referenceComparisonHandlesNullableParentAndGroupIdentity() { + UUID groupId = UUID.randomUUID(); + EntityReference group = new EntityReference().withId(groupId).withType(Entity.METRIC_GROUP); + EntityReference sameGroup = + new EntityReference().withId(groupId).withType(Entity.METRIC_GROUP).withName("renamed"); + EntityReference otherGroup = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC_GROUP); + + assertTrue(MetricRepository.sameReferenceById(null, null)); + assertTrue(MetricRepository.sameReferenceById(group, group)); + assertTrue(MetricRepository.sameReferenceById(group, sameGroup)); + assertFalse(MetricRepository.sameReferenceById(group, null)); + assertFalse(MetricRepository.sameReferenceById(null, group)); + assertFalse(MetricRepository.sameReferenceById(group, otherGroup)); + } + + @Test + void childMetricsAlwaysInheritTheirParentGroup() { + EntityReference parent = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC); + EntityReference requestedGroup = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC_GROUP); + EntityReference inheritedGroup = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC_GROUP); + + assertEquals( + inheritedGroup, + MetricRepository.effectiveHierarchyGroup(parent, requestedGroup, inheritedGroup)); + assertEquals( + requestedGroup, + MetricRepository.effectiveHierarchyGroup(null, requestedGroup, inheritedGroup)); + } + + @Test + void selfParentIsRejectedBeforeTheUnpersistedParentReferenceIsResolved() { + Metric metric = + new Metric() + .withName("revenue") + .withFullyQualifiedName("revenue") + .withParent( + new EntityReference().withType(Entity.METRIC).withFullyQualifiedName("revenue")); + + IllegalArgumentException error = + org.junit.jupiter.api.Assertions.assertThrows( + IllegalArgumentException.class, + () -> MetricRepository.validateSelfParentReference(metric)); + + assertTrue(error.getMessage().contains("cannot be its own parent")); + } + + @Test + void directHierarchyCycleIsRejected() throws NoSuchMethodException { + UUID metricId = UUID.randomUUID(); + UUID parentId = UUID.randomUUID(); + try (RepositoryFixture fixture = repositoryFixture()) { + when(fixture + .relationshipDAO() + .findFrom(parentId, Entity.METRIC, Relationship.CONTAINS.ordinal(), Entity.METRIC)) + .thenReturn(List.of(relationship(metricId))); + + IllegalArgumentException error = + invokeHierarchyValidation(fixture.repository(), metric(metricId, parentId)); + + assertTrue(error.getMessage().contains("Circular reference detected")); + } + } + + @Test + void transitiveHierarchyCycleIsRejected() throws NoSuchMethodException { + UUID metricId = UUID.randomUUID(); + UUID parentId = UUID.randomUUID(); + UUID ancestorId = UUID.randomUUID(); + try (RepositoryFixture fixture = repositoryFixture()) { + when(fixture + .relationshipDAO() + .findFrom(parentId, Entity.METRIC, Relationship.CONTAINS.ordinal(), Entity.METRIC)) + .thenReturn(List.of(relationship(ancestorId))); + when(fixture + .relationshipDAO() + .findFrom(ancestorId, Entity.METRIC, Relationship.CONTAINS.ordinal(), Entity.METRIC)) + .thenReturn(List.of(relationship(metricId))); + + IllegalArgumentException error = + invokeHierarchyValidation(fixture.repository(), metric(metricId, parentId)); + + assertTrue(error.getMessage().contains("Circular reference detected")); + } + } + + @Test + void defaultStatusReflectsReviewersAndPreservesExplicitUpdates() { + try (RepositoryFixture fixture = repositoryFixture()) { + Metric withoutReviewers = new Metric(); + Metric withReviewers = + new Metric() + .withReviewers( + List.of( + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.USER) + .withName("reviewer"))); + Metric explicitUpdate = new Metric().withEntityStatus(EntityStatus.IN_REVIEW); + + fixture.repository().setDefaultStatus(withoutReviewers, false); + fixture.repository().setDefaultStatus(withReviewers, false); + fixture.repository().setDefaultStatus(explicitUpdate, true); + + assertEquals(EntityStatus.APPROVED, withoutReviewers.getEntityStatus()); + assertEquals(EntityStatus.DRAFT, withReviewers.getEntityStatus()); + assertEquals(EntityStatus.IN_REVIEW, explicitUpdate.getEntityStatus()); + } + } + + @Test + void hierarchyItemCarriesExactlyOneTypedPayload() { + UUID metricId = UUID.randomUUID(); + UUID groupId = UUID.randomUUID(); + Metric metric = new Metric().withId(metricId).withName("revenue"); + MetricGroup group = new MetricGroup().withId(groupId).withName("profitability"); + + MetricHierarchyItem metricItem = + MetricRepository.toHierarchyItem( + new CollectionDAO.MetricDAO.HierarchyRow(metricId, Entity.METRIC), + Map.of(metricId, metric), + Map.of(groupId, group)); + MetricHierarchyItem groupItem = + MetricRepository.toHierarchyItem( + new CollectionDAO.MetricDAO.HierarchyRow(groupId, Entity.METRIC_GROUP), + Map.of(metricId, metric), + Map.of(groupId, group)); + + assertEquals(MetricHierarchyItem.Kind.METRIC, metricItem.getKind()); + assertNotNull(metricItem.getMetric()); + assertNull(metricItem.getGroup()); + assertEquals(MetricHierarchyItem.Kind.METRIC_GROUP, groupItem.getKind()); + assertNotNull(groupItem.getGroup()); + assertNull(groupItem.getMetric()); + } + + @Test + void unrestrictedHierarchyPagingUsesOneBoundedPageAndCountQuery() { + UUID metricId = UUID.randomUUID(); + List rows = + List.of(new CollectionDAO.MetricDAO.HierarchyRow(metricId, Entity.METRIC)); + try (RepositoryFixture fixture = repositoryFixture()) { + when(fixture + .metricDAO() + .listHierarchy( + Relationship.CONTAINS.ordinal(), Relationship.HAS.ordinal(), "%margin%", 25, 50)) + .thenReturn(rows); + when(fixture + .metricDAO() + .countHierarchy( + Relationship.CONTAINS.ordinal(), Relationship.HAS.ordinal(), "%margin%")) + .thenReturn(12_345); + + MetricRepository.HierarchyScan scan = + fixture.repository().scanUnrestrictedHierarchyRows(25, 50, "%margin%"); + + assertEquals(rows, scan.rows()); + assertEquals(12_345, scan.total()); + verify(fixture.metricDAO()) + .listHierarchy( + Relationship.CONTAINS.ordinal(), Relationship.HAS.ordinal(), "%margin%", 25, 50); + verify(fixture.metricDAO()) + .countHierarchy(Relationship.CONTAINS.ordinal(), Relationship.HAS.ordinal(), "%margin%"); + } + } + + @Test + void assetDirectionUsesGenericLineageSetsWithUpstreamPrecedence() { + UUID assetId = UUID.randomUUID(); + + assertEquals( + MetricAssetDirection.Direction.UPSTREAM, + MetricRepository.assetDirection(assetId, Set.of(assetId), Set.of(assetId))); + assertEquals( + MetricAssetDirection.Direction.DOWNSTREAM, + MetricRepository.assetDirection(assetId, Set.of(), Set.of(assetId))); + assertEquals( + MetricAssetDirection.Direction.UNRELATED, + MetricRepository.assetDirection(assetId, Set.of(), Set.of())); + } + + @Test + void observabilityRejectsLinkedAssetSetsAboveTheExplicitDetailLimit() { + UUID metricId = UUID.randomUUID(); + try (RepositoryFixture fixture = repositoryFixture()) { + when(fixture + .relationshipDAO() + .countFindTo(metricId, Entity.METRIC, List.of(Relationship.APPLIED_TO.ordinal()))) + .thenReturn(MetricRepository.MAX_OBSERVABILITY_ASSET_DETAILS + 1); + + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> fixture.repository().getAssetsWithDirection(metricId)); + + assertTrue(exception.getMessage().contains("paginated /assets endpoint")); + verify(fixture.relationshipDAO(), never()) + .findToWithOffset( + metricId, Entity.METRIC, List.of(Relationship.APPLIED_TO.ordinal()), 0, 200); + } + } + + @Test + void hierarchySearchEscapesSqlWildcards() { + assertEquals("%margin!!!%!_net%", MetricGroupRepository.buildNameLike("Margin!%_Net")); + assertEquals("%", MetricGroupRepository.buildNameLike(" ")); + } + + @Test + void metricCsvContractIncludesExpertsAndMetricGroupAfterExistingColumns() { + List headers = + MetricRepository.MetricCsv.HEADERS.stream().map(header -> header.getName()).toList(); + + assertEquals("parent", headers.get(headers.size() - 3)); + assertEquals("experts", headers.get(headers.size() - 2)); + assertEquals("metricGroup", headers.getLast()); + } + + @Test + void hierarchyPayloadSanitizationRemovesRestrictedEmbeddedReferencesWithoutMutatingSource() { + EntityReference hiddenParent = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC) + .withName("restricted_parent") + .withFullyQualifiedName("restricted_parent"); + EntityReference hiddenGroup = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC_GROUP) + .withName("restricted_group") + .withFullyQualifiedName("restricted_group"); + Metric source = + new Metric() + .withId(UUID.randomUUID()) + .withName("visible_metric") + .withParent(hiddenParent) + .withMetricGroup(hiddenGroup); + + Metric sanitized = + MetricRepository.sanitizeHierarchyMetric(source, ignored -> false, ignored -> false); + + assertNull(sanitized.getParent()); + assertNull(sanitized.getMetricGroup()); + assertNotNull(source.getParent()); + assertNotNull(source.getMetricGroup()); + } + + @Test + void hierarchyReferenceSearchMatchesNamesAndDisplayNamesLiterally() { + EntityReference reference = + new EntityReference().withName("gross_margin").withDisplayName("Gross Margin %"); + + assertEquals(true, MetricGroupRepository.referenceMatchesQuery(reference, "MARGIN")); + assertEquals(true, MetricGroupRepository.referenceMatchesQuery(reference, "%")); + assertEquals(false, MetricGroupRepository.referenceMatchesQuery(reference, "revenue")); + } + + @Test + void hierarchyAggregateCountsIncludeOnlyVisibleReferences() { + EntityReference visible = new EntityReference().withId(UUID.randomUUID()); + EntityReference restricted = new EntityReference().withId(UUID.randomUUID()); + + int count = + MetricRepository.countVisibleReferences( + List.of(restricted, visible), reference -> reference.getId().equals(visible.getId())); + + assertEquals(1, count); + } + + @Test + void childrenCountSingleHydrationUsesTheNonDeletedRelationshipCount() { + Metric parent = new Metric().withId(UUID.randomUUID()).withName("parent"); + try (RepositoryFixture fixture = repositoryFixture()) { + when(fixture + .relationshipDAO() + .countNonDeletedChildMetrics(parent.getId(), Relationship.CONTAINS.ordinal())) + .thenReturn(3); + + fixture.repository().setFields(parent, new Fields(Set.of("childrenCount")), null); + + assertEquals(3, parent.getChildrenCount()); + } + } + + @Test + void childrenCountBulkHydrationDefaultsMissingParentsToZero() { + Metric parentWithChildren = + new Metric().withId(UUID.randomUUID()).withName("parent_with_children"); + Metric leaf = new Metric().withId(UUID.randomUUID()).withName("leaf"); + try (RepositoryFixture fixture = repositoryFixture()) { + when(fixture + .relationshipDAO() + .countNonDeletedChildMetricsBatch( + List.of(parentWithChildren.getId().toString(), leaf.getId().toString()), + Relationship.CONTAINS.ordinal())) + .thenReturn( + List.of( + CollectionDAO.EntityRelationshipCount.builder() + .id(parentWithChildren.getId()) + .count(2) + .build())); + + fixture + .repository() + .setFieldsInBulk(new Fields(Set.of("childrenCount")), List.of(parentWithChildren, leaf)); + + assertEquals(2, parentWithChildren.getChildrenCount()); + assertEquals(0, leaf.getChildrenCount()); + } + } + + @Test + void metricWritesUseTheActiveTransactionDAOAndRestoreTheDefaultDAOAfterward() { + try (RepositoryFixture fixture = repositoryFixture()) { + CollectionDAO transactionDAO = mock(CollectionDAO.class); + CollectionDAO.MetricDAO transactionMetricDAO = mock(CollectionDAO.MetricDAO.class); + when(transactionDAO.metricDAO()).thenReturn(transactionMetricDAO); + + assertSame(fixture.metricDAO(), fixture.repository().entityDAOForWrite()); + RepositoryTransactionContext.runWith( + transactionDAO, + () -> assertSame(transactionMetricDAO, fixture.repository().entityDAOForWrite())); + assertSame(fixture.metricDAO(), fixture.repository().entityDAOForWrite()); + } + } + + private RepositoryFixture repositoryFixture() { + CollectionDAO collectionDAO = mock(CollectionDAO.class); + CollectionDAO.MetricDAO metricDAO = mock(CollectionDAO.MetricDAO.class); + CollectionDAO.EntityRelationshipDAO relationshipDAO = + mock(CollectionDAO.EntityRelationshipDAO.class); + when(collectionDAO.metricDAO()).thenReturn(metricDAO); + when(collectionDAO.relationshipDAO()).thenReturn(relationshipDAO); + Entity.setCollectionDAO(collectionDAO); + return new RepositoryFixture(new MetricRepository(), metricDAO, relationshipDAO); + } + + private Metric metric(UUID metricId, UUID parentId) { + return new Metric() + .withId(metricId) + .withName("revenue") + .withFullyQualifiedName("revenue") + .withParent( + new EntityReference() + .withId(parentId) + .withType(Entity.METRIC) + .withName("parent") + .withFullyQualifiedName("parent")); + } + + private CollectionDAO.EntityRelationshipRecord relationship(UUID ancestorId) { + return CollectionDAO.EntityRelationshipRecord.builder() + .id(ancestorId) + .type(Entity.METRIC) + .build(); + } + + private IllegalArgumentException invokeHierarchyValidation( + MetricRepository repository, Metric metric) throws NoSuchMethodException { + Method validation = MetricRepository.class.getDeclaredMethod("validateHierarchy", Metric.class); + validation.setAccessible(true); + InvocationTargetException invocation = + assertThrows(InvocationTargetException.class, () -> validation.invoke(repository, metric)); + return assertInstanceOf(IllegalArgumentException.class, invocation.getCause()); + } + + private record RepositoryFixture( + MetricRepository repository, + CollectionDAO.MetricDAO metricDAO, + CollectionDAO.EntityRelationshipDAO relationshipDAO) + implements AutoCloseable { + @Override + public void close() { + Entity.cleanup(); + } + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/RepositoryTransactionContextTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/RepositoryTransactionContextTest.java new file mode 100644 index 000000000000..b113ef6c1f10 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/RepositoryTransactionContextTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.jdbi3; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; + +import org.junit.jupiter.api.Test; + +class RepositoryTransactionContextTest { + + @Test + void restoresThePreviousContextAfterNestedScopesAndFailures() { + CollectionDAO outerDAO = mock(CollectionDAO.class); + CollectionDAO innerDAO = mock(CollectionDAO.class); + + RepositoryTransactionContext.runWith( + outerDAO, + () -> { + assertSame(outerDAO, RepositoryTransactionContext.currentDAO()); + assertSame(outerDAO, RepositoryTransactionContext.requireCurrentDAO()); + assertThrows( + IllegalStateException.class, + () -> + RepositoryTransactionContext.runWith( + innerDAO, + () -> { + assertSame(innerDAO, RepositoryTransactionContext.currentDAO()); + assertSame(innerDAO, RepositoryTransactionContext.requireCurrentDAO()); + throw new IllegalStateException("mutation failed"); + })); + assertSame(outerDAO, RepositoryTransactionContext.requireCurrentDAO()); + }); + + assertNull(RepositoryTransactionContext.currentDAO()); + assertThrows(IllegalStateException.class, RepositoryTransactionContext::requireCurrentDAO); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/WorkflowDefinitionGraphValidationTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/WorkflowDefinitionGraphValidationTest.java index 58a390800f80..48665f611483 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/WorkflowDefinitionGraphValidationTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/WorkflowDefinitionGraphValidationTest.java @@ -13,6 +13,8 @@ package org.openmetadata.service.jdbi3; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mockStatic; @@ -24,6 +26,8 @@ import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.openmetadata.schema.governance.workflows.WorkflowDefinition; +import org.openmetadata.schema.governance.workflows.elements.WorkflowNodeDefinitionInterface; +import org.openmetadata.schema.governance.workflows.elements.nodes.automatedTask.SetEntityAttributeTaskDefinition; import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.service.Entity; @@ -37,6 +41,8 @@ class WorkflowDefinitionGraphValidationTest { private static final String INCIDENT_WORKFLOW = "json/data/governance/workflows/TestCaseResolutionTaskWorkflow.json"; + private static final String METRIC_APPROVAL_WORKFLOW = + "json/data/governance/workflows/MetricApprovalWorkflow.json"; @Test void cyclicStateMachineWorkflowPassesGraphValidation() throws Exception { @@ -66,6 +72,42 @@ void expiryTimerTransitionIdCountsAsDeclaredTransition() throws Exception { "expiryTimer.transitionId should be treated as a declared transition"); } + @Test + void metricApprovalWorkflowSeedPassesGraphValidation() throws Exception { + WorkflowDefinition workflow = loadWorkflow(METRIC_APPROVAL_WORKFLOW); + + assertDoesNotThrow( + () -> validateGraph(workflow), + "the shipped Metric approval workflow must be deployable during seed bootstrap"); + assertTrue( + workflow.getNodes().stream() + .anyMatch(node -> "rollbackEntityTask".equals(node.getSubType())), + "update rejection must retain the rollback task"); + assertEdge(workflow, "ApproveMetric", "SetMetricStatusToRejected", "reject"); + assertEdge(workflow, "ApprovalForUpdates", "RollbackMetricChanges", "reject"); + + WorkflowNodeDefinitionInterface rejectionNode = + workflow.getNodes().stream() + .filter(node -> "SetMetricStatusToRejected".equals(node.getName())) + .findFirst() + .orElseThrow(); + SetEntityAttributeTaskDefinition rejectionTask = + assertInstanceOf(SetEntityAttributeTaskDefinition.class, rejectionNode); + assertEquals("status", rejectionTask.getConfig().getFieldName()); + assertEquals("Rejected", rejectionTask.getConfig().getFieldValue()); + } + + private void assertEdge(WorkflowDefinition workflow, String from, String to, String condition) { + assertTrue( + workflow.getEdges().stream() + .anyMatch( + edge -> + from.equals(edge.getFrom()) + && to.equals(edge.getTo()) + && condition.equals(edge.getCondition())), + () -> "expected workflow edge " + from + " -> " + to + " on " + condition); + } + private static final String EXPIRY_TIMER_WORKFLOW_JSON = """ { diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricGroupResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricGroupResourceTest.java new file mode 100644 index 000000000000..f3475ca79283 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricGroupResourceTest.java @@ -0,0 +1,380 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.resources.metrics; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.SecurityContext; +import java.lang.reflect.Method; +import java.security.Principal; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.mockito.InOrder; +import org.mockito.MockedStatic; +import org.openmetadata.schema.api.data.RestoreEntity; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.ApiStatus; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.EventType; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.schema.type.Paging; +import org.openmetadata.schema.type.Permission; +import org.openmetadata.schema.type.ResourcePermission; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; +import org.openmetadata.schema.utils.ResultList; +import org.openmetadata.service.Entity; +import org.openmetadata.service.jdbi3.MetricGroupRepository; +import org.openmetadata.service.limits.Limits; +import org.openmetadata.service.security.Authorizer; +import org.openmetadata.service.util.RestUtil.DeleteResponse; +import org.openmetadata.service.util.RestUtil.PutResponse; + +class MetricGroupResourceTest { + + @Test + void deleteByIdRefreshesMembersAfterTheDeleteCommits() { + UUID groupId = UUID.randomUUID(); + MetricGroup snapshot = groupWithMember(groupId, "profitability"); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().getWithMembers(groupId, Include.ALL)).thenReturn(snapshot); + when(fixture.repository().delete("alice", groupId, false, false)) + .thenReturn( + new DeleteResponse<>(snapshot.withDeleted(true), EventType.ENTITY_SOFT_DELETED)); + + Response response = fixture.resource().delete(null, securityContext("alice"), false, groupId); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + InOrder lifecycle = inOrder(fixture.repository()); + lifecycle.verify(fixture.repository()).getWithMembers(groupId, Include.ALL); + lifecycle.verify(fixture.repository()).delete("alice", groupId, false, false); + lifecycle.verify(fixture.repository()).refreshMembersAfterGroupLifecycle(snapshot); + } + } + + @Test + void deleteByNameRefreshesMembersAfterTheDeleteCommits() { + String groupName = "profitability"; + MetricGroup snapshot = groupWithMember(UUID.randomUUID(), groupName); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().getByNameWithMembers(groupName, Include.ALL)).thenReturn(snapshot); + when(fixture.repository().deleteByName("alice", groupName, false, false)) + .thenReturn( + new DeleteResponse<>(snapshot.withDeleted(true), EventType.ENTITY_SOFT_DELETED)); + + Response response = + fixture.resource().delete(null, securityContext("alice"), false, groupName); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + InOrder lifecycle = inOrder(fixture.repository()); + lifecycle.verify(fixture.repository()).getByNameWithMembers(groupName, Include.ALL); + lifecycle.verify(fixture.repository()).deleteByName("alice", groupName, false, false); + lifecycle.verify(fixture.repository()).refreshMembersAfterGroupLifecycle(snapshot); + } + } + + @Test + void restoreDelegatesMemberRefreshToThePostCommitRepositoryHook() { + UUID groupId = UUID.randomUUID(); + MetricGroup restored = groupWithMember(groupId, "profitability").withDeleted(false); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().restoreEntity("alice", groupId)) + .thenReturn(new PutResponse<>(Response.Status.OK, restored, EventType.ENTITY_RESTORED)); + + Response response = + fixture + .resource() + .restore(null, securityContext("alice"), new RestoreEntity().withId(groupId)); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + InOrder lifecycle = inOrder(fixture.repository()); + lifecycle.verify(fixture.repository()).restoreEntity("alice", groupId); + lifecycle.verify(fixture.repository()).restoreFromSearch(restored); + verify(fixture.repository(), never()) + .refreshMembersAfterGroupLifecycle(any(MetricGroup.class)); + } + } + + @Test + void memberListPreservesSearchRootFilterAndOffsetPaging() { + UUID groupId = UUID.randomUUID(); + MetricGroup group = + new MetricGroup() + .withId(groupId) + .withName("profitability") + .withFullyQualifiedName("profitability"); + ResultList expected = + new ResultList<>(List.of(), new Paging().withLimit(15).withOffset(30).withTotal(0)); + try (ResourceFixture fixture = resourceFixture()) { + SecurityContext securityContext = securityContext("alice"); + when(fixture.repository().get(any(), eq(groupId), any())).thenReturn(group); + when(fixture.authorizer().getPermission(securityContext, "alice", Entity.METRIC)) + .thenReturn(metricViewPermission(Permission.Access.CONDITIONAL_ALLOW)); + when(fixture + .repository() + .listMetrics(eq(groupId), eq(15), eq(30), eq("margin"), eq(true), any())) + .thenReturn(expected); + + ResultList actual = + fixture.resource().listMetrics(securityContext, groupId, "margin", true, 15, 30); + + assertEquals(expected, actual); + verify(fixture.authorizer()).authorize(any(), any(), any()); + verify(fixture.repository()) + .listMetrics(eq(groupId), eq(15), eq(30), eq("margin"), eq(true), any()); + } + } + + @Test + void memberListUsesDatabasePagingForUnconditionalMetricVisibility() { + UUID groupId = UUID.randomUUID(); + MetricGroup group = + new MetricGroup() + .withId(groupId) + .withName("profitability") + .withFullyQualifiedName("profitability"); + ResultList expected = + new ResultList<>(List.of(), new Paging().withLimit(15).withOffset(30).withTotal(0)); + try (ResourceFixture fixture = resourceFixture()) { + SecurityContext securityContext = securityContext("alice"); + when(fixture.repository().get(any(), eq(groupId), any())).thenReturn(group); + when(fixture.authorizer().getPermission(securityContext, "alice", Entity.METRIC)) + .thenReturn(metricViewPermission(Permission.Access.ALLOW)); + when(fixture.repository().listMetrics(groupId, 15, 30, "margin", false)).thenReturn(expected); + + ResultList actual = + fixture.resource().listMetrics(securityContext, groupId, "margin", false, 15, 30); + + assertEquals(expected, actual); + verify(fixture.repository()).listMetrics(groupId, 15, 30, "margin", false); + verify(fixture.repository(), never()) + .listMetrics(eq(groupId), eq(15), eq(30), eq("margin"), eq(false), any()); + } + } + + @Test + void genericMetricGroupResponsesNeverExposeEmbeddedMembers() { + MetricGroup group = groupWithMember(UUID.randomUUID(), "profitability"); + Response response = Response.ok(group).build(); + + Response sanitized = MetricGroupResource.withoutMembers(response); + + assertEquals(response, sanitized); + assertNull(((MetricGroup) sanitized.getEntity()).getMetrics()); + } + + @Test + void memberPagingParametersRejectNegativeOffsetsAndZeroLimits() throws Exception { + Method method = + MetricGroupResource.class.getMethod( + "listMetrics", + SecurityContext.class, + UUID.class, + String.class, + boolean.class, + int.class, + int.class); + Min limit = + Arrays.stream(method.getParameterAnnotations()[4]) + .filter(Min.class::isInstance) + .map(Min.class::cast) + .findFirst() + .orElseThrow(); + Min offset = + Arrays.stream(method.getParameterAnnotations()[5]) + .filter(Min.class::isInstance) + .map(Min.class::cast) + .findFirst() + .orElseThrow(); + + assertEquals(1, limit.value()); + assertEquals(0, offset.value()); + } + + @Test + void bulkMembershipResponseMapsFailureAndPartialSuccess() { + try (ResourceFixture fixture = resourceFixture()) { + BulkOperationResult failure = + new BulkOperationResult().withStatus(ApiStatus.FAILURE).withNumberOfRowsFailed(1); + BulkOperationResult partial = + new BulkOperationResult() + .withStatus(ApiStatus.PARTIAL_SUCCESS) + .withNumberOfRowsPassed(1) + .withNumberOfRowsFailed(1); + + assertEquals( + Response.Status.BAD_REQUEST.getStatusCode(), + fixture.resource().buildBulkOperationResponse(failure).getStatus()); + assertEquals( + Response.Status.OK.getStatusCode(), + fixture.resource().buildBulkOperationResponse(partial).getStatus()); + } + } + + @Test + void metadataOnlyUpdatesDoNotRequireMemberAuthorization() { + EntityReference retained = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC).withName("margin"); + EntityReference removed = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC).withName("cost"); + EntityReference added = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC).withName("profit"); + MetricGroup original = new MetricGroup().withMetrics(List.of(retained, removed)); + MetricGroup metadataOnly = new MetricGroup().withMetrics(List.of(retained, removed)); + MetricGroup membershipUpdate = new MetricGroup().withMetrics(List.of(retained, added)); + + assertEquals(List.of(), MetricGroupResource.membershipMutationTargets(original, metadataOnly)); + assertEquals( + Set.of(removed.getId(), added.getId()), + MetricGroupResource.membershipMutationTargets(original, membershipUpdate).stream() + .map(EntityReference::getId) + .collect(java.util.stream.Collectors.toSet())); + } + + @Test + void bulkAddDelegatesTheCallerAndPreservesDryRun() { + String groupName = "profitability"; + EntityReference metric = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.METRIC).withName("margin"); + BulkAssets request = new BulkAssets().withAssets(List.of(metric)).withDryRun(true); + BulkOperationResult expected = + new BulkOperationResult().withStatus(ApiStatus.SUCCESS).withDryRun(true); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().getByName(any(), eq(groupName), any())) + .thenReturn( + new MetricGroup() + .withId(UUID.randomUUID()) + .withName(groupName) + .withFullyQualifiedName(groupName)); + when(fixture.repository().hierarchySubtree(metric)).thenReturn(List.of(metric)); + when(fixture + .repository() + .bulkAddMetrics( + eq(groupName), + argThat( + authorized -> + Boolean.TRUE.equals(authorized.getDryRun()) + && authorized.getAssets().equals(List.of(metric))), + eq("alice"))) + .thenReturn(expected); + + Response response = + fixture.resource().bulkAddMetrics(null, securityContext("alice"), groupName, request); + + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + assertEquals(expected, response.getEntity()); + verify(fixture.repository()) + .bulkAddMetrics( + eq(groupName), + argThat( + authorized -> + Boolean.TRUE.equals(authorized.getDryRun()) + && authorized.getAssets().equals(List.of(metric))), + eq("alice")); + } + } + + @Test + void constructorRegistersTheMetricGroupEntityContract() { + try (ResourceFixture fixture = resourceFixture()) { + fixture.entity().verify(() -> Entity.getEntityRepository(Entity.METRIC_GROUP)); + fixture.entity().verify(() -> Entity.getEntityClassFromType(Entity.METRIC_GROUP)); + fixture + .entity() + .verify(() -> Entity.registerResourcePermissions(Entity.METRIC_GROUP, List.of())); + assertNotNull(fixture.resource()); + } + } + + private SecurityContext securityContext(String name) { + Principal principal = mock(Principal.class); + when(principal.getName()).thenReturn(name); + SecurityContext context = mock(SecurityContext.class); + when(context.getUserPrincipal()).thenReturn(principal); + return context; + } + + private MetricGroup groupWithMember(UUID id, String name) { + EntityReference member = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC) + .withName("margin") + .withFullyQualifiedName("margin"); + return new MetricGroup() + .withId(id) + .withName(name) + .withFullyQualifiedName(name) + .withMetrics(List.of(member)); + } + + private ResourcePermission metricViewPermission(Permission.Access access) { + return new ResourcePermission() + .withResource(Entity.METRIC) + .withPermissions( + List.of( + new Permission().withOperation(MetadataOperation.VIEW_BASIC).withAccess(access))); + } + + private ResourceFixture resourceFixture() { + MockedStatic entity = mockStatic(Entity.class); + MetricGroupRepository repository = mock(MetricGroupRepository.class); + Authorizer authorizer = mock(Authorizer.class); + when(repository.getAllowedFields()).thenReturn(Set.of("id", "metricCount")); + when(repository.getFields(anyString())) + .thenReturn(org.openmetadata.service.util.EntityUtil.Fields.EMPTY_FIELDS); + entity.when(() -> Entity.getEntityRepository(Entity.METRIC_GROUP)).thenReturn(repository); + entity + .when(() -> Entity.getEntityClassFromType(Entity.METRIC_GROUP)) + .thenReturn(MetricGroup.class); + try { + return new ResourceFixture( + new MetricGroupResource(authorizer, mock(Limits.class)), repository, authorizer, entity); + } catch (RuntimeException exception) { + entity.close(); + throw exception; + } + } + + private record ResourceFixture( + MetricGroupResource resource, + MetricGroupRepository repository, + Authorizer authorizer, + MockedStatic entity) + implements AutoCloseable { + @Override + public void close() { + entity.close(); + } + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricMapperTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricMapperTest.java new file mode 100644 index 000000000000..a3868b8bbe47 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricMapperTest.java @@ -0,0 +1,140 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.resources.metrics; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Answers.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mockStatic; + +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.openmetadata.schema.api.data.CreateMetric; +import org.openmetadata.schema.api.data.CreateMetricGroup; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.service.Entity; + +class MetricMapperTest { + + @Test + void metricMapperCarriesParentAndGroupReferences() { + Metric metric = + new MetricMapper() + .createToEntity( + new CreateMetric() + .withName("netRevenue") + .withParent("revenue") + .withMetricGroup("profitability"), + "admin"); + + assertNotNull(metric.getParent()); + assertEquals(Entity.METRIC, metric.getParent().getType()); + assertEquals("revenue", metric.getParent().getFullyQualifiedName()); + assertNotNull(metric.getMetricGroup()); + assertEquals(Entity.METRIC_GROUP, metric.getMetricGroup().getType()); + assertEquals("profitability", metric.getMetricGroup().getFullyQualifiedName()); + } + + @Test + void metricMapperPreservesDeprecatedCreateAssets() { + EntityReference table = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.TABLE) + .withFullyQualifiedName("service.database.schema.orders"); + + Metric metric = + new MetricMapper() + .createToEntity( + new CreateMetric().withName("orderCount").withAssets(List.of(table)), "admin"); + + assertEquals(List.of(table), metric.getAssets()); + } + + @Test + void metricMapperResolvesExpertsAsUserReferences() { + UUID expertId = UUID.randomUUID(); + EntityReference resolved = + new EntityReference() + .withId(expertId) + .withType(Entity.USER) + .withName("metricExpert") + .withFullyQualifiedName("metricExpert"); + try (MockedStatic entity = mockStatic(Entity.class, CALLS_REAL_METHODS)) { + entity + .when( + () -> + Entity.getEntityReferenceByName( + org.mockito.ArgumentMatchers.eq(Entity.USER), + org.mockito.ArgumentMatchers.eq("metricExpert"), + org.mockito.ArgumentMatchers.eq( + org.openmetadata.schema.type.Include.NON_DELETED))) + .thenReturn(resolved); + entity + .when( + () -> + Entity.getEntityReference( + org.mockito.ArgumentMatchers.any(EntityReference.class), + org.mockito.ArgumentMatchers.eq(org.openmetadata.schema.type.Include.ALL))) + .thenReturn(resolved); + + Metric metric = + new MetricMapper() + .createToEntity( + new CreateMetric().withName("netRevenue").withExperts(List.of("metricExpert")), + "admin"); + + assertEquals(1, metric.getExperts().size()); + assertEquals(expertId, metric.getExperts().getFirst().getId()); + assertEquals(Entity.USER, metric.getExperts().getFirst().getType()); + } + } + + @Test + void metricGroupMapperCreatesTypedMetricReferences() { + MetricGroup group = + new MetricGroupMapper() + .createToEntity( + new CreateMetricGroup() + .withName("profitability") + .withMetrics(List.of("grossMargin", "netRevenue")), + "admin"); + + assertEquals(2, group.getMetrics().size()); + assertEquals(Entity.METRIC, group.getMetrics().getFirst().getType()); + assertEquals("grossMargin", group.getMetrics().getFirst().getFullyQualifiedName()); + } + + @Test + void metricGroupMapperPreservesMetadataAndTreatsOmittedMembersAsUnset() { + MetricGroup group = + new MetricGroupMapper() + .createToEntity( + new CreateMetricGroup() + .withName("profitability") + .withDisplayName("Profitability Metrics") + .withDescription("Metrics for profit performance"), + "alice"); + + assertEquals("profitability", group.getName()); + assertEquals("Profitability Metrics", group.getDisplayName()); + assertEquals("alice", group.getUpdatedBy()); + assertNull(group.getMetrics()); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricResourceTest.java new file mode 100644 index 000000000000..ec2de703be3a --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/metrics/MetricResourceTest.java @@ -0,0 +1,508 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.resources.metrics; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import jakarta.json.Json; +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.SecurityContext; +import java.lang.reflect.Method; +import java.security.Principal; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedStatic; +import org.openmetadata.schema.api.data.MetricAssetDirection; +import org.openmetadata.schema.api.data.MetricHierarchyContext; +import org.openmetadata.schema.api.data.MetricHierarchyItem; +import org.openmetadata.schema.api.data.MetricObservability; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.policies.accessControl.Rule; +import org.openmetadata.schema.type.ApiStatus; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.schema.type.Paging; +import org.openmetadata.schema.type.Permission; +import org.openmetadata.schema.type.ResourcePermission; +import org.openmetadata.schema.type.api.BulkAssets; +import org.openmetadata.schema.type.api.BulkOperationResult; +import org.openmetadata.schema.type.api.BulkResponse; +import org.openmetadata.schema.utils.ResultList; +import org.openmetadata.service.Entity; +import org.openmetadata.service.exception.EntityNotFoundException; +import org.openmetadata.service.jdbi3.ListFilter; +import org.openmetadata.service.jdbi3.MetricRepository; +import org.openmetadata.service.limits.Limits; +import org.openmetadata.service.security.AuthorizationException; +import org.openmetadata.service.security.Authorizer; +import org.openmetadata.service.security.policyevaluator.OperationContext; +import org.openmetadata.service.security.policyevaluator.ResourceContextInterface; + +class MetricResourceTest { + + @Test + void hierarchyFilterDistinguishesAllRootsAndOneParentsChildren() { + UUID parentId = UUID.randomUUID(); + try (ResourceFixture fixture = resourceFixture()) { + fixture + .entity() + .when( + () -> Entity.getEntityReferenceByName(Entity.METRIC, "revenue", Include.NON_DELETED)) + .thenReturn( + new EntityReference() + .withId(parentId) + .withType(Entity.METRIC) + .withFullyQualifiedName("revenue")); + ListFilter all = new ListFilter(); + ListFilter roots = new ListFilter(); + ListFilter children = new ListFilter(); + + fixture.resource().addHierarchyFilter(all, null); + fixture.resource().addHierarchyFilter(roots, "null"); + fixture.resource().addHierarchyFilter(children, "revenue"); + + assertEquals(null, all.getQueryParam("rootMetrics")); + assertEquals("true", roots.getQueryParam("rootMetrics")); + assertEquals(parentId.toString(), children.getQueryParam("parentMetricId")); + } + } + + @Test + void hierarchyMutationDetectionUsesParentAndGroupIdentity() { + UUID parentId = UUID.randomUUID(); + UUID groupId = UUID.randomUUID(); + Metric original = + new Metric() + .withParent(new EntityReference().withId(parentId)) + .withMetricGroup(new EntityReference().withId(groupId)); + Metric same = + new Metric() + .withParent(new EntityReference().withId(parentId).withName("renamed-parent")) + .withMetricGroup(new EntityReference().withId(groupId).withName("renamed-group")); + Metric moved = + new Metric() + .withParent(new EntityReference().withId(UUID.randomUUID())) + .withMetricGroup(new EntityReference().withId(groupId)); + + assertFalse(MetricResource.hierarchyMembershipChanged(original, same)); + assertTrue(MetricResource.hierarchyMembershipChanged(original, moved)); + } + + @Test + void hierarchyDestinationAuthorizationCoversTheResolvedParentAndGroup() { + EntityReference parent = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC) + .withFullyQualifiedName("revenue"); + EntityReference group = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.METRIC_GROUP) + .withFullyQualifiedName("profitability"); + Metric updated = new Metric().withParent(parent).withMetricGroup(group); + + assertEquals(List.of(parent, group), MetricResource.hierarchyDestinations(null, updated)); + assertEquals( + List.of(), + MetricResource.hierarchyDestinations( + new Metric().withParent(parent).withMetricGroup(group), updated)); + assertEquals(List.of(), MetricResource.hierarchyDestinations(null, new Metric())); + + try (ResourceFixture fixture = resourceFixture()) { + ArgumentCaptor operations = ArgumentCaptor.forClass(OperationContext.class); + ArgumentCaptor resources = + ArgumentCaptor.forClass(ResourceContextInterface.class); + + fixture.resource().authorizeHierarchyDestinations(mock(SecurityContext.class), null, updated); + + verify(fixture.authorizer(), times(2)) + .authorize(any(), operations.capture(), resources.capture()); + assertEquals( + Set.of(Entity.METRIC, Entity.METRIC_GROUP), + operations.getAllValues().stream() + .map(OperationContext::getResource) + .collect(Collectors.toSet())); + assertEquals( + Set.of(Entity.METRIC, Entity.METRIC_GROUP), + resources.getAllValues().stream() + .map(ResourceContextInterface::getResource) + .collect(Collectors.toSet())); + for (int index = 0; index < operations.getAllValues().size(); index++) { + assertEquals( + List.of(MetadataOperation.EDIT_ALL), + operations + .getAllValues() + .get(index) + .getOperations(resources.getAllValues().get(index))); + } + } + } + + @Test + void metricPatchRejectsRelationshipDerivedFieldsAndDetectsHierarchyPaths() { + jakarta.json.JsonPatch assets = + Json.createPatchBuilder().add("/assets", Json.createArrayBuilder().build()).build(); + jakarta.json.JsonPatch children = + Json.createPatchBuilder().add("/children", Json.createArrayBuilder().build()).build(); + jakarta.json.JsonPatch childrenCount = + Json.createPatchBuilder().add("/childrenCount", 2).build(); + jakarta.json.JsonPatch parent = + Json.createPatchBuilder() + .add( + "/parent", + Json.createObjectBuilder().add("id", UUID.randomUUID().toString()).build()) + .build(); + + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, () -> MetricResource.validateMetricPatch(assets)); + + assertTrue(exception.getMessage().contains("assets")); + assertThrows( + IllegalArgumentException.class, () -> MetricResource.validateMetricPatch(children)); + assertThrows( + IllegalArgumentException.class, () -> MetricResource.validateMetricPatch(childrenCount)); + assertTrue(MetricResource.patchMutatesHierarchy(parent)); + assertFalse(MetricResource.patchMutatesHierarchy(assets)); + } + + @Test + void hierarchyEndpointsPreserveIndependentZeroSizedPages() throws Exception { + Method hierarchy = + MetricResource.class.getMethod( + "getHierarchyContext", + jakarta.ws.rs.core.SecurityContext.class, + UUID.class, + int.class, + int.class, + int.class, + int.class); + + Min childLimit = + Arrays.stream(hierarchy.getParameterAnnotations()[2]) + .filter(Min.class::isInstance) + .map(Min.class::cast) + .findFirst() + .orElseThrow(); + Min siblingLimit = + Arrays.stream(hierarchy.getParameterAnnotations()[4]) + .filter(Min.class::isInstance) + .map(Min.class::cast) + .findFirst() + .orElseThrow(); + + assertEquals(0, childLimit.value()); + assertEquals(0, siblingLimit.value()); + } + + @Test + void hierarchyContextDelegatesZeroLimitsWithoutCoercion() { + UUID metricId = UUID.randomUUID(); + MetricHierarchyContext expected = new MetricHierarchyContext(); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().get(any(), eq(metricId), any())) + .thenReturn( + new Metric().withId(metricId).withName("revenue").withFullyQualifiedName("revenue")); + when(fixture + .repository() + .getHierarchyContext(eq(metricId), eq(0), eq(4), eq(0), eq(7), any(), any())) + .thenReturn(expected); + + MetricHierarchyContext actual = + fixture + .resource() + .getHierarchyContext( + mock(jakarta.ws.rs.core.SecurityContext.class), metricId, 0, 4, 0, 7); + + assertEquals(expected, actual); + verify(fixture.repository()) + .getHierarchyContext(eq(metricId), eq(0), eq(4), eq(0), eq(7), any(), any()); + } + } + + @Test + void hierarchyListAuthorizesAndPreservesOffsetPaging() { + ResultList expected = + new ResultList<>(List.of(), new Paging().withLimit(25).withOffset(50).withTotal(0)); + try (ResourceFixture fixture = resourceFixture()) { + SecurityContext securityContext = securityContext("alice"); + when(fixture.authorizer().getPermission(securityContext, "alice", Entity.METRIC)) + .thenReturn(viewPermission(Entity.METRIC, Permission.Access.CONDITIONAL_ALLOW)); + when(fixture.authorizer().getPermission(securityContext, "alice", Entity.METRIC_GROUP)) + .thenReturn(viewPermission(Entity.METRIC_GROUP, Permission.Access.ALLOW)); + when(fixture.repository().listHierarchy(eq(25), eq(50), eq("margin"), any(), any())) + .thenReturn(expected); + + ResultList actual = + fixture.resource().listHierarchy(securityContext, "margin", 25, 50); + + assertEquals(expected, actual); + verify(fixture.repository()).listHierarchy(eq(25), eq(50), eq("margin"), any(), any()); + verify(fixture.authorizer()).authorize(any(), any(), any()); + } + } + + @Test + void hierarchyListUsesDatabasePagingWhenMetricsAndGroupsAreUnconditionallyVisible() { + ResultList expected = + new ResultList<>(List.of(), new Paging().withLimit(25).withOffset(50).withTotal(0)); + try (ResourceFixture fixture = resourceFixture()) { + SecurityContext securityContext = securityContext("alice"); + when(fixture.authorizer().getPermission(securityContext, "alice", Entity.METRIC)) + .thenReturn(viewPermission(Entity.METRIC, Permission.Access.ALLOW)); + when(fixture.authorizer().getPermission(securityContext, "alice", Entity.METRIC_GROUP)) + .thenReturn(viewPermission(Entity.METRIC_GROUP, Permission.Access.ALLOW)); + when(fixture.repository().listHierarchy(25, 50, "margin")).thenReturn(expected); + + ResultList actual = + fixture.resource().listHierarchy(securityContext, "margin", 25, 50); + + assertEquals(expected, actual); + verify(fixture.repository()).listHierarchy(25, 50, "margin"); + verify(fixture.repository(), never()) + .listHierarchy(eq(25), eq(50), eq("margin"), any(), any()); + } + } + + @Test + void hierarchyListFiltersPolicyDerivedAllowsBecauseConditionalRulesMayStillApply() { + ResourcePermission policyPermission = viewPermission(Entity.METRIC, Permission.Access.ALLOW); + policyPermission.getPermissions().getFirst().withRule(new Rule().withName("catalog-view")); + + assertFalse(MetricResource.hasUnconditionalView(policyPermission)); + assertTrue( + MetricResource.hasUnconditionalView( + viewPermission(Entity.METRIC, Permission.Access.ALLOW))); + } + + @Test + void assetsListRejectsMissingMetricBeforeScanningRelationships() { + UUID metricId = UUID.randomUUID(); + EntityNotFoundException missing = EntityNotFoundException.byId(metricId.toString()); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().get(any(), eq(metricId), any())).thenThrow(missing); + + EntityNotFoundException thrown = + assertThrows( + EntityNotFoundException.class, + () -> + fixture + .resource() + .getAssets( + null, mock(SecurityContext.class), metricId, 20, 0, null, null, null)); + + assertEquals(missing, thrown); + verify(fixture.repository(), never()) + .listAssets(eq(metricId), anyInt(), anyInt(), any(), any(), any(), any()); + } + } + + @Test + void observabilityRejectsMissingMetricBeforeScanningRelationships() { + UUID metricId = UUID.randomUUID(); + EntityNotFoundException missing = EntityNotFoundException.byId(metricId.toString()); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().get(any(), eq(metricId), any())).thenThrow(missing); + + EntityNotFoundException thrown = + assertThrows( + EntityNotFoundException.class, + () -> + fixture.resource().getObservability(null, mock(SecurityContext.class), metricId)); + + assertEquals(missing, thrown); + verify(fixture.repository(), never()).getAssetsWithDirection(metricId); + verify(fixture.repository(), never()).getObservability(eq(metricId), any(), any()); + } + } + + @Test + void observabilityReusesTheAuthorizedLinkedAssets() { + UUID metricId = UUID.randomUUID(); + EntityReference table = + new EntityReference() + .withId(UUID.randomUUID()) + .withType(Entity.TABLE) + .withName("orders") + .withFullyQualifiedName("service.database.schema.orders"); + List linkedAssets = + List.of( + new MetricAssetDirection() + .withAsset(table) + .withDirection(MetricAssetDirection.Direction.UPSTREAM)); + MetricObservability expected = new MetricObservability(); + try (ResourceFixture fixture = resourceFixture()) { + when(fixture.repository().get(any(), eq(metricId), any())) + .thenReturn(new Metric().withId(metricId).withName("revenue")); + when(fixture.repository().getAssetsWithDirection(metricId)).thenReturn(linkedAssets); + when(fixture.repository().getObservability(metricId, linkedAssets, Set.of(table.getId()))) + .thenReturn(expected); + + MetricObservability actual = + fixture.resource().getObservability(null, mock(SecurityContext.class), metricId); + + assertEquals(expected, actual); + verify(fixture.repository(), times(1)).getAssetsWithDirection(metricId); + verify(fixture.repository()).getObservability(metricId, linkedAssets, Set.of(table.getId())); + } + } + + @Test + void customUnitsRequireMetricViewBeforeReadingCatalogValues() { + SecurityContext securityContext = securityContext("alice"); + AuthorizationException denied = new AuthorizationException("denied"); + try (ResourceFixture fixture = resourceFixture()) { + doThrow(denied) + .when(fixture.authorizer()) + .authorize(eq(securityContext), any(OperationContext.class), any()); + + AuthorizationException thrown = + assertThrows( + AuthorizationException.class, + () -> fixture.resource().getCustomUnitsOfMeasurement(securityContext)); + + assertEquals(denied, thrown); + ArgumentCaptor operation = ArgumentCaptor.forClass(OperationContext.class); + ArgumentCaptor resource = + ArgumentCaptor.forClass(ResourceContextInterface.class); + verify(fixture.authorizer()) + .authorize(eq(securityContext), operation.capture(), resource.capture()); + assertEquals(Entity.METRIC, operation.getValue().getResource()); + assertEquals( + List.of(MetadataOperation.VIEW_BASIC), + operation.getValue().getOperations(resource.getValue())); + verify(fixture.repository(), never()).getDistinctCustomUnitsOfMeasurement(); + } + } + + @Test + void bulkResponseAndAuthorizationFailureMergingCoverAllStatuses() { + EntityReference denied = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.TABLE).withName("orders"); + BulkResponse denial = new BulkResponse().withRequest(denied).withMessage("denied"); + try (ResourceFixture fixture = resourceFixture()) { + BulkOperationResult partial = + fixture + .resource() + .mergeAuthorizationFailures( + new BulkOperationResult() + .withStatus(ApiStatus.SUCCESS) + .withNumberOfRowsProcessed(1) + .withNumberOfRowsPassed(1), + List.of(denial)); + BulkOperationResult failure = + fixture + .resource() + .mergeAuthorizationFailures( + new BulkOperationResult().withStatus(ApiStatus.SUCCESS), List.of(denial)); + BulkOperationResult dryRun = + fixture.resource().emptyBulkResult(new BulkAssets().withDryRun(true)); + + assertEquals(ApiStatus.PARTIAL_SUCCESS, partial.getStatus()); + assertEquals(2, partial.getNumberOfRowsProcessed()); + assertEquals(1, partial.getNumberOfRowsFailed()); + assertEquals(ApiStatus.FAILURE, failure.getStatus()); + assertEquals(1, failure.getNumberOfRowsProcessed()); + assertEquals(ApiStatus.SUCCESS, dryRun.getStatus()); + assertTrue(dryRun.getDryRun()); + assertEquals( + Response.Status.BAD_REQUEST.getStatusCode(), + fixture.resource().buildBulkOperationResponse(failure).getStatus()); + assertEquals( + Response.Status.OK.getStatusCode(), + fixture.resource().buildBulkOperationResponse(partial).getStatus()); + } + } + + @Test + void constructorRegistersTheMetricEntityContract() { + try (ResourceFixture fixture = resourceFixture()) { + fixture.entity().verify(() -> Entity.getEntityRepository(Entity.METRIC)); + fixture.entity().verify(() -> Entity.getEntityClassFromType(Entity.METRIC)); + fixture.entity().verify(() -> Entity.registerResourcePermissions(Entity.METRIC, List.of())); + assertNotNull(fixture.resource()); + assertFalse(fixture.resource().getRepository().getAllowedFields().isEmpty()); + } + } + + private SecurityContext securityContext(String name) { + Principal principal = mock(Principal.class); + when(principal.getName()).thenReturn(name); + SecurityContext context = mock(SecurityContext.class); + when(context.getUserPrincipal()).thenReturn(principal); + return context; + } + + private ResourcePermission viewPermission(String resource, Permission.Access access) { + return new ResourcePermission() + .withResource(resource) + .withPermissions( + List.of( + new Permission().withOperation(MetadataOperation.VIEW_BASIC).withAccess(access))); + } + + private ResourceFixture resourceFixture() { + MockedStatic entity = mockStatic(Entity.class); + MetricRepository repository = mock(MetricRepository.class); + Authorizer authorizer = mock(Authorizer.class); + when(repository.getAllowedFields()) + .thenReturn(Set.of("id", "parent", "children", "relatedMetrics")); + when(repository.getFields(anyString())) + .thenReturn(org.openmetadata.service.util.EntityUtil.Fields.EMPTY_FIELDS); + entity.when(() -> Entity.getEntityRepository(Entity.METRIC)).thenReturn(repository); + entity.when(() -> Entity.getEntityClassFromType(Entity.METRIC)).thenReturn(Metric.class); + try { + return new ResourceFixture( + new MetricResource(authorizer, mock(Limits.class)), repository, authorizer, entity); + } catch (RuntimeException exception) { + entity.close(); + throw exception; + } + } + + private record ResourceFixture( + MetricResource resource, + MetricRepository repository, + Authorizer authorizer, + MockedStatic entity) + implements AutoCloseable { + @Override + public void close() { + entity.close(); + } + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/IndexMappingVersionTrackerTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/IndexMappingVersionTrackerTest.java index 4be2f12247f2..2d28b18a1448 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/search/IndexMappingVersionTrackerTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/IndexMappingVersionTrackerTest.java @@ -94,6 +94,15 @@ private Map buildMappingsFromPairs(String... pairs) { return mappings; } + @Test + void metricGroupIsDiscoverableWithoutBeingADataAsset() { + IndexMapping metricGroup = + IndexMappingLoader.getInstance().getIndexMapping().get("metricGroup"); + + assertEquals(List.of("all"), metricGroup.getParentAliases()); + assertFalse(metricGroup.getParentAliases().contains("dataAsset")); + } + // --- Basic functionality tests --- @Test diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchIndexFactoryTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchIndexFactoryTest.java index 1c3e52212ae0..5895d0fe9ea3 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchIndexFactoryTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchIndexFactoryTest.java @@ -41,6 +41,7 @@ import org.openmetadata.schema.entity.data.Glossary; import org.openmetadata.schema.entity.data.GlossaryTerm; import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.schema.entity.data.MetricGroup; import org.openmetadata.schema.entity.data.MlModel; import org.openmetadata.schema.entity.data.Pipeline; import org.openmetadata.schema.entity.data.PipelineStatus; @@ -111,6 +112,7 @@ import org.openmetadata.service.search.indexes.McpServiceIndex; import org.openmetadata.service.search.indexes.MessagingServiceIndex; import org.openmetadata.service.search.indexes.MetadataServiceIndex; +import org.openmetadata.service.search.indexes.MetricGroupIndex; import org.openmetadata.service.search.indexes.MetricIndex; import org.openmetadata.service.search.indexes.MlModelIndex; import org.openmetadata.service.search.indexes.MlModelServiceIndex; @@ -393,6 +395,8 @@ private static Stream supportedIndexMappings() { Arguments.of(Entity.USER, (Supplier) User::new, UserIndex.class), Arguments.of(Entity.TEAM, (Supplier) Team::new, TeamIndex.class), Arguments.of(Entity.METRIC, (Supplier) Metric::new, MetricIndex.class), + Arguments.of( + Entity.METRIC_GROUP, (Supplier) MetricGroup::new, MetricGroupIndex.class), Arguments.of(Entity.GLOSSARY, (Supplier) Glossary::new, GlossaryIndex.class), Arguments.of( Entity.GLOSSARY_TERM, (Supplier) GlossaryTerm::new, GlossaryTermIndex.class), diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchUtilsTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchUtilsTest.java index 3cac25b9f7c2..edfc35a480a7 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchUtilsTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/SearchUtilsTest.java @@ -571,6 +571,8 @@ void isDataAssetIndexRecognizesDataAssetIndices(String index) { // user/team/dataAsset alias are NOT data assets in this classifier's sense "user_search_index", "team_search_index", + "metric_group_search_index", + Entity.METRIC_GROUP, "dataAsset", "all", "garbage" @@ -680,6 +682,8 @@ void searchAfterMultipleCommaBearingValuesPreserved() { "pipeline_search_index | pipeline", "container_search_index | container", "metric_search_index | metric", + "metric_group_search_index | metricGroup", + "metricGroup | metricGroup", "user_search_index | user", "team_search_index | team", "context_file_search_index | contextFile", diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricGroupIndexTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricGroupIndexTest.java new file mode 100644 index 000000000000..7702bd10db81 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricGroupIndexTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.search.indexes; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.entity.data.MetricGroup; + +class MetricGroupIndexTest { + + @Test + void buildDocumentAlwaysIndexesNumericMemberCount() { + Map emptyCount = + new MetricGroupIndex(new MetricGroup()).buildSearchIndexDocInternal(new HashMap<>()); + Map populatedCount = + new MetricGroupIndex(new MetricGroup().withMetricCount(4)) + .buildSearchIndexDocInternal(new HashMap<>()); + + assertEquals(0, emptyCount.get("metricCount")); + assertEquals(4, populatedCount.get("metricCount")); + } + + @Test + void reindexFieldsIncludeCountAndExcludeUnboundedMembers() { + MetricGroupIndex index = new MetricGroupIndex(new MetricGroup()); + + assertTrue(index.getRequiredReindexFields().contains("metricCount")); + assertTrue(index.getExcludedFields().contains("metrics")); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricIndexTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricIndexTest.java new file mode 100644 index 000000000000..911ecb2180f6 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/search/indexes/MetricIndexTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2021 Collate + * 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. + */ + +package org.openmetadata.service.search.indexes; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.api.data.MetricDimension; +import org.openmetadata.schema.api.data.MetricMeasure; +import org.openmetadata.schema.entity.data.Metric; +import org.openmetadata.service.search.SearchClient; + +class MetricIndexTest { + + @Test + void buildDocumentAddsHierarchyCountsAndMetricChildFqnParts() { + Metric metric = + new Metric() + .withName("revenue") + .withChildrenCount(3) + .withDimensions( + List.of( + new MetricDimension() + .withName("region") + .withFullyQualifiedName("revenue.dimension.region"))) + .withMeasures( + List.of( + new MetricMeasure() + .withName("amount") + .withFullyQualifiedName("revenue.measure.amount"))); + + Map result = + new MetricIndex(metric).buildSearchIndexDocInternal(new HashMap<>()); + + assertEquals(3, result.get("childrenCount")); + assertTrue(result.get("fqnParts").toString().contains("region")); + assertTrue(result.get("fqnParts").toString().contains("amount")); + } + + @Test + void buildDocumentDefaultsMissingChildrenCountToZero() { + Map result = + new MetricIndex(new Metric()).buildSearchIndexDocInternal(new HashMap<>()); + + assertEquals(0, result.get("childrenCount")); + } + + @Test + void missingMetricGroupIsExplicitlyMarkedForSearchFieldRemoval() { + Map result = + new MetricIndex(new Metric()).buildSearchIndexDocInternal(new HashMap<>()); + + assertTrue(result.containsKey("metricGroup")); + assertNull(result.get("metricGroup")); + assertTrue(SearchClient.FIELDS_TO_REMOVE_WHEN_NULL.contains("metricGroup")); + } + + @Test + void reindexFieldsIncludeRelationshipDerivedHierarchyFields() { + MetricIndex index = new MetricIndex(new Metric()); + + assertTrue(index.getRequiredReindexFields().contains("parent")); + assertTrue(index.getRequiredReindexFields().contains("childrenCount")); + assertTrue(index.getRequiredReindexFields().contains("metricGroup")); + assertTrue(index.getExcludedFields().contains("children")); + assertFalse(index.getExcludedFields().contains("metricGroup")); + } +} diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskWorkflowHandlerTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskWorkflowHandlerTest.java index 3a896d0d6f57..ed15e0605ad7 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskWorkflowHandlerTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/tasks/TaskWorkflowHandlerTest.java @@ -13,7 +13,13 @@ package org.openmetadata.service.tasks; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -38,6 +44,7 @@ import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.Include; import org.openmetadata.schema.type.TagLabel; +import org.openmetadata.schema.type.TaskAvailableTransition; import org.openmetadata.schema.type.TaskEntityStatus; import org.openmetadata.schema.type.TaskEntityType; import org.openmetadata.schema.type.TaskResolution; @@ -72,6 +79,94 @@ void testInstanceNotNull() { assertNotNull(handler); } + @Test + void testMetricRejectedResolutionRequiresComment() { + Task metricApproval = metricApprovalTask(); + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + metricApproval, TaskResolutionType.Rejected, null)); + + assertEquals("A rejection comment is required", exception.getMessage()); + assertThrows( + IllegalArgumentException.class, + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + metricApproval, TaskResolutionType.Rejected, "")); + assertThrows( + IllegalArgumentException.class, + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + metricApproval, TaskResolutionType.Rejected, " ")); + } + + @Test + void testMetricRejectionAlwaysRequiresComment() { + Task metricApproval = metricApprovalTask(); + + assertThrows( + IllegalArgumentException.class, + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + metricApproval, TaskResolutionType.Rejected, null)); + assertDoesNotThrow( + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + metricApproval, TaskResolutionType.Rejected, "Metric definition is incomplete")); + } + + @Test + void testNonMetricTransitionsPreserveCommentlessApiContract() { + Task dataAccessRequest = + new Task() + .withType(TaskEntityType.DataAccessRequest) + .withAbout(new EntityReference().withType(Entity.TABLE)); + Task incident = + new Task() + .withType(TaskEntityType.TestCaseResolution) + .withAbout(new EntityReference().withType(Entity.TEST_CASE)); + + assertDoesNotThrow( + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + dataAccessRequest, TaskResolutionType.Rejected, null)); + assertDoesNotThrow( + () -> + TaskWorkflowHandler.validateMetricRejectionComment( + incident, TaskResolutionType.Completed, null)); + } + + @Test + void testTransitionRequiringCommentRejectsBlankResolutionComments() { + TaskAvailableTransition transition = + new TaskAvailableTransition().withId("reject").withRequiresComment(true); + + assertThrows( + IllegalArgumentException.class, + () -> TaskWorkflowHandler.validateResolutionComment(transition, null)); + assertThrows( + IllegalArgumentException.class, + () -> TaskWorkflowHandler.validateResolutionComment(transition, " ")); + assertDoesNotThrow( + () -> TaskWorkflowHandler.validateResolutionComment(transition, "Missing ownership")); + } + + @Test + void testTransitionWithoutCommentRequirementAcceptsMissingComment() { + TaskAvailableTransition transition = + new TaskAvailableTransition().withId("approve").withRequiresComment(false); + + assertDoesNotThrow(() -> TaskWorkflowHandler.validateResolutionComment(transition, null)); + assertDoesNotThrow(() -> TaskWorkflowHandler.validateResolutionComment(null, null)); + } + + @Test + void testDefaultRuntimeTaskReadinessWaitIsBoundedBelowOneSecond() { + assertTrue(TaskWorkflowHandler.DEFAULT_RUNTIME_TASK_READINESS_WAIT_MILLIS < 1_000L); + } + @Test void testSupportsMultiApprovalUsesRuntimeTaskWhenWorkflowInstanceIdMissing() { Task task = new Task().withId(UUID.randomUUID()); @@ -124,6 +219,7 @@ void testResolveTaskReturnsRefreshedOpenTaskWhenWorkflowStillOpen() { workflowMock.when(WorkflowHandler::getInstance).thenReturn(workflowHandler); when(workflowHandler.transformToNodeVariables(eq(taskId), any())) .thenAnswer(invocation -> invocation.getArgument(1)); + when(workflowHandler.hasActiveRuntimeTask(taskId)).thenReturn(true); when(workflowHandler.resolveTask(eq(taskId), any())).thenReturn(true); when(workflowHandler.isAwaitingAdditionalVotes(taskId)).thenReturn(true); @@ -178,7 +274,139 @@ void testResolveWorkflowTaskDoesNotFallbackWhenWorkflowResolutionFails() { } @Test - void testResolveWorkflowTaskFallbackRejectsAlreadyResolvedTask() { + void testResolveWorkflowTaskWaitsForRuntimeTaskBeforeTransformingVariables() { + UUID taskId = UUID.randomUUID(); + TaskAvailableTransition continueTransition = + new TaskAvailableTransition() + .withId("continue") + .withTargetTaskStatus(TaskEntityStatus.InProgress); + Task task = + new Task() + .withId(taskId) + .withWorkflowInstanceId(UUID.randomUUID()) + .withStatus(TaskEntityStatus.Open) + .withType(TaskEntityType.RequestApproval) + .withAbout(new EntityReference().withType(Entity.METRIC)) + .withAvailableTransitions(List.of(continueTransition)); + Task refreshedTask = new Task().withId(taskId).withStatus(TaskEntityStatus.InProgress); + + WorkflowHandler workflowHandler = mock(WorkflowHandler.class); + TaskRepository taskRepository = mock(TaskRepository.class); + EntityUtil.Fields fields = new EntityUtil.Fields(Set.of("about")); + + try (MockedStatic workflowMock = Mockito.mockStatic(WorkflowHandler.class); + MockedStatic entityMock = Mockito.mockStatic(Entity.class)) { + workflowMock.when(WorkflowHandler::getInstance).thenReturn(workflowHandler); + when(workflowHandler.hasActiveRuntimeTask(taskId)).thenReturn(false, true); + when(workflowHandler.transformToNodeVariables(eq(taskId), any())) + .thenAnswer(invocation -> invocation.getArgument(1)); + when(workflowHandler.resolveTask(eq(taskId), any())).thenReturn(true); + + entityMock.when(() -> Entity.getEntityRepository(Entity.TASK)).thenReturn(taskRepository); + when(taskRepository.getFields(anyString())).thenReturn(fields); + when(taskRepository.get(isNull(), eq(taskId), eq(fields))).thenReturn(refreshedTask); + + Task result = + new TaskWorkflowHandler(3, 0) + .resolveTask(task, "continue", null, null, null, null, "alice"); + + assertSame(refreshedTask, result); + var invocationOrder = Mockito.inOrder(workflowHandler); + invocationOrder.verify(workflowHandler, Mockito.times(2)).hasActiveRuntimeTask(taskId); + invocationOrder.verify(workflowHandler).transformToNodeVariables(eq(taskId), any()); + invocationOrder.verify(workflowHandler).resolveTask(eq(taskId), any()); + } + } + + @Test + void testResolveWorkflowTaskDoesNotFinalizeWhenRuntimeTaskRemainsUnavailable() { + UUID taskId = UUID.randomUUID(); + Task task = + new Task() + .withId(taskId) + .withWorkflowInstanceId(UUID.randomUUID()) + .withStatus(TaskEntityStatus.Open) + .withType(TaskEntityType.RequestApproval) + .withAbout(new EntityReference().withType(Entity.METRIC)); + + WorkflowHandler workflowHandler = mock(WorkflowHandler.class); + TaskRepository taskRepository = mock(TaskRepository.class); + + try (MockedStatic workflowMock = Mockito.mockStatic(WorkflowHandler.class); + MockedStatic entityMock = Mockito.mockStatic(Entity.class)) { + workflowMock.when(WorkflowHandler::getInstance).thenReturn(workflowHandler); + when(workflowHandler.hasActiveRuntimeTask(taskId)).thenReturn(false); + entityMock.when(() -> Entity.getEntityRepository(Entity.TASK)).thenReturn(taskRepository); + + IllegalStateException exception = + assertThrows( + IllegalStateException.class, + () -> + new TaskWorkflowHandler(3, 0) + .resolveTask( + task, + "reject", + TaskResolutionType.Rejected, + null, + null, + "Missing definition details", + "alice")); + + assertTrue(exception.getMessage().contains("unavailable")); + verify(workflowHandler, Mockito.times(3)).hasActiveRuntimeTask(taskId); + verify(workflowHandler, never()).transformToNodeVariables(any(), any()); + verify(workflowHandler, never()).resolveTask(any(), any()); + verify(taskRepository, never()).resolveTask(any(), any(TaskResolution.class), anyString()); + } + } + + @Test + void testMetricWorkflowDoesNotFallbackWhenRuntimeTaskDisappearsDuringResolution() { + UUID taskId = UUID.randomUUID(); + Task task = + new Task() + .withId(taskId) + .withWorkflowInstanceId(UUID.randomUUID()) + .withStatus(TaskEntityStatus.Open) + .withType(TaskEntityType.RequestApproval) + .withAbout(new EntityReference().withType(Entity.METRIC)); + + WorkflowHandler workflowHandler = mock(WorkflowHandler.class); + TaskRepository taskRepository = mock(TaskRepository.class); + + try (MockedStatic workflowMock = Mockito.mockStatic(WorkflowHandler.class); + MockedStatic entityMock = Mockito.mockStatic(Entity.class)) { + workflowMock.when(WorkflowHandler::getInstance).thenReturn(workflowHandler); + when(workflowHandler.hasActiveRuntimeTask(taskId)).thenReturn(true, false); + when(workflowHandler.transformToNodeVariables(eq(taskId), any())) + .thenAnswer(invocation -> invocation.getArgument(1)); + when(workflowHandler.resolveTask(eq(taskId), any())).thenReturn(false); + entityMock.when(() -> Entity.getEntityRepository(Entity.TASK)).thenReturn(taskRepository); + + TaskStateConflictException exception = + assertThrows( + TaskStateConflictException.class, + () -> + new TaskWorkflowHandler(1, 0) + .resolveTask( + task, + "reject", + TaskResolutionType.Rejected, + null, + null, + "Missing definition details", + "alice")); + + assertTrue(exception.getMessage().contains("disappeared")); + verify(workflowHandler, Mockito.times(2)).hasActiveRuntimeTask(taskId); + verify(workflowHandler).transformToNodeVariables(eq(taskId), any()); + verify(workflowHandler).resolveTask(eq(taskId), any()); + verify(taskRepository, never()).resolveTask(any(), any(TaskResolution.class), anyString()); + } + } + + @Test + void testNonMetricWorkflowFallbackRejectsAlreadyResolvedTask() { UUID taskId = UUID.randomUUID(); Task task = new Task() @@ -213,14 +441,62 @@ void testResolveWorkflowTaskFallbackRejectsAlreadyResolvedTask() { } } + @Test + void testNonMetricWorkflowPreservesDirectResolutionFallback() { + UUID taskId = UUID.randomUUID(); + Task task = + new Task() + .withId(taskId) + .withWorkflowInstanceId(UUID.randomUUID()) + .withStatus(TaskEntityStatus.Open) + .withType(TaskEntityType.RequestApproval); + Task storedTask = new Task().withId(taskId).withStatus(TaskEntityStatus.Completed); + EntityReference resolvedBy = + new EntityReference().withId(UUID.randomUUID()).withType(Entity.USER).withName("alice"); + EntityUtil.Fields fields = new EntityUtil.Fields(Set.of("resolution")); + + WorkflowHandler workflowHandler = mock(WorkflowHandler.class); + TaskRepository taskRepository = mock(TaskRepository.class); + + try (MockedStatic workflowMock = Mockito.mockStatic(WorkflowHandler.class); + MockedStatic entityMock = Mockito.mockStatic(Entity.class)) { + workflowMock.when(WorkflowHandler::getInstance).thenReturn(workflowHandler); + when(workflowHandler.transformToNodeVariables(eq(taskId), any())).thenReturn(null); + when(workflowHandler.resolveTask(taskId, null)).thenReturn(false); + when(workflowHandler.hasActiveRuntimeTask(taskId)).thenReturn(false); + + entityMock.when(() -> Entity.getEntityRepository(Entity.TASK)).thenReturn(taskRepository); + entityMock + .when(() -> Entity.getEntityReferenceByName(Entity.USER, "alice", Include.NON_DELETED)) + .thenReturn(resolvedBy); + when(taskRepository.resolveTask(eq(task), any(TaskResolution.class), eq("alice"))) + .thenReturn(storedTask); + when(taskRepository.getFields(anyString())).thenReturn(fields); + when(taskRepository.get(isNull(), eq(taskId), eq(fields))).thenReturn(storedTask); + + Task result = + new TaskWorkflowHandler(1, 0) + .resolveTask(task, "approve", TaskResolutionType.Approved, null, null, null, "alice"); + + assertSame(storedTask, result); + verify(taskRepository).resolveTask(eq(task), any(TaskResolution.class), eq("alice")); + } + } + @Test void testResolveStandaloneTaskReturnsRefreshedResolvedTask() { UUID taskId = UUID.randomUUID(); + TaskAvailableTransition resolveIncident = + new TaskAvailableTransition() + .withId("complete") + .withResolutionType(TaskResolutionType.Completed) + .withRequiresComment(true); Task task = new Task() .withId(taskId) .withStatus(TaskEntityStatus.Open) - .withType(TaskEntityType.CustomTask); + .withType(TaskEntityType.CustomTask) + .withAvailableTransitions(List.of(resolveIncident)); Task storedTask = new Task().withId(taskId).withStatus(TaskEntityStatus.Completed); Task refreshedTask = new Task().withId(taskId).withStatus(TaskEntityStatus.Completed); EntityReference resolvedBy = @@ -247,7 +523,13 @@ void testResolveStandaloneTaskReturnsRefreshedResolvedTask() { Task result = TaskWorkflowHandler.getInstance() .resolveTask( - task, "complete", TaskResolutionType.Completed, null, null, null, "alice"); + task, + "complete", + TaskResolutionType.Completed, + null, + null, + "Resolution details", + "alice"); assertSame(refreshedTask, result); verify(taskRepository).resolveTask(eq(task), any(TaskResolution.class), eq("alice")); @@ -385,4 +667,10 @@ void testApplySuggestion_columnTag_appliesToColumnNotParent() throws Exception { parentTags == null || parentTags.isEmpty(), "Column tag suggestion must not tag the parent table"); } + + private Task metricApprovalTask() { + return new Task() + .withType(TaskEntityType.RequestApproval) + .withAbout(new EntityReference().withType(Entity.METRIC)); + } } diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/util/EntityFieldUtilsTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/util/EntityFieldUtilsTest.java index 7ed4971ff344..d3cfe4683d3a 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/util/EntityFieldUtilsTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/util/EntityFieldUtilsTest.java @@ -69,6 +69,7 @@ void setEntityFieldCreatesPatchAndChangeEventWhenEntityChanges() { eq("alice"), any(JsonPatch.class), isNull(), + eq("*"), eq("workflow-bot")); ArgumentCaptor jsonCaptor = ArgumentCaptor.forClass(String.class); diff --git a/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 b/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 index 51d85de0d243..fb4e52ec157a 100644 --- a/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 +++ b/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 @@ -98,6 +98,7 @@ ENTITY_TYPE | 'webAnalyticEvent' | 'llmService' | 'metric' + | 'metricGroup' | 'report' | 'query' | 'directory' diff --git a/openmetadata-spec/src/main/resources/elasticsearch/en/metric_group_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/en/metric_group_index_mapping.json new file mode 100644 index 000000000000..5b722c1b737e --- /dev/null +++ b/openmetadata-spec/src/main/resources/elasticsearch/en/metric_group_index_mapping.json @@ -0,0 +1,587 @@ +{ + "settings": { + "index": { + "max_ngram_diff": 17 + }, + "analysis": { + "tokenizer": { + "n_gram_tokenizer": { + "type": "ngram", + "min_gram": 3, + "max_gram": 20, + "token_chars": [ + "letter", + "digit" + ] + } + }, + "normalizer": { + "lowercase_normalizer": { + "type": "custom", + "char_filter": [], + "filter": [ + "lowercase" + ] + } + }, + "analyzer": { + "om_analyzer": { + "tokenizer": "standard", + "filter": [ + "word_delimiter_filter", + "lowercase", + "om_stemmer", + "om_plural_stemmer" + ] + }, + "om_ngram": { + "type": "custom", + "tokenizer": "n_gram_tokenizer", + "filter": [ + "lowercase" + ] + }, + "om_compound_analyzer": { + "tokenizer": "standard", + "filter": [ + "compound_word_delimiter_graph", + "lowercase", + "flatten_graph" + ] + } + }, + "filter": { + "om_stemmer": { + "type": "stemmer", + "name": "kstem" + }, + "word_delimiter_filter": { + "type": "word_delimiter", + "preserve_original": true + }, + "compound_word_delimiter_graph": { + "type": "word_delimiter_graph", + "generate_word_parts": true, + "generate_number_parts": true, + "split_on_case_change": true, + "split_on_numerics": true, + "catenate_words": false, + "catenate_numbers": false, + "catenate_all": false, + "preserve_original": true, + "stem_english_possessive": true + }, + "om_plural_stemmer": { + "type": "stemmer", + "name": "minimal_english" + } + } + } + }, + "mappings": { + "properties": { + "extension": { + "type": "object", + "enabled": false + }, + "customPropertiesTyped": { + "type": "nested", + "properties": { + "name": { + "type": "keyword" + }, + "propertyType": { + "type": "keyword" + }, + "stringValue": { + "type": "keyword" + }, + "textValue": { + "type": "text", + "analyzer": "om_analyzer" + }, + "longValue": { + "type": "long" + }, + "doubleValue": { + "type": "double" + }, + "start": { + "type": "long" + }, + "end": { + "type": "long" + }, + "refId": { + "type": "keyword" + }, + "refType": { + "type": "keyword" + }, + "refName": { + "type": "keyword" + }, + "refFqn": { + "type": "keyword" + } + } + }, + "changeDescription": { + "enabled": false + }, + "incrementalChangeDescription": { + "enabled": false + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "analyzer": "om_analyzer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256, + "normalizer": "lowercase_normalizer" + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "fullyQualifiedName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "displayName": { + "type": "text", + "analyzer": "om_analyzer", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + }, + "actualCase": { + "type": "keyword", + "ignore_above": 256 + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "description": { + "type": "text", + "analyzer": "om_analyzer", + "similarity": "boolean", + "term_vector": "with_positions_offsets" + }, + "fqnParts": { + "type": "keyword" + }, + "domains": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "dataProducts": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "owners": { + "type": "nested", + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "version": { + "type": "float" + }, + "updatedAt": { + "type": "date", + "format": "epoch_second" + }, + "updatedBy": { + "type": "text" + }, + "href": { + "type": "text" + }, + "tier": { + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "classificationTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "glossaryTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "tags": { + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "deleted": { + "type": "boolean" + }, + "entityType": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "entityStatus": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "totalVotes": { + "type": "long", + "null_value": 0 + }, + "votes": { + "type": "object", + "dynamic": false, + "properties": { + "upVotes": { + "type": "integer" + }, + "downVotes": { + "type": "integer" + } + } + }, + "descriptionStatus": { + "type": "keyword" + }, + "descriptionSources": { + "type": "object", + "dynamic": false + }, + "tagSources": { + "type": "object", + "dynamic": false + }, + "tierSources": { + "type": "object", + "dynamic": false + }, + "certification": { + "type": "object", + "properties": { + "tagLabel": { + "type": "object", + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "appliedDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + }, + "expiryDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + } + } + }, + "fqnHash": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 512 + } + } + }, + "fingerprint": { + "type": "keyword" + }, + "textToLLMContext": { + "type": "text" + }, + "textToEmbed": { + "type": "text" + }, + "chunkIndex": { + "type": "integer" + }, + "chunkCount": { + "type": "integer" + }, + "ownerDisplayName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "ownerName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "metrics": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricCount": { + "type": "integer" + } + } + } +} diff --git a/openmetadata-spec/src/main/resources/elasticsearch/en/metric_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/en/metric_index_mapping.json index cc421681919f..b4f11a658c6a 100644 --- a/openmetadata-spec/src/main/resources/elasticsearch/en/metric_index_mapping.json +++ b/openmetadata-spec/src/main/resources/elasticsearch/en/metric_index_mapping.json @@ -518,6 +518,67 @@ } } }, + "parent": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricGroup": { + "properties": { + "id": { "type": "keyword" }, + "type": { "type": "keyword" }, + "name": { "type": "keyword" }, + "displayName": { "type": "keyword" }, + "fullyQualifiedName": { "type": "keyword" }, + "description": { "type": "text" }, + "deleted": { "type": "boolean" }, + "href": { "type": "text" } + } + }, + "childrenCount": { + "type": "integer" + }, "usageCount": { "type": "integer" }, diff --git a/openmetadata-spec/src/main/resources/elasticsearch/indexMapping.json b/openmetadata-spec/src/main/resources/elasticsearch/indexMapping.json index 8b5ad5f5f2c6..f98d336bf9b7 100644 --- a/openmetadata-spec/src/main/resources/elasticsearch/indexMapping.json +++ b/openmetadata-spec/src/main/resources/elasticsearch/indexMapping.json @@ -298,6 +298,15 @@ ], "childAliases": [] }, + "metricGroup": { + "indexName": "metric_group_search_index", + "indexMappingFile": "/elasticsearch/%s/metric_group_index_mapping.json", + "alias": "metricGroup", + "parentAliases": [ + "all" + ], + "childAliases": [] + }, "glossary": { "indexName": "glossary_search_index", "indexMappingFile": "/elasticsearch/%s/glossary_index_mapping.json", diff --git a/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_group_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_group_index_mapping.json new file mode 100644 index 000000000000..2afbb776a7b2 --- /dev/null +++ b/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_group_index_mapping.json @@ -0,0 +1,574 @@ +{ + "settings": { + "analysis": { + "normalizer": { + "lowercase_normalizer": { + "type": "custom", + "char_filter": [], + "filter": [ + "lowercase" + ] + } + }, + "analyzer": { + "om_analyzer": { + "tokenizer": "letter", + "filter": [ + "lowercase", + "om_stemmer" + ] + }, + "om_analyzer_jp": { + "tokenizer": "kuromoji_tokenizer", + "type": "custom", + "filter": [ + "kuromoji_baseform", + "kuromoji_part_of_speech", + "kuromoji_number", + "kuromoji_stemmer" + ] + }, + "om_ngram": { + "type": "custom", + "tokenizer": "n_gram_tokenizer", + "filter": [ + "lowercase" + ] + }, + "om_compound_analyzer": { + "tokenizer": "standard", + "filter": [ + "lowercase", + "compound_word_delimiter_graph", + "flatten_graph" + ] + } + }, + "filter": { + "om_stemmer": { + "type": "stemmer", + "name": "english" + }, + "compound_word_delimiter_graph": { + "type": "word_delimiter_graph", + "generate_word_parts": true, + "generate_number_parts": true, + "split_on_case_change": true, + "split_on_numerics": true, + "catenate_words": false, + "catenate_numbers": false, + "catenate_all": false, + "preserve_original": true, + "stem_english_possessive": true + } + }, + "tokenizer": { + "n_gram_tokenizer": { + "type": "ngram", + "min_gram": 1, + "max_gram": 2, + "token_chars": [ + "letter", + "digit" + ] + } + } + }, + "index": { + "max_ngram_diff": 1 + } + }, + "mappings": { + "properties": { + "extension": { + "type": "object", + "enabled": false + }, + "customPropertiesTyped": { + "type": "nested", + "properties": { + "name": { + "type": "keyword" + }, + "propertyType": { + "type": "keyword" + }, + "stringValue": { + "type": "keyword" + }, + "textValue": { + "type": "text", + "analyzer": "om_analyzer" + }, + "longValue": { + "type": "long" + }, + "doubleValue": { + "type": "double" + }, + "start": { + "type": "long" + }, + "end": { + "type": "long" + }, + "refId": { + "type": "keyword" + }, + "refType": { + "type": "keyword" + }, + "refName": { + "type": "keyword" + }, + "refFqn": { + "type": "keyword" + } + } + }, + "changeDescription": { + "enabled": false + }, + "incrementalChangeDescription": { + "enabled": false + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "analyzer": "om_analyzer_jp", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256, + "normalizer": "lowercase_normalizer" + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "fullyQualifiedName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "fqnParts": { + "type": "keyword" + }, + "domains": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "dataProducts": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "displayName": { + "type": "text", + "analyzer": "om_analyzer_jp", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + }, + "actualCase": { + "type": "keyword", + "ignore_above": 256 + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "description": { + "type": "text", + "analyzer": "om_analyzer_jp", + "index_options": "docs" + }, + "owners": { + "type": "nested", + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "version": { + "type": "float" + }, + "updatedAt": { + "type": "date", + "format": "epoch_second" + }, + "updatedBy": { + "type": "text" + }, + "href": { + "type": "text" + }, + "tier": { + "properties": { + "tagFQN": { + "type": "keyword", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + }, + "normalizer": "lowercase_normalizer" + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "classificationTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "glossaryTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "tags": { + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "deleted": { + "type": "boolean" + }, + "entityType": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "entityStatus": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "totalVotes": { + "type": "long", + "null_value": 0 + }, + "votes": { + "type": "object", + "dynamic": false, + "properties": { + "upVotes": { + "type": "integer" + }, + "downVotes": { + "type": "integer" + } + } + }, + "descriptionStatus": { + "type": "keyword" + }, + "certification": { + "type": "object", + "properties": { + "tagLabel": { + "type": "object", + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "appliedDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + }, + "expiryDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + } + } + }, + "fqnHash": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 512 + } + } + }, + "fingerprint": { + "type": "keyword" + }, + "textToLLMContext": { + "type": "text" + }, + "textToEmbed": { + "type": "text" + }, + "chunkIndex": { + "type": "integer" + }, + "chunkCount": { + "type": "integer" + }, + "ownerDisplayName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "ownerName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "metrics": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricCount": { + "type": "integer" + } + } + } +} diff --git a/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_index_mapping.json index ef6c569e78b5..10b125081ad7 100644 --- a/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_index_mapping.json +++ b/openmetadata-spec/src/main/resources/elasticsearch/jp/metric_index_mapping.json @@ -522,6 +522,67 @@ } } }, + "parent": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricGroup": { + "properties": { + "id": { "type": "keyword" }, + "type": { "type": "keyword" }, + "name": { "type": "keyword" }, + "displayName": { "type": "keyword" }, + "fullyQualifiedName": { "type": "keyword" }, + "description": { "type": "text" }, + "deleted": { "type": "boolean" }, + "href": { "type": "text" } + } + }, + "childrenCount": { + "type": "integer" + }, "usageCount": { "type": "integer" }, diff --git a/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_group_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_group_index_mapping.json new file mode 100644 index 000000000000..80c485f52c4d --- /dev/null +++ b/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_group_index_mapping.json @@ -0,0 +1,553 @@ +{ + "settings": { + "index": { + "max_ngram_diff": 17 + }, + "analysis": { + "tokenizer": { + "n_gram_tokenizer": { + "type": "ngram", + "min_gram": 3, + "max_gram": 20, + "token_chars": [ + "letter", + "digit" + ] + } + }, + "normalizer": { + "lowercase_normalizer": { + "type": "custom", + "char_filter": [], + "filter": [ + "lowercase", + "asciifolding" + ] + } + }, + "analyzer": { + "om_analyzer": { + "tokenizer": "standard", + "filter": [ + "word_delimiter_filter", + "lowercase", + "asciifolding", + "russian_stop", + "russian_snowball", + "english_stop", + "om_kstem" + ] + }, + "om_ngram": { + "type": "custom", + "tokenizer": "n_gram_tokenizer", + "filter": [ + "lowercase" + ] + }, + "om_compound_analyzer": { + "tokenizer": "standard", + "filter": [ + "compound_word_delimiter_graph", + "lowercase", + "flatten_graph" + ] + } + }, + "filter": { + "word_delimiter_filter": { + "type": "word_delimiter", + "preserve_original": true + }, + "compound_word_delimiter_graph": { + "type": "word_delimiter_graph", + "generate_word_parts": true, + "generate_number_parts": true, + "split_on_case_change": true, + "split_on_numerics": true, + "catenate_words": false, + "catenate_numbers": false, + "catenate_all": false, + "preserve_original": true, + "stem_english_possessive": true + }, + "russian_stop": { + "type": "stop", + "stopwords": "_russian_" + }, + "english_stop": { + "type": "stop", + "stopwords": "_english_" + }, + "russian_snowball": { + "name": "russian", + "type": "stemmer" + }, + "om_kstem": { + "type": "kstem" + }, + "asciifolding": { + "type": "asciifolding" + } + } + } + }, + "mappings": { + "properties": { + "extension": { + "type": "object", + "enabled": false + }, + "customPropertiesTyped": { + "type": "nested", + "properties": { + "name": { + "type": "keyword" + }, + "propertyType": { + "type": "keyword" + }, + "stringValue": { + "type": "keyword" + }, + "textValue": { + "type": "text", + "analyzer": "om_analyzer" + }, + "longValue": { + "type": "long" + }, + "doubleValue": { + "type": "double" + }, + "start": { + "type": "long" + }, + "end": { + "type": "long" + }, + "refId": { + "type": "keyword" + }, + "refType": { + "type": "keyword" + }, + "refName": { + "type": "keyword" + }, + "refFqn": { + "type": "keyword" + } + } + }, + "changeDescription": { + "enabled": false + }, + "incrementalChangeDescription": { + "enabled": false + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "analyzer": "om_analyzer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256, + "normalizer": "lowercase_normalizer" + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "fullyQualifiedName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "displayName": { + "type": "text", + "analyzer": "om_analyzer", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + }, + "actualCase": { + "type": "keyword", + "ignore_above": 256 + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "description": { + "type": "text", + "analyzer": "om_analyzer", + "similarity": "boolean", + "term_vector": "with_positions_offsets" + }, + "fqnParts": { + "type": "keyword" + }, + "domains": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "owners": { + "type": "nested", + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "version": { + "type": "float" + }, + "updatedAt": { + "type": "date", + "format": "epoch_second" + }, + "updatedBy": { + "type": "text" + }, + "href": { + "type": "text" + }, + "tier": { + "properties": { + "tagFQN": { + "type": "keyword", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + }, + "normalizer": "lowercase_normalizer" + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "classificationTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "glossaryTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "tags": { + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "deleted": { + "type": "boolean" + }, + "entityType": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "entityStatus": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "totalVotes": { + "type": "long", + "null_value": 0 + }, + "votes": { + "type": "object", + "dynamic": false, + "properties": { + "upVotes": { + "type": "integer" + }, + "downVotes": { + "type": "integer" + } + } + }, + "descriptionStatus": { + "type": "keyword" + }, + "descriptionSources": { + "type": "object", + "dynamic": false + }, + "tagSources": { + "type": "object", + "dynamic": false + }, + "tierSources": { + "type": "object", + "dynamic": false + }, + "certification": { + "type": "object", + "properties": { + "tagLabel": { + "type": "object", + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "appliedDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + }, + "expiryDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + } + } + }, + "fqnHash": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 512 + } + } + }, + "fingerprint": { + "type": "keyword" + }, + "textToLLMContext": { + "type": "text" + }, + "textToEmbed": { + "type": "text" + }, + "chunkIndex": { + "type": "integer" + }, + "chunkCount": { + "type": "integer" + }, + "ownerDisplayName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "ownerName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "metrics": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricCount": { + "type": "integer" + } + } + } +} diff --git a/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_index_mapping.json index 01ee2ac0ee37..7b8994467243 100644 --- a/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_index_mapping.json +++ b/openmetadata-spec/src/main/resources/elasticsearch/ru/metric_index_mapping.json @@ -484,6 +484,67 @@ } } }, + "parent": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricGroup": { + "properties": { + "id": { "type": "keyword" }, + "type": { "type": "keyword" }, + "name": { "type": "keyword" }, + "displayName": { "type": "keyword" }, + "fullyQualifiedName": { "type": "keyword" }, + "description": { "type": "text" }, + "deleted": { "type": "boolean" }, + "href": { "type": "text" } + } + }, + "childrenCount": { + "type": "integer" + }, "usageCount": { "type": "integer" }, diff --git a/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_group_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_group_index_mapping.json new file mode 100644 index 000000000000..bfc286c43dfb --- /dev/null +++ b/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_group_index_mapping.json @@ -0,0 +1,559 @@ +{ + "settings": { + "analysis": { + "normalizer": { + "lowercase_normalizer": { + "type": "custom", + "char_filter": [], + "filter": [ + "lowercase" + ] + } + }, + "analyzer": { + "om_analyzer": { + "tokenizer": "letter", + "filter": [ + "lowercase", + "om_stemmer" + ] + }, + "om_ngram": { + "type": "custom", + "tokenizer": "n_gram_tokenizer", + "filter": [ + "lowercase" + ] + }, + "om_compound_analyzer": { + "tokenizer": "standard", + "filter": [ + "lowercase", + "compound_word_delimiter_graph", + "flatten_graph" + ] + } + }, + "filter": { + "om_stemmer": { + "type": "stemmer", + "name": "english" + }, + "compound_word_delimiter_graph": { + "type": "word_delimiter_graph", + "generate_word_parts": true, + "generate_number_parts": true, + "split_on_case_change": true, + "split_on_numerics": true, + "catenate_words": false, + "catenate_numbers": false, + "catenate_all": false, + "preserve_original": true, + "stem_english_possessive": true + } + }, + "tokenizer": { + "n_gram_tokenizer": { + "type": "ngram", + "min_gram": 2, + "max_gram": 3, + "token_chars": [ + "letter", + "digit" + ] + } + } + }, + "index": { + "max_ngram_diff": 1 + } + }, + "mappings": { + "properties": { + "extension": { + "type": "object", + "enabled": false + }, + "customPropertiesTyped": { + "type": "nested", + "properties": { + "name": { + "type": "keyword" + }, + "propertyType": { + "type": "keyword" + }, + "stringValue": { + "type": "keyword" + }, + "textValue": { + "type": "text", + "analyzer": "om_analyzer" + }, + "longValue": { + "type": "long" + }, + "doubleValue": { + "type": "double" + }, + "start": { + "type": "long" + }, + "end": { + "type": "long" + }, + "refId": { + "type": "keyword" + }, + "refType": { + "type": "keyword" + }, + "refName": { + "type": "keyword" + }, + "refFqn": { + "type": "keyword" + } + } + }, + "changeDescription": { + "enabled": false + }, + "incrementalChangeDescription": { + "enabled": false + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256, + "normalizer": "lowercase_normalizer" + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "fullyQualifiedName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "fqnParts": { + "type": "keyword" + }, + "domains": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "dataProducts": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "displayName": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + }, + "actualCase": { + "type": "keyword", + "ignore_above": 256 + }, + "ngram": { + "type": "text", + "analyzer": "om_ngram" + }, + "compound": { + "type": "text", + "analyzer": "om_compound_analyzer" + } + } + }, + "description": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart", + "index_options": "docs" + }, + "owners": { + "type": "nested", + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "version": { + "type": "float" + }, + "updatedAt": { + "type": "date", + "format": "epoch_second" + }, + "updatedBy": { + "type": "text" + }, + "href": { + "type": "text" + }, + "tier": { + "properties": { + "tagFQN": { + "type": "keyword", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + }, + "normalizer": "lowercase_normalizer" + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "classificationTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "glossaryTags": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "tags": { + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "deleted": { + "type": "boolean" + }, + "entityType": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "ignore_above": 256 + } + } + }, + "entityStatus": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "totalVotes": { + "type": "long", + "null_value": 0 + }, + "descriptionStatus": { + "type": "keyword" + }, + "certification": { + "type": "object", + "properties": { + "tagLabel": { + "type": "object", + "properties": { + "tagFQN": { + "type": "keyword", + "normalizer": "lowercase_normalizer", + "fields": { + "text": { + "type": "text", + "analyzer": "om_analyzer" + } + } + }, + "labelType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "source": { + "type": "keyword" + }, + "state": { + "type": "keyword" + } + } + }, + "appliedDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + }, + "expiryDate": { + "type": "date", + "format": "strict_date_optional_time||epoch_millis" + } + } + }, + "fqnHash": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 512 + } + } + }, + "fingerprint": { + "type": "keyword" + }, + "textToLLMContext": { + "type": "text" + }, + "textToEmbed": { + "type": "text" + }, + "chunkIndex": { + "type": "integer" + }, + "chunkCount": { + "type": "integer" + }, + "ownerDisplayName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "ownerName": { + "type": "keyword", + "normalizer": "lowercase_normalizer" + }, + "metrics": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricCount": { + "type": "integer" + } + } + } +} diff --git a/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_index_mapping.json b/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_index_mapping.json index 1c499cde2ff3..e4de2b700bd8 100644 --- a/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_index_mapping.json +++ b/openmetadata-spec/src/main/resources/elasticsearch/zh/metric_index_mapping.json @@ -519,6 +519,67 @@ } } }, + "parent": { + "properties": { + "id": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 36 + } + } + }, + "type": { + "type": "keyword" + }, + "name": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "displayName": { + "type": "keyword", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "fullyQualifiedName": { + "type": "text" + }, + "description": { + "type": "text" + }, + "deleted": { + "type": "boolean" + }, + "href": { + "type": "text" + } + } + }, + "metricGroup": { + "properties": { + "id": { "type": "keyword" }, + "type": { "type": "keyword" }, + "name": { "type": "keyword" }, + "displayName": { "type": "keyword" }, + "fullyQualifiedName": { "type": "keyword" }, + "description": { "type": "text" }, + "deleted": { "type": "boolean" }, + "href": { "type": "text" } + } + }, + "childrenCount": { + "type": "integer" + }, "usageCount": { "type": "integer" }, diff --git a/openmetadata-spec/src/main/resources/json/schema/api/data/createMetric.json b/openmetadata-spec/src/main/resources/json/schema/api/data/createMetric.json index 5b4cf8580b17..c3f12ea4db4a 100644 --- a/openmetadata-spec/src/main/resources/json/schema/api/data/createMetric.json +++ b/openmetadata-spec/src/main/resources/json/schema/api/data/createMetric.json @@ -73,13 +73,31 @@ "assets": { "description": "Data assets (tables, dashboards, etc.) this metric is computed on or applies to.", "$ref": "../../type/entityReferenceList.json", - "default": null + "default": null, + "deprecated": true, + "$comment": "@deprecated Use PUT /v1/metrics/{name}/assets/add to link assets after creating the metric" + }, + "parent": { + "description": "Fully qualified name of the parent metric this metric is a variant of.", + "$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName" + }, + "metricGroup": { + "description": "Fully qualified name of the Metric Group this metric hierarchy belongs to. Children inherit their parent's group.", + "$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName" }, "owners": { "description": "Owners of this metric", "$ref": "../../type/entityReferenceList.json", "default": null }, + "experts": { + "description": "List of fully qualified user names for users who are experts in this metric.", + "type": "array", + "items": { + "type": "string" + }, + "default": null + }, "reviewers": { "description": "Reviewers of this metric", "$ref": "../../type/entityReferenceList.json", diff --git a/openmetadata-spec/src/main/resources/json/schema/api/data/createMetricGroup.json b/openmetadata-spec/src/main/resources/json/schema/api/data/createMetricGroup.json new file mode 100644 index 000000000000..f2e8deb5b2c2 --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/api/data/createMetricGroup.json @@ -0,0 +1,67 @@ +{ + "$id": "https://open-metadata.org/schema/api/data/createMetricGroup.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CreateMetricGroupRequest", + "description": "Create Metric Group entity request", + "type": "object", + "javaType": "org.openmetadata.schema.api.data.CreateMetricGroup", + "javaInterfaces": ["org.openmetadata.schema.CreateEntity"], + "properties": { + "name": { + "description": "Name that identifies this Metric Group.", + "$ref": "../../type/basic.json#/definitions/entityName" + }, + "displayName": { + "description": "Display Name that identifies this Metric Group.", + "type": "string" + }, + "description": { + "description": "Description of the Metric Group.", + "$ref": "../../type/basic.json#/definitions/markdown" + }, + "metrics": { + "description": "Fully qualified names of the metrics that belong to this group.", + "type": "array", + "items": { + "$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName" + }, + "default": null + }, + "owners": { + "description": "Owners of this Metric Group.", + "$ref": "../../type/entityReferenceList.json", + "default": null + }, + "tags": { + "description": "Tags for this Metric Group.", + "type": "array", + "items": { + "$ref": "../../type/tagLabel.json" + }, + "default": null + }, + "domains": { + "description": "Fully qualified names of the domains the Metric Group belongs to.", + "type": "array", + "items": { + "type": "string" + } + }, + "dataProducts": { + "description": "List of fully qualified names of data products this entity is part of.", + "type": "array", + "items": { + "$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName" + } + }, + "extension": { + "description": "Entity extension data with custom attributes added to the entity.", + "$ref": "../../type/basic.json#/definitions/entityExtension" + }, + "provider": { + "$ref": "../../type/basic.json#/definitions/providerType" + } + }, + "required": ["name"], + "additionalProperties": false +} diff --git a/openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyContext.json b/openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyContext.json new file mode 100644 index 000000000000..f493bca6286d --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyContext.json @@ -0,0 +1,46 @@ +{ + "$id": "https://open-metadata.org/schema/api/data/metricHierarchyContext.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MetricHierarchyContext", + "description": "Hierarchy context for one Metric detail page.", + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricHierarchyContext", + "properties": { + "group": { + "description": "Metric Group containing the hierarchy, when grouped.", + "$ref": "../../entity/data/metricGroup.json" + }, + "current": { + "description": "Current Metric.", + "$ref": "../../entity/data/metric.json" + }, + "ancestors": { + "description": "Ancestors ordered from the hierarchy root to the current Metric's parent.", + "type": "array", + "items": { "$ref": "../../entity/data/metric.json" }, + "default": [] + }, + "siblings": { + "description": "Page of Metrics with the same parent as the current Metric.", + "type": "array", + "items": { "$ref": "../../entity/data/metric.json" }, + "default": [] + }, + "children": { + "description": "Page of immediate child Metrics.", + "type": "array", + "items": { "$ref": "../../entity/data/metric.json" }, + "default": [] + }, + "siblingPaging": { + "description": "Offset paging for siblings.", + "$ref": "../../type/paging.json" + }, + "childrenPaging": { + "description": "Offset paging for immediate children.", + "$ref": "../../type/paging.json" + } + }, + "required": ["current", "siblingPaging", "childrenPaging"], + "additionalProperties": false +} diff --git a/openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyItem.json b/openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyItem.json new file mode 100644 index 000000000000..03ccf65d77bc --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/api/data/metricHierarchyItem.json @@ -0,0 +1,46 @@ +{ + "$id": "https://open-metadata.org/schema/api/data/metricHierarchyItem.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MetricHierarchyItem", + "description": "Typed entries and detail context used to browse the Metric hierarchy.", + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricHierarchyItem", + "definitions": { + "kind": { + "description": "Kind of top-level hierarchy entry.", + "type": "string", + "enum": ["metricGroup", "metric"] + } + }, + "properties": { + "kind": { + "$ref": "#/definitions/kind" + }, + "group": { + "description": "Top-level Metric Group when kind is metricGroup.", + "$ref": "../../entity/data/metricGroup.json" + }, + "metric": { + "description": "Standalone root Metric when kind is metric.", + "$ref": "../../entity/data/metric.json" + } + }, + "oneOf": [ + { + "properties": { + "kind": { "const": "metricGroup" } + }, + "required": ["group"], + "not": { "required": ["metric"] } + }, + { + "properties": { + "kind": { "const": "metric" } + }, + "required": ["metric"], + "not": { "required": ["group"] } + } + ], + "required": ["kind"], + "additionalProperties": false +} diff --git a/openmetadata-spec/src/main/resources/json/schema/api/data/metricObservability.json b/openmetadata-spec/src/main/resources/json/schema/api/data/metricObservability.json new file mode 100644 index 000000000000..ab9b07708d25 --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/api/data/metricObservability.json @@ -0,0 +1,313 @@ +{ + "$id": "https://open-metadata.org/schema/api/data/metricObservability.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MetricObservability", + "description": "Server-computed health rollup for a Metric, derived from the data quality of the assets the metric is computed on.", + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricObservability", + "definitions": { + "metricAssetDirection": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricAssetDirection", + "description": "A data asset linked to a metric, annotated with where it sits relative to the metric in the lineage graph.", + "properties": { + "asset": { + "description": "The linked data asset.", + "$ref": "../../type/entityReference.json" + }, + "direction": { + "description": "Where the asset sits relative to the metric. `upstream` assets feed the metric and drive its health, `downstream` assets consume it, and `unrelated` assets are linked but have no lineage edge to the metric.", + "type": "string", + "enum": ["upstream", "downstream", "unrelated"], + "default": "unrelated" + }, + "affectsHealth": { + "description": "True only for a direct upstream Table, the sources included in Metric health.", + "type": "boolean", + "default": false + } + }, + "required": ["asset", "direction"], + "additionalProperties": false + }, + "health": { + "javaType": "org.openmetadata.schema.type.MetricHealth", + "description": "Overall health band for a metric.", + "type": "string", + "enum": ["Healthy", "AtRisk", "Degraded", "Unknown"] + }, + "dimensionRollup": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricDimensionRollup", + "description": "Data quality test results for one quality dimension, aggregated across the metric's upstream assets.", + "properties": { + "dimension": { + "description": "Name of the data quality dimension, for example Completeness or Accuracy.", + "type": "string" + }, + "total": { + "description": "Number of tests evaluated in this dimension.", + "type": "integer" + }, + "passed": { + "description": "Number of tests that passed.", + "type": "integer" + }, + "failed": { + "description": "Number of tests with a Failed terminal result.", + "type": "integer" + }, + "aborted": { + "description": "Number of terminal tests that aborted.", + "type": "integer" + }, + "score": { + "description": "Pass rate for this dimension as a percentage.", + "type": "number", + "minimum": 0, + "maximum": 100 + } + }, + "required": ["dimension", "total", "passed", "failed", "score"], + "additionalProperties": false + }, + "assetRollup": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricAssetRollup", + "description": "Health contribution of a single upstream asset.", + "properties": { + "asset": { + "description": "The upstream data asset.", + "$ref": "../../type/entityReference.json" + }, + "score": { + "description": "Pass rate for this asset as a percentage. Absent when the asset has no data quality tests.", + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "health": { + "description": "Health band for this asset.", + "$ref": "#/definitions/health" + }, + "total": { + "description": "Number of tests evaluated on this asset.", + "type": "integer" + }, + "failed": { + "description": "Number of tests with a Failed terminal result on this asset.", + "type": "integer" + }, + "passed": { + "description": "Number of successful terminal tests on this asset.", + "type": "integer" + }, + "aborted": { + "description": "Number of aborted terminal tests on this asset.", + "type": "integer" + }, + "latestRunTime": { + "description": "Most recent included terminal result on this asset.", + "$ref": "../../type/basic.json#/definitions/timestamp" + }, + "redacted": { + "description": "True when the caller can see the aggregate contribution but not this source's identity or details.", + "type": "boolean", + "default": false + } + }, + "required": ["asset", "health"], + "additionalProperties": false + }, + "testResult": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricTestResult", + "description": "A single data quality test contributing to the rollup.", + "properties": { + "testCase": { + "description": "The test case.", + "$ref": "../../type/entityReference.json" + }, + "asset": { + "description": "The asset the test runs against.", + "$ref": "../../type/entityReference.json" + }, + "dimension": { + "description": "Data quality dimension the test belongs to.", + "type": "string" + }, + "status": { + "description": "Result of the most recent run.", + "type": "string" + }, + "timestamp": { + "description": "When the most recent run completed.", + "$ref": "../../type/basic.json#/definitions/timestamp" + } + }, + "required": ["testCase"], + "additionalProperties": false + }, + "incident": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricIncident", + "description": "An unresolved data quality incident on one of the metric's upstream assets.", + "properties": { + "id": { + "description": "Identifier of the incident.", + "$ref": "../../type/basic.json#/definitions/uuid" + }, + "testCase": { + "description": "The test case that raised the incident.", + "$ref": "../../type/entityReference.json" + }, + "asset": { + "description": "The asset the incident is on.", + "$ref": "../../type/entityReference.json" + }, + "severity": { + "description": "Severity assigned to the incident.", + "type": "string" + }, + "status": { + "description": "Current resolution status.", + "type": "string" + }, + "timestamp": { + "description": "When the incident was raised.", + "$ref": "../../type/basic.json#/definitions/timestamp" + } + }, + "required": ["testCase"], + "additionalProperties": false + }, + "statusCounts": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricTestStatusCounts", + "description": "Global latest-result counts used to compute the Metric score.", + "properties": { + "passed": { "type": "integer" }, + "failed": { "type": "integer" }, + "aborted": { "type": "integer" }, + "queued": { "type": "integer" }, + "missing": { "type": "integer" }, + "terminal": { "type": "integer" } + }, + "required": ["passed", "failed", "aborted", "queued", "missing", "terminal"], + "additionalProperties": false + }, + "sourceCoverage": { + "type": "object", + "javaType": "org.openmetadata.schema.api.data.MetricSourceCoverage", + "description": "Coverage and redaction information for direct upstream tables.", + "properties": { + "upstreamTables": { "type": "integer" }, + "testedTables": { "type": "integer" }, + "visibleTables": { "type": "integer" }, + "restrictedTables": { "type": "integer" }, + "coveragePercent": { "type": "number", "minimum": 0, "maximum": 100 }, + "partial": { "type": "boolean", "default": false } + }, + "required": ["upstreamTables", "testedTables", "visibleTables", "restrictedTables", "coveragePercent", "partial"], + "additionalProperties": false + }, + "reasonCode": { + "javaType": "org.openmetadata.schema.api.data.MetricObservabilityReasonCode", + "description": "Stable code localized by API clients.", + "type": "string", + "enum": ["NoLinkedAssets", "NoUpstreamTables", "NoTerminalResults", "Healthy", "AtRisk", "Degraded", "Unavailable", "PartialDetails"] + } + }, + "properties": { + "metric": { + "description": "The metric this rollup describes.", + "$ref": "../../type/entityReference.json" + }, + "health": { + "description": "Overall health band. Unknown when no upstream asset carries a data quality test.", + "$ref": "#/definitions/health" + }, + "score": { + "description": "Overall score as a percentage. Absent when health is Unknown.", + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "rollupReason": { + "description": "Backward-compatible server explanation. Clients should localize reasonCode.", + "type": "string" + }, + "reasonCode": { + "$ref": "#/definitions/reasonCode" + }, + "statusCounts": { + "$ref": "#/definitions/statusCounts" + }, + "sourceCoverage": { + "$ref": "#/definitions/sourceCoverage" + }, + "latestRunTime": { + "description": "Most recent included terminal result across all direct upstream tables.", + "$ref": "../../type/basic.json#/definitions/timestamp" + }, + "partial": { + "description": "True when detail rows are redacted for one or more sources while global aggregates remain complete.", + "type": "boolean", + "default": false + }, + "dimensions": { + "description": "Per-dimension breakdown of the contributing tests.", + "type": "array", + "items": { + "$ref": "#/definitions/dimensionRollup" + }, + "default": [] + }, + "assets": { + "description": "Per-asset breakdown of the contributing upstream assets.", + "type": "array", + "items": { + "$ref": "#/definitions/assetRollup" + }, + "default": [] + }, + "linkedAssets": { + "description": "Every asset linked to the metric, annotated with its lineage direction. Only the upstream ones contribute to the score, so this is what explains an asset's absence from `assets`.", + "type": "array", + "items": { + "$ref": "#/definitions/metricAssetDirection" + }, + "default": [] + }, + "tests": { + "description": "The individual test results behind the rollup.", + "type": "array", + "items": { + "$ref": "#/definitions/testResult" + }, + "default": [] + }, + "incidents": { + "description": "Unresolved incidents on the metric's upstream assets.", + "type": "array", + "items": { + "$ref": "#/definitions/incident" + }, + "default": [] + }, + "upstreamAssetCount": { + "description": "Number of upstream assets linked to the metric.", + "type": "integer" + }, + "evaluatedAssetCount": { + "description": "Number of upstream assets that carried at least one data quality test and therefore contributed to the score.", + "type": "integer" + }, + "evaluatedAt": { + "description": "When this rollup was computed.", + "$ref": "../../type/basic.json#/definitions/timestamp" + } + }, + "required": ["health"], + "additionalProperties": false +} diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/data/metric.json b/openmetadata-spec/src/main/resources/json/schema/entity/data/metric.json index a30da74ea4b3..e1a3d61e34fb 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/data/metric.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/data/metric.json @@ -241,6 +241,22 @@ "description": "Related Metrics.", "$ref": "../../type/entityReferenceList.json" }, + "parent": { + "description": "Parent metric this metric is a variant of. Metric fully qualified names stay flat, so the hierarchy is tracked purely through CONTAINS relationships and reparenting never rewrites the fully qualified name.", + "$ref": "../../type/entityReference.json" + }, + "metricGroup": { + "description": "Metric Group this metric belongs to, if any. A group organizes metrics for browsing; membership is a relationship, so it is derived on read and never stored on the metric.", + "$ref": "../../type/entityReference.json" + }, + "children": { + "description": "Immediate child metrics (variants) of this metric.", + "$ref": "../../type/entityReferenceList.json" + }, + "childrenCount": { + "description": "Count of immediate, non-deleted child metrics. Computed on read and never stored.", + "type": "integer" + }, "assets": { "description": "Data assets (tables, columns, dashboards, etc.) this metric is computed on or applies to. Establishes a first-class metric-to-asset relationship so the metric can be surfaced as context for those assets.", "$ref": "../../type/entityReferenceList.json" @@ -269,6 +285,11 @@ "description": "Owners of this metrics.", "$ref": "../../type/entityReferenceList.json" }, + "experts": { + "description": "Users who are experts in this Metric.", + "$ref": "../../type/entityReferenceList.json", + "default": null + }, "reviewers": { "description": "Reviewers of this Metric.", "$ref": "../../type/entityReferenceList.json" diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/data/metricGroup.json b/openmetadata-spec/src/main/resources/json/schema/entity/data/metricGroup.json new file mode 100644 index 000000000000..f37eee9e0211 --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/entity/data/metricGroup.json @@ -0,0 +1,119 @@ +{ + "$id": "https://open-metadata.org/schema/entity/data/metricGroup.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MetricGroup", + "description": "A named collection of Metrics, such as `Profitability` or `Supply Chain`. A Metric Group organizes related metrics for browsing and governance; it holds metrics without owning them, so deleting a group leaves its metrics intact and merely ungrouped.", + "$comment": "@om-entity-type", + "type": "object", + "javaType": "org.openmetadata.schema.entity.data.MetricGroup", + "javaInterfaces": ["org.openmetadata.schema.EntityInterface"], + "properties": { + "id": { + "description": "Unique identifier that identifies this Metric Group instance.", + "$ref": "../../type/basic.json#/definitions/uuid" + }, + "name": { + "description": "Name that identifies this Metric Group uniquely.", + "$ref": "../../type/basic.json#/definitions/entityName" + }, + "fullyQualifiedName": { + "description": "A unique name that identifies a Metric Group. Metric Groups do not nest, so this is the bare name.", + "$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName" + }, + "displayName": { + "description": "Display Name that identifies this Metric Group.", + "type": "string" + }, + "description": { + "description": "Description of the Metric Group, summarising what the metrics inside it have in common.", + "$ref": "../../type/basic.json#/definitions/markdown" + }, + "metrics": { + "description": "Metrics that belong to this group. This relationship-derived field is used internally for mutations and is exposed to clients only through the authorized, paginated `/v1/metricGroups/{id}/metrics` endpoint.", + "readOnly": true, + "$ref": "../../type/entityReferenceList.json" + }, + "metricCount": { + "description": "Count of non-deleted metrics in this group. Computed on read and never stored.", + "readOnly": true, + "type": "integer" + }, + "version": { + "description": "Metadata version of the entity.", + "$ref": "../../type/entityHistory.json#/definitions/entityVersion" + }, + "updatedAt": { + "description": "Last update time corresponding to the new version of the entity in Unix epoch time milliseconds.", + "$ref": "../../type/basic.json#/definitions/timestamp" + }, + "updatedBy": { + "description": "User who made the update.", + "type": "string" + }, + "impersonatedBy": { + "description": "Bot user that performed the action on behalf of the actual user.", + "$ref": "../../type/basic.json#/definitions/impersonatedBy" + }, + "href": { + "description": "Link to the resource corresponding to this entity.", + "$ref": "../../type/basic.json#/definitions/href" + }, + "owners": { + "description": "Owners of this Metric Group.", + "$ref": "../../type/entityReferenceList.json" + }, + "followers": { + "description": "Followers of this Metric Group.", + "$ref": "../../type/entityReferenceList.json" + }, + "tags": { + "description": "Tags for this Metric Group.", + "type": "array", + "items": { + "$ref": "../../type/tagLabel.json" + }, + "default": [] + }, + "changeDescription": { + "description": "Change that lead to this version of the entity.", + "$ref": "../../type/entityHistory.json#/definitions/changeDescription" + }, + "incrementalChangeDescription": { + "description": "Change that lead to this version of the entity.", + "$ref": "../../type/entityHistory.json#/definitions/changeDescription" + }, + "deleted": { + "description": "When `true` indicates the entity has been soft deleted.", + "type": "boolean", + "default": false + }, + "domains": { + "description": "Domains the Metric Group belongs to.", + "$ref": "../../type/entityReferenceList.json" + }, + "dataProducts": { + "description": "List of data products this entity is part of.", + "$ref": "../../type/entityReferenceList.json" + }, + "votes": { + "description": "Votes on the entity.", + "$ref": "../../type/votes.json" + }, + "extension": { + "description": "Entity extension data with custom attributes added to the entity.", + "$ref": "../../type/basic.json#/definitions/entityExtension" + }, + "certification": { + "$ref": "../../type/assetCertification.json" + }, + "entityStatus": { + "description": "Status of the Metric Group.", + "$ref": "../../type/status.json" + }, + "provider": { + "$ref": "../../type/basic.json#/definitions/providerType" + } + }, + "required": ["id", "name"], + "additionalProperties": false +} diff --git a/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.test.tsx b/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.test.tsx new file mode 100644 index 000000000000..cb7873977436 --- /dev/null +++ b/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.test.tsx @@ -0,0 +1,56 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import { render, screen, within } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { Table } from './table'; + +describe('Table', () => { + it('can omit the selection cell for a full-width synthetic row', () => { + render( + + + + + + + + Gross margin + Margin after costs + + + Profitability + + +
+ ); + + const metricRow = screen.getByText('Gross margin').closest('tr'); + const groupRow = screen.getByText('Profitability').closest('tr'); + + expect(metricRow).not.toBeNull(); + expect(groupRow).not.toBeNull(); + expect( + within(metricRow as HTMLElement).getByRole('checkbox') + ).toBeVisible(); + expect( + within(groupRow as HTMLElement).queryByRole('checkbox') + ).not.toBeInTheDocument(); + expect(screen.getByText('Profitability').closest('td')).toHaveAttribute( + 'colspan', + '3' + ); + }); +}); diff --git a/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.tsx b/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.tsx index 3eac5ae844c4..05542e5eb5d8 100644 --- a/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.tsx +++ b/openmetadata-ui-core-components/src/main/resources/ui/src/components/application/table/table.tsx @@ -326,6 +326,8 @@ interface TableRowProps 'children' | 'className' | 'onClick' | 'slot' | 'style' | 'id' > { highlightSelectedRow?: boolean; + /** Omits the selection cell when a synthetic row spans the full table. */ + hideSelectionCell?: boolean; } const TableRow = ({ @@ -333,6 +335,7 @@ const TableRow = ({ children, className, highlightSelectedRow = true, + hideSelectionCell = false, ...props }: TableRowProps) => { const { size } = useContext(TableContext); @@ -353,7 +356,7 @@ const TableRow = ({ typeof className === 'function' ? className(state) : className ) }> - {selectionBehavior === 'toggle' && ( + {selectionBehavior === 'toggle' && !hideSelectionCell && ( { + if (!value) { + throw new Error(`${fixtureName} was not created`); + } + + return value; +}; + +const verifyDisabledMetricMetadataRules = async ( + page: Page, + apiContext: APIRequestContext, + metric: MetricClass +) => { + const metricId = requireFixtureValue(metric.entityResponseData.id, 'Metric'); + const firstUserName = user.getUserDisplayName(); + const secondUserName = user2.getUserDisplayName(); + const teamName = requireFixtureValue(team.responseData.displayName, 'Team'); + const firstDomainName = requireFixtureValue( + domain.responseData.displayName, + 'First domain' + ); + const secondDomainName = requireFixtureValue( + domain2.responseData.displayName, + 'Second domain' + ); + const firstDataProductName = requireFixtureValue( + createdDataProducts[0]?.responseData.displayName, + 'First data product' + ); + const secondDataProductName = requireFixtureValue( + createdDataProducts[1]?.responseData.displayName, + 'Second data product' + ); + const firstGlossaryTermName = requireFixtureValue( + glossaryTerm.responseData.displayName, + 'First glossary term' + ); + const secondGlossaryTermName = requireFixtureValue( + glossaryTerm2.responseData.displayName, + 'Second glossary term' + ); + const dialog = await openMetricMetadataEditor(page); + + await selectMetricMetadataReference(dialog, 'Owners', firstUserName); + await selectMetricMetadataReference(dialog, 'Owners', secondUserName); + const ownersGroup = await selectMetricMetadataReference( + dialog, + 'Owners', + teamName + ); + await expectMetricMetadataSelections(ownersGroup, [ + firstUserName, + secondUserName, + teamName, + ]); + + await selectMetricMetadataReference(dialog, 'Domains', firstDomainName); + const domainsGroup = await selectMetricMetadataReference( + dialog, + 'Domains', + secondDomainName + ); + await expectMetricMetadataSelections(domainsGroup, [ + firstDomainName, + secondDomainName, + ]); + + await selectMetricMetadataReference( + dialog, + 'Data Products', + firstDataProductName + ); + const dataProductsGroup = await selectMetricMetadataReference( + dialog, + 'Data Products', + secondDataProductName + ); + await expectMetricMetadataSelections(dataProductsGroup, [ + firstDataProductName, + secondDataProductName, + ]); + + await selectMetricMetadataReference( + dialog, + 'Glossary Terms', + firstGlossaryTermName + ); + const glossaryTermsGroup = await selectMetricMetadataReference( + dialog, + 'Glossary Terms', + secondGlossaryTermName + ); + await expectMetricMetadataSelections(glossaryTermsGroup, [ + firstGlossaryTermName, + secondGlossaryTermName, + ]); + + await saveMetricMetadata(page, dialog, metricId); + + const persisted = await getPersistedMetricMetadata(apiContext, metricId); + expect(persisted.owners?.map(({ id }) => id).sort()).toEqual( + [ + requireFixtureValue(user.responseData.id, 'First user'), + requireFixtureValue(user2.responseData.id, 'Second user'), + requireFixtureValue(team.responseData.id, 'Team'), + ].sort() + ); + expect(persisted.domains?.map(({ id }) => id).sort()).toEqual( + [ + requireFixtureValue(domain.responseData.id, 'First domain'), + requireFixtureValue(domain2.responseData.id, 'Second domain'), + ].sort() + ); + expect(persisted.dataProducts?.map(({ id }) => id).sort()).toEqual( + [ + requireFixtureValue( + createdDataProducts[0]?.responseData.id, + 'First data product' + ), + requireFixtureValue( + createdDataProducts[1]?.responseData.id, + 'Second data product' + ), + ].sort() + ); + expect(persisted.tags?.map(({ tagFQN }) => tagFQN)).toEqual( + expect.arrayContaining([ + requireFixtureValue( + glossaryTerm.responseData.fullyQualifiedName, + 'First glossary term' + ), + requireFixtureValue( + glossaryTerm2.responseData.fullyQualifiedName, + 'Second glossary term' + ), + ]) + ); + + const metadataRail = page.getByTestId('metric-metadata-rail'); + for (const referenceName of [ + firstUserName, + secondUserName, + teamName, + firstDomainName, + secondDomainName, + firstDataProductName, + secondDataProductName, + firstGlossaryTermName, + secondGlossaryTermName, + ]) { + await expect(metadataRail).toContainText(referenceName); + } +}; + test.beforeAll('Setup pre-requests', async ({ browser }) => { test.slow(true); @@ -173,6 +337,19 @@ test.describe( const { apiContext, afterAction } = await performAdminLogin(browser); await entity.create(apiContext); + + if (entity instanceof MetricClass) { + try { + await redirectToHomePage(page); + await entity.visitEntityPage(page); + await verifyDisabledMetricMetadataRules(page, apiContext, entity); + } finally { + await afterAction(); + } + + return; + } + await afterAction(); await redirectToHomePage(page); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataAssetRulesEnabled.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataAssetRulesEnabled.spec.ts index b5f881f39982..9ec5d04d8b7d 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataAssetRulesEnabled.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/DataAssetRulesEnabled.spec.ts @@ -10,7 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { expect } from '@playwright/test'; +import { expect, type APIRequestContext, type Page } from '@playwright/test'; import { DataProduct } from '../../support/domain/DataProduct'; import { Domain } from '../../support/domain/Domain'; import { ApiCollectionClass } from '../../support/entity/ApiCollectionClass'; @@ -54,6 +54,13 @@ import { assignGlossaryTerm, waitForAllLoadersToDisappear, } from '../../utils/entity'; +import { + expectMetricMetadataSelections, + getPersistedMetricMetadata, + openMetricMetadataEditor, + saveMetricMetadata, + selectMetricMetadataReference, +} from '../../utils/metricMetadata'; import { test } from '../fixtures/pages'; const entities = [ @@ -101,6 +108,119 @@ const glossary = new Glossary(); const glossaryTerm = new GlossaryTerm(glossary); const glossaryTerm2 = new GlossaryTerm(glossary); +const requireFixtureValue = ( + value: string | undefined, + fixtureName: string +) => { + if (!value) { + throw new Error(`${fixtureName} was not created`); + } + + return value; +}; + +const verifyEnabledMetricMetadataRules = async ( + page: Page, + apiContext: APIRequestContext, + metric: MetricClass +) => { + const metricId = requireFixtureValue(metric.entityResponseData.id, 'Metric'); + const firstUserName = user.getUserDisplayName(); + const secondUserName = user2.getUserDisplayName(); + const teamName = requireFixtureValue(team.responseData.displayName, 'Team'); + const firstDomainName = requireFixtureValue( + domain.responseData.displayName, + 'First domain' + ); + const secondDomainName = requireFixtureValue( + domain2.responseData.displayName, + 'Second domain' + ); + const firstDataProductName = requireFixtureValue( + createdDataProducts[0]?.responseData.displayName, + 'First data product' + ); + const secondDataProductName = requireFixtureValue( + createdDataProducts[1]?.responseData.displayName, + 'Second data product' + ); + const dialog = await openMetricMetadataEditor(page); + + let ownersGroup = await selectMetricMetadataReference( + dialog, + 'Owners', + firstUserName + ); + ownersGroup = await selectMetricMetadataReference( + dialog, + 'Owners', + secondUserName + ); + await expectMetricMetadataSelections(ownersGroup, [ + firstUserName, + secondUserName, + ]); + ownersGroup = await selectMetricMetadataReference(dialog, 'Owners', teamName); + await expectMetricMetadataSelections( + ownersGroup, + [teamName], + [firstUserName, secondUserName] + ); + + await selectMetricMetadataReference(dialog, 'Domains', secondDomainName); + const domainsGroup = await selectMetricMetadataReference( + dialog, + 'Domains', + firstDomainName + ); + await expectMetricMetadataSelections( + domainsGroup, + [firstDomainName], + [secondDomainName] + ); + + await selectMetricMetadataReference( + dialog, + 'Data Products', + firstDataProductName + ); + const dataProductsGroup = await selectMetricMetadataReference( + dialog, + 'Data Products', + secondDataProductName + ); + await expectMetricMetadataSelections( + dataProductsGroup, + [secondDataProductName], + [firstDataProductName] + ); + + await saveMetricMetadata(page, dialog, metricId); + + const persisted = await getPersistedMetricMetadata(apiContext, metricId); + expect(persisted.owners?.map(({ id }) => id)).toEqual([ + requireFixtureValue(team.responseData.id, 'Team'), + ]); + expect(persisted.domains?.map(({ id }) => id)).toEqual([ + requireFixtureValue(domain.responseData.id, 'First domain'), + ]); + expect(persisted.dataProducts?.map(({ id }) => id)).toEqual([ + requireFixtureValue( + createdDataProducts[1]?.responseData.id, + 'Second data product' + ), + ]); + + const metadataRail = page.getByTestId('metric-metadata-rail'); + await expect(metadataRail).toContainText(teamName); + await expect(metadataRail).not.toContainText(firstUserName); + await expect(metadataRail).not.toContainText(secondUserName); + await expect(metadataRail).toContainText(firstDomainName); + await expect(metadataRail).not.toContainText(secondDomainName); + await expect(metadataRail).toContainText(secondDataProductName); + await expect(metadataRail).not.toContainText(firstDataProductName); +}; + test.beforeAll('Setup pre-requests', async ({ browser }) => { test.slow(true); @@ -155,6 +275,19 @@ test.describe( const { apiContext, afterAction } = await performAdminLogin(browser); await entity.create(apiContext); + + if (entity instanceof MetricClass) { + try { + await authenticateAdminPage(page); + await entity.visitEntityPage(page); + await verifyEnabledMetricMetadataRules(page, apiContext, entity); + } finally { + await afterAction(); + } + + return; + } + await afterAction(); await authenticateAdminPage(page); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Glossary/GlossaryApprovalAfterMove.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Glossary/GlossaryApprovalAfterMove.spec.ts index 45c590415e59..2eb721473360 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Glossary/GlossaryApprovalAfterMove.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/Glossary/GlossaryApprovalAfterMove.spec.ts @@ -392,12 +392,30 @@ test.describe( const taskResolve = waitForTaskResolveResponse(reviewerPage); await rejectButton.click(); - await taskResolve; - - await toastNotification( - reviewerPage, - /Task resolved successfully|Vote recorded/ - ); + const rejectDialog = reviewerPage.getByRole('dialog', { + name: 'Reject', + }); + const requiresComment = await Promise.race([ + rejectDialog + .waitFor({ state: 'visible' }) + .then(() => true as const), + taskResolve.then(() => false as const), + ]); + + if (requiresComment) { + await rejectDialog + .getByRole('textbox', { name: 'Comment *' }) + .fill('Rejected after moving the parent glossary term'); + + const confirmReject = rejectDialog.getByRole('button', { + name: 'Reject', + exact: true, + }); + await expect(confirmReject).toBeEnabled(); + await confirmReject.click(); + } + + expect((await taskResolve).ok()).toBe(true); }); await test.step('Verify term reaches Rejected status and zero remaining open tasks', async () => { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricActivityTasks.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricActivityTasks.spec.ts new file mode 100644 index 000000000000..9db3ca8da7bf --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricActivityTasks.spec.ts @@ -0,0 +1,424 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import { APIRequestContext, expect, test } from '@playwright/test'; +import { PLAYWRIGHT_BASIC_TEST_TAG_OBJ } from '../../constant/config'; +import { MetricClass } from '../../support/entity/MetricClass'; +import { UserClass } from '../../support/user/UserClass'; +import { performAdminLogin } from '../../utils/admin'; +import { uuid } from '../../utils/common'; +import { performUserLogin } from '../../utils/user'; + +interface AdminUser { + displayName?: string; + fullyQualifiedName?: string; + id: string; + name: string; +} + +interface CreatedThread { + id: string; + message: string; +} + +interface MetricResponse { + description?: string; +} + +interface TaskComment { + message: string; +} + +interface TaskResponse { + availableTransitions?: Array<{ id: string }>; + comments?: TaskComment[]; + id: string; + status: string; +} + +interface TaskCounts { + approved?: number; + completed?: number; + open?: number; + total?: number; +} + +const waitForOpenApprovalTask = async ( + apiContext: APIRequestContext, + metricFqn: string +) => { + let taskId = ''; + + await expect + .poll( + async () => { + const response = await apiContext.get('/api/v1/tasks', { + params: { + aboutEntity: metricFqn, + fields: + 'assignees,availableTransitions,createdBy,resolution,reviewers', + limit: 10, + status: 'Open', + type: 'RequestApproval', + }, + }); + if (!response.ok()) { + return ''; + } + const taskList = (await response.json()) as { + data?: Array<{ id?: number | string }>; + }; + taskId = String(taskList.data?.[0]?.id ?? ''); + + return taskId; + }, + { intervals: [1_000, 2_000, 5_000], timeout: 120_000 } + ) + .not.toBe(''); + + return taskId; +}; + +test.describe( + 'Metric Activity and Tasks', + PLAYWRIGHT_BASIC_TEST_TAG_OBJ, + () => { + test('creates a mentioned conversation and completes a description task', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin( + browser, + { navigate: true } + ); + const metric = new MetricClass(); + const commentText = `Please validate this metric definition ${uuid()}`; + const taskTitle = `Clarify metric definition ${uuid()}`; + const proposedDescription = `Governed metric definition ${uuid()}`; + const taskComment = `Definition reviewed ${uuid()}`; + const resolutionNote = `Approved through the metric activity workflow ${uuid()}`; + let threadId: string | undefined; + let taskId: string | undefined; + + try { + const adminResponse = await apiContext.get('/api/v1/users/name/admin'); + expect(adminResponse.ok()).toBeTruthy(); + const admin = (await adminResponse.json()) as AdminUser; + const adminFqn = admin.fullyQualifiedName ?? admin.name; + const adminLabel = admin.displayName ?? admin.name; + + await metric.create(apiContext); + expect(metric.entityResponseData.id).toBeTruthy(); + const metricFqn = metric.entityResponseData.fullyQualifiedName; + + await metric.visitEntityPage(page); + await page.getByTestId('activity_feed').click(); + + const activityTab = page.getByTestId('metric-activity-tab'); + await expect(activityTab).toBeVisible(); + + const composer = activityTab + .getByTestId('metric-activity-composer') + .getByRole('textbox'); + await composer.fill(`Review with @${admin.name}`); + + const mentionSuggestion = page.getByTestId( + `metric-mention-suggestion-${admin.id}` + ); + await expect(mentionSuggestion).toBeVisible(); + await mentionSuggestion.click(); + + const selectedMention = await composer.inputValue(); + expect(selectedMention).toContain( + `<#E::user::${adminFqn}|@${adminLabel}>` + ); + await composer.fill(`${selectedMention}${commentText}`); + + const createThreadResponsePromise = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'POST' && + url.pathname === '/api/v1/conversations' + ); + }); + await activityTab + .getByTestId('metric-activity-composer-submit') + .click(); + const createThreadResponse = await createThreadResponsePromise; + expect(createThreadResponse.ok()).toBeTruthy(); + const thread = (await createThreadResponse.json()) as CreatedThread; + threadId = thread.id; + expect(thread.message).toContain( + `<#E::user::${adminFqn}|@${adminLabel}>` + ); + expect(thread.message).toContain(commentText); + + const threadCard = page.getByTestId( + `metric-activity-item-${thread.id}` + ); + await expect(threadCard).toBeVisible(); + await expect(threadCard).toContainText(commentText); + + const tasksTab = activityTab.getByRole('tab', { name: /Tasks/ }); + await tasksTab.click(); + await page.getByTestId('metric-task-create').click(); + + const taskDialog = page.getByTestId('metric-task-create-dialog'); + await expect(taskDialog).toBeVisible(); + await taskDialog + .getByTestId('metric-task-create-title') + .fill(taskTitle); + await taskDialog + .getByTestId('metric-task-create-assignees-search') + .fill(admin.name); + const assigneeCheckbox = taskDialog.getByRole('checkbox', { + exact: true, + name: adminLabel, + }); + await assigneeCheckbox.focus(); + await assigneeCheckbox.press('Space'); + await expect(assigneeCheckbox).toBeChecked(); + await taskDialog + .getByTestId('metric-task-create-value') + .getByRole('textbox') + .fill(proposedDescription); + + const createTaskResponsePromise = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'POST' && + url.pathname === '/api/v1/tasks' + ); + }); + await taskDialog.getByTestId('metric-task-create-submit').click(); + const createTaskResponse = await createTaskResponsePromise; + expect(createTaskResponse.ok()).toBeTruthy(); + const createdTask = (await createTaskResponse.json()) as TaskResponse; + taskId = createdTask.id; + expect(createdTask.status).toBe('Open'); + + const taskCard = page.getByTestId(`metric-task-item-${createdTask.id}`); + const taskListItem = taskCard.locator('xpath=ancestor::li[1]'); + await expect(taskListItem).toBeVisible(); + await expect(taskListItem).toContainText(taskTitle); + await expect(taskListItem).toContainText(adminLabel); + await expect(tasksTab).toContainText('1'); + await taskCard.click(); + + const taskDetail = page.getByTestId('metric-task-detail'); + await expect(taskDetail).toContainText(taskTitle); + + const taskCommentResponsePromise = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'POST' && + url.pathname === `/api/v1/tasks/${createdTask.id}/comments` + ); + }); + await taskDetail + .getByTestId('metric-activity-composer') + .getByRole('textbox') + .fill(taskComment); + await taskDetail.getByTestId('metric-activity-composer-submit').click(); + const taskCommentResponse = await taskCommentResponsePromise; + expect(taskCommentResponse.ok()).toBeTruthy(); + const taskWithComment = + (await taskCommentResponse.json()) as TaskResponse; + expect(taskWithComment.comments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ message: taskComment }), + ]) + ); + + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/tasks/${createdTask.id}`, + { + params: { + fields: 'availableTransitions,comments,payload,resolution', + }, + } + ); + expect(response.ok()).toBeTruthy(); + const task = (await response.json()) as TaskResponse; + + return task.availableTransitions?.some( + (transition) => transition.id === 'approve' + ); + }, + { timeout: 60_000 } + ) + .toBe(true); + + await taskDetail.getByRole('button', { name: 'Close' }).click(); + await activityTab.getByRole('tab', { name: /All Activity/ }).click(); + await tasksTab.click(); + await expect(taskListItem).toBeVisible(); + await taskCard.click(); + await expect(taskDetail).toContainText(taskComment); + + await taskDetail + .getByRole('textbox', { name: 'Note' }) + .fill(resolutionNote); + const resolveTaskResponsePromise = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'POST' && + url.pathname === `/api/v1/tasks/${createdTask.id}/resolve` + ); + }); + await taskDetail.getByRole('button', { name: 'Approve' }).click(); + const resolveTaskResponse = await resolveTaskResponsePromise; + expect(resolveTaskResponse.ok()).toBeTruthy(); + const resolvedTask = (await resolveTaskResponse.json()) as TaskResponse; + expect(resolvedTask.status).toBe('Approved'); + + await expect + .poll(async () => { + const response = await apiContext.get( + `/api/v1/metrics/name/${encodeURIComponent(metricFqn)}` + ); + expect(response.ok()).toBeTruthy(); + + return ((await response.json()) as MetricResponse).description; + }) + .toBe(proposedDescription); + + await expect(taskCard).toBeHidden(); + await expect(tasksTab).toContainText('0'); + await expect + .poll(async () => { + const response = await apiContext.get('/api/v1/tasks/count', { + params: { aboutEntity: metricFqn }, + }); + expect(response.ok()).toBeTruthy(); + + return (await response.json()) as TaskCounts; + }) + .toEqual( + expect.objectContaining({ + approved: 1, + completed: 1, + open: 0, + total: 1, + }) + ); + + await taskDetail.getByRole('button', { name: 'Close' }).click(); + await activityTab.getByRole('button', { name: /Status/ }).click(); + await page.getByRole('option', { exact: true, name: 'Closed' }).click(); + + await expect(taskListItem).toBeVisible(); + await expect(taskListItem).toContainText('Approved'); + await taskCard.click(); + await expect(taskDetail).toContainText(taskComment); + await expect(taskDetail).toContainText(resolutionNote); + } finally { + if (taskId) { + await apiContext.delete(`/api/v1/tasks/${taskId}`, { + params: { hardDelete: 'true' }, + }); + } + if (threadId) { + await apiContext.delete(`/api/v1/conversations/${threadId}`); + } + if (metric.entityResponseData.id) { + await metric.delete(apiContext); + } + await afterAction(); + } + }); + + test('opens an approval request from Tasks in the Approval Workflow tab', async ({ + browser, + }) => { + test.setTimeout(5 * 60 * 1_000); + + const { apiContext, afterAction } = await performAdminLogin(browser); + const metric = new MetricClass(); + const reviewer = new UserClass(undefined, true); + let reviewerAfterAction: (() => Promise) | undefined; + let reviewerCreated = false; + + try { + await reviewer.create(apiContext); + reviewerCreated = true; + + const createResponse = await apiContext.post('/api/v1/metrics', { + data: { + ...metric.entity, + reviewers: [{ id: reviewer.responseData.id, type: 'user' }], + }, + }); + expect(createResponse.status()).toBe(201); + metric.entityResponseData = await createResponse.json(); + + const metricFqn = metric.entityResponseData.fullyQualifiedName; + const approvalTaskId = await waitForOpenApprovalTask( + apiContext, + metricFqn + ); + const reviewerSession = await performUserLogin(browser, reviewer); + reviewerAfterAction = reviewerSession.afterAction; + const reviewerPage = reviewerSession.page; + + await metric.visitEntityPage(reviewerPage); + await reviewerPage.getByTestId('activity_feed').click(); + const activityTab = reviewerPage.getByTestId('metric-activity-tab'); + await expect(activityTab).toBeVisible(); + await activityTab.getByRole('tab', { name: /Tasks/ }).click(); + + const reviewButton = reviewerPage.getByTestId( + `metric-task-review-${approvalTaskId}` + ); + await expect(reviewButton).toBeVisible({ timeout: 60_000 }); + await expect(reviewButton).toHaveText('View Approval Workflow'); + await reviewButton.click(); + + await expect(reviewerPage).toHaveURL( + new RegExp( + `/metric/${encodeURIComponent(metricFqn)}/approval(?:\\?.*)?$` + ) + ); + await expect( + reviewerPage.getByTestId('metric-approval-tab') + ).toBeVisible({ timeout: 60_000 }); + await expect( + reviewerPage.getByTestId('metric-approval-approve-btn') + ).toBeVisible(); + } finally { + try { + await reviewerAfterAction?.(); + } finally { + try { + if (metric.entityResponseData.id) { + await metric.delete(apiContext); + } + } finally { + try { + if (reviewerCreated) { + await reviewer.delete(apiContext); + } + } finally { + await afterAction(); + } + } + } + } + }); + } +); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricGovernance.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricGovernance.spec.ts new file mode 100644 index 000000000000..2031590029d8 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricGovernance.spec.ts @@ -0,0 +1,2384 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import { APIRequestContext, expect, Page, Route, test } from '@playwright/test'; +import { PLAYWRIGHT_BASIC_TEST_TAG_OBJ } from '../../constant/config'; +import { PolicyClass } from '../../support/access-control/PoliciesClass'; +import { RolesClass } from '../../support/access-control/RolesClass'; +import { MetricClass } from '../../support/entity/MetricClass'; +import { TableClass } from '../../support/entity/TableClass'; +import { UserClass } from '../../support/user/UserClass'; +import { performAdminLogin } from '../../utils/admin'; +import { uuid } from '../../utils/common'; +import { connectEdgeBetweenNodesViaAPI } from '../../utils/lineage'; +import { performUserLogin } from '../../utils/user'; + +/** + * Covers the governance surface added to Metric: the approval status a metric starts life with, + * the linked-asset endpoints, and the health rollup — plus the tabs that surface them. + */ + +interface EntityFixture { + id: string; + name: string; + fullyQualifiedName: string; + displayName?: string; + type?: string; +} + +interface MetricApiResponse extends EntityFixture { + description?: string; + entityStatus?: string; +} + +interface ApprovalTaskApiResponse { + about?: EntityFixture; + availableTransitions?: Array<{ + id?: string; + resolutionType?: string; + }>; + id?: number | string; + status?: string; + type?: string; +} + +type ApprovalResolution = 'Approved' | 'Rejected'; + +interface MetricObservabilityApiResponse { + assets: Array<{ + asset: EntityFixture; + failed?: number; + passed?: number; + redacted?: boolean; + score?: number; + }>; + dimensions: Array<{ + dimension: string; + failed: number; + passed: number; + score: number; + total: number; + }>; + health: string; + incidents: Array<{ + asset?: EntityFixture; + redacted?: boolean; + testCase: EntityFixture; + }>; + linkedAssets: Array<{ + asset: EntityFixture; + direction: 'downstream' | 'unrelated' | 'upstream'; + }>; + reasonCode: string; + score?: number; + statusCounts: { + aborted: number; + failed: number; + missing: number; + passed: number; + queued: number; + terminal: number; + }; + sourceCoverage: { + restrictedTables: number; + upstreamTables: number; + visibleTables: number; + }; + tests: Array<{ + asset?: EntityFixture; + dimension?: string; + redacted?: boolean; + status?: string; + testCase: EntityFixture; + }>; + upstreamAssetCount: number; +} + +const createMetric = async ( + apiContext: APIRequestContext, + data: Record +): Promise => { + const response = await apiContext.post('/api/v1/metrics', { data }); + + expect(response.status()).toBe(201); + + return (await response.json()) as MetricApiResponse; +}; + +const createQualityTestCase = async ( + apiContext: APIRequestContext, + data: { + entityLink: string; + name: string; + parameterValues: Array<{ name: string; value: number }>; + testDefinition: string; + } +): Promise => { + const response = await apiContext.post('/api/v1/dataQuality/testCases', { + data, + }); + + expect(response.status()).toBe(201); + + return (await response.json()) as EntityFixture; +}; + +const addQualityTestResult = async ( + apiContext: APIRequestContext, + testCaseFqn: string, + status: 'Failed' | 'Success', + timestamp: number +) => { + const response = await apiContext.post( + `/api/v1/dataQuality/testCases/testCaseResults/${encodeURIComponent( + testCaseFqn + )}`, + { + data: { + result: status, + testCaseStatus: status, + testResultValue: [], + timestamp, + }, + } + ); + + expect(response.ok()).toBeTruthy(); +}; + +const getMetricObservability = async ( + apiContext: APIRequestContext, + metricId: string +): Promise => { + const response = await apiContext.get( + `/api/v1/metrics/${metricId}/observability` + ); + + expect(response.ok()).toBeTruthy(); + + return (await response.json()) as MetricObservabilityApiResponse; +}; + +const expectMetricStatus = async ( + apiContext: APIRequestContext, + metricId: string, + status: string +) => + expect + .poll( + async () => { + const response = await apiContext.get(`/api/v1/metrics/${metricId}`); + const metric = (await response.json()) as MetricApiResponse; + + return metric.entityStatus; + }, + { intervals: [1_000, 2_000, 5_000], timeout: 120_000 } + ) + .toBe(status); + +const waitForOpenApprovalTask = async ( + apiContext: APIRequestContext, + metricFqn: string, + resolution: ApprovalResolution, + previousTaskId?: string +) => { + let taskId = ''; + + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/tasks?aboutEntity=${encodeURIComponent( + metricFqn + )}&type=RequestApproval&status=Open&limit=10&fields=assignees,availableTransitions,createdBy,resolution,reviewers` + ); + if (!response.ok()) { + return ''; + } + const taskList = (await response.json()) as { + data?: ApprovalTaskApiResponse[]; + }; + const task = taskList.data?.find( + (candidate) => + String(candidate.id ?? '') !== previousTaskId && + candidate.availableTransitions?.some( + (transition) => transition.resolutionType === resolution + ) + ); + taskId = String(task?.id ?? ''); + + return taskId; + }, + { + intervals: [1_000, 2_000, 5_000], + timeout: 120_000, + } + ) + .not.toBe(''); + + return taskId; +}; + +const expectAssignedTaskNotification = async ( + apiContext: APIRequestContext, + taskId: string, + metricFqn: string, + status: ApprovalResolution +) => + expect + .poll( + async () => { + const response = await apiContext.get('/api/v1/tasks/assigned', { + params: { + fields: 'about,assignees,createdBy,resolution', + limit: 100, + status, + }, + }); + if (!response.ok()) { + return; + } + const taskList = (await response.json()) as { + data?: ApprovalTaskApiResponse[]; + }; + const notification = taskList.data?.find( + (task) => String(task.id ?? '') === taskId + ); + + return notification + ? { + aboutFqn: notification.about?.fullyQualifiedName, + aboutType: notification.about?.type, + status: notification.status, + taskId: String(notification.id ?? ''), + type: notification.type, + } + : undefined; + }, + { intervals: [1_000, 2_000, 5_000], timeout: 120_000 } + ) + .toEqual({ + aboutFqn: metricFqn, + aboutType: 'metric', + status, + taskId, + type: 'RequestApproval', + }); + +const visitMetricApproval = async ( + page: Page, + metricFqn: string, + expectedAction: 'approve' | 'reject' +) => { + await page.goto(`/metric/${encodeURIComponent(metricFqn)}`, { + waitUntil: 'domcontentloaded', + }); + await expect(page.getByTestId('metric-details-page')).toBeVisible({ + timeout: 60_000, + }); + await page.getByTestId('approval').click(); + await expect( + page.getByTestId(`metric-approval-${expectedAction}-btn`) + ).toBeVisible({ timeout: 60_000 }); +}; + +const resolveApprovalInUi = async ( + page: Page, + taskId: string, + resolution: ApprovalResolution, + note: string +) => { + const action = resolution === 'Approved' ? 'approve' : 'reject'; + const actionButton = page.getByTestId(`metric-approval-${action}-btn`); + + if (resolution === 'Rejected') { + await expect(actionButton).toBeDisabled(); + } + await page + .getByTestId('metric-approval-note') + .getByRole('textbox') + .fill(note); + await expect(actionButton).toBeEnabled(); + + const resolveResponse = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'POST' && + url.pathname.endsWith(`/api/v1/tasks/${taskId}/resolve`) + ); + }); + await actionButton.click(); + expect((await resolveResponse).ok()).toBeTruthy(); +}; + +const patchMetricDescription = async ( + apiContext: APIRequestContext, + metricId: string, + description: string +) => { + const response = await apiContext.patch(`/api/v1/metrics/${metricId}`, { + data: [{ op: 'replace', path: '/description', value: description }], + headers: { 'Content-Type': 'application/json-patch+json' }, + }); + + expect(response.ok()).toBeTruthy(); +}; + +const expectMetricSnapshot = async ( + apiContext: APIRequestContext, + metricId: string, + expected: Pick +) => + expect + .poll( + async () => { + const response = await apiContext.get(`/api/v1/metrics/${metricId}`); + if (!response.ok()) { + return {}; + } + const metric = (await response.json()) as MetricApiResponse; + + return { + description: metric.description, + entityStatus: metric.entityStatus, + }; + }, + { intervals: [1_000, 2_000, 5_000], timeout: 120_000 } + ) + .toEqual(expected); + +const fulfillJson = (route: Route, body: unknown, status = 200) => + route.fulfill({ + body: JSON.stringify(body), + contentType: 'application/json', + status, + }); + +const attachScreenshot = async (page: Page, testId: string, name: string) => { + const target = page.getByTestId(testId); + await expect(target).toBeVisible(); + await page.evaluate(async () => { + await document.fonts.ready; + }); + const firstBounds = await target.boundingBox(); + + expect(firstBounds).not.toBeNull(); + expect(firstBounds?.width).toBeGreaterThan(0); + expect(firstBounds?.height).toBeGreaterThan(0); + + await target.evaluate( + () => + new Promise((resolve) => { + requestAnimationFrame(() => requestAnimationFrame(() => resolve())); + }) + ); + + const stableBounds = await target.boundingBox(); + + expect(stableBounds).not.toBeNull(); + expect( + Math.abs((stableBounds?.x ?? 0) - (firstBounds?.x ?? 0)) + ).toBeLessThanOrEqual(1); + expect( + Math.abs((stableBounds?.y ?? 0) - (firstBounds?.y ?? 0)) + ).toBeLessThanOrEqual(1); + expect( + Math.abs((stableBounds?.width ?? 0) - (firstBounds?.width ?? 0)) + ).toBeLessThanOrEqual(1); + expect( + Math.abs((stableBounds?.height ?? 0) - (firstBounds?.height ?? 0)) + ).toBeLessThanOrEqual(1); + + const body = await target.screenshot({ animations: 'disabled' }); + const devicePixelRatio = await page.evaluate(() => window.devicePixelRatio); + const pngWidth = body.readUInt32BE(16); + const pngHeight = body.readUInt32BE(20); + + expect(body.subarray(0, 8).toString('hex')).toBe('89504e470d0a1a0a'); + expect(body.byteLength).toBeGreaterThan(1_024); + expect(pngWidth).toBeGreaterThan(0); + expect(pngHeight).toBeGreaterThan(0); + expect( + Math.abs( + pngWidth - Math.round((stableBounds?.width ?? 0) * devicePixelRatio) + ) + ).toBeLessThanOrEqual(2); + expect( + Math.abs( + pngHeight - Math.round((stableBounds?.height ?? 0) * devicePixelRatio) + ) + ).toBeLessThanOrEqual(2); + + await test.info().attach(name, { + body, + contentType: 'image/png', + }); +}; + +test.describe('Metric Governance', PLAYWRIGHT_BASIC_TEST_TAG_OBJ, () => { + test('a metric with no reviewers is approved on creation', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + let metricId: string | undefined; + + try { + const metric = await createMetric(apiContext, { + name: `pw-metric-auto-approved-${uuid()}`, + description: 'No reviewers, so nothing to approve', + }); + metricId = metric.id; + + expect(metric.entityStatus).toBe('Approved'); + } finally { + if (metricId) { + await apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ); + } + await afterAction(); + } + }); + + test('a complete non-reviewer change enters review automatically', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const reviewer = new UserClass(); + let metricId: string | undefined; + + try { + await reviewer.create(apiContext); + + const metric = await createMetric(apiContext, { + name: `pw-metric-reviewed-${uuid()}`, + description: 'Awaiting review', + reviewers: [{ id: reviewer.responseData.id, type: 'user' }], + }); + metricId = metric.id; + + await expectMetricStatus(apiContext, metric.id, 'In Review'); + } finally { + if (metricId) { + await apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ); + } + await reviewer.delete(apiContext); + await afterAction(); + } + }); + + test('lets the assigned reviewer approve a real Metric workflow in the UI', async ({ + browser, + }) => { + test.setTimeout(5 * 60 * 1_000); + + const { apiContext, afterAction } = await performAdminLogin(browser); + const reviewer = new UserClass(undefined, true); + const decisionNote = `Approved from the Metric UI ${uuid()}`; + let metricId: string | undefined; + let openTaskId = ''; + let reviewerCreated = false; + let reviewerAfterAction: (() => Promise) | undefined; + + try { + await reviewer.create(apiContext); + reviewerCreated = true; + + const metric = await createMetric(apiContext, { + description: 'Metric awaiting a real reviewer decision', + name: `pw-metric-ui-approval-${uuid()}`, + reviewers: [{ id: reviewer.responseData.id, type: 'user' }], + }); + metricId = metric.id; + + await expectMetricStatus(apiContext, metric.id, 'In Review'); + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/tasks?aboutEntity=${encodeURIComponent( + metric.fullyQualifiedName + )}&type=RequestApproval&status=Open&limit=1&fields=assignees,availableTransitions,createdBy,resolution,reviewers` + ); + if (!response.ok()) { + return false; + } + const taskList = (await response.json()) as { + data?: Array<{ + availableTransitions?: Array<{ + id?: string; + resolutionType?: string; + }>; + id?: number | string; + }>; + }; + const task = taskList.data?.[0]; + const approvalTransition = task?.availableTransitions?.find( + ({ resolutionType }) => resolutionType === 'Approved' + ); + openTaskId = String(task?.id ?? ''); + + return Boolean(openTaskId && approvalTransition?.id); + }, + { + intervals: [1_000, 2_000, 5_000], + timeout: 120_000, + } + ) + .toBe(true); + expect(openTaskId).not.toBe(''); + + const reviewerSession = await performUserLogin(browser, reviewer); + reviewerAfterAction = reviewerSession.afterAction; + const reviewerPage = reviewerSession.page; + await reviewerPage.goto( + `/metric/${encodeURIComponent(metric.fullyQualifiedName)}`, + { waitUntil: 'domcontentloaded' } + ); + await expect(reviewerPage.getByTestId('metric-details-page')).toBeVisible( + { timeout: 60_000 } + ); + await reviewerPage.getByTestId('approval').click(); + await expect( + reviewerPage.getByTestId('metric-approval-approve-btn') + ).toBeVisible({ timeout: 60_000 }); + await reviewerPage + .getByTestId('metric-approval-note') + .getByRole('textbox') + .fill(decisionNote); + + const resolveResponse = reviewerPage.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'POST' && + url.pathname.endsWith(`/api/v1/tasks/${openTaskId}/resolve`) + ); + }); + await reviewerPage.getByTestId('metric-approval-approve-btn').click(); + expect((await resolveResponse).ok()).toBeTruthy(); + + await expectMetricStatus( + reviewerSession.apiContext, + metric.id, + 'Approved' + ); + await expectAssignedTaskNotification( + reviewerSession.apiContext, + openTaskId, + metric.fullyQualifiedName, + 'Approved' + ); + await reviewerPage.reload({ waitUntil: 'domcontentloaded' }); + await expect( + reviewerPage + .getByTestId('metric-detail-header') + .getByTestId('metric-status-pill') + ).toContainText('Approved'); + await reviewerPage.getByTestId('approval').click(); + await expect( + reviewerPage.getByTestId('metric-approval-status-pill') + ).toContainText('Approved'); + await expect( + reviewerPage.getByTestId('metric-approval-history') + ).toContainText(decisionNote, { timeout: 60_000 }); + await attachScreenshot( + reviewerPage, + 'metric-approval-tab', + 'metric-approval-real' + ); + } finally { + try { + await reviewerAfterAction?.(); + } finally { + try { + if (metricId) { + await apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ); + } + } finally { + try { + if (reviewerCreated) { + await reviewer.delete(apiContext); + } + } finally { + await afterAction(); + } + } + } + } + }); + + test('a reviewer-authored metric change is auto-approved', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const reviewer = new UserClass(undefined, true); + let reviewerAfterAction: (() => Promise) | undefined; + let metricId: string | undefined; + + try { + await reviewer.create(apiContext); + const reviewerSession = await performUserLogin(browser, reviewer); + reviewerAfterAction = reviewerSession.afterAction; + const metric = await createMetric(reviewerSession.apiContext, { + name: `pw-metric-reviewer-authored-${uuid()}`, + description: 'Complete metric authored by its reviewer', + reviewers: [{ id: reviewer.responseData.id, type: 'user' }], + }); + metricId = metric.id; + + await expectMetricStatus( + reviewerSession.apiContext, + metric.id, + 'Approved' + ); + } finally { + await reviewerAfterAction?.(); + if (metricId) { + await apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ); + } + await reviewer.delete(apiContext); + await afterAction(); + } + }); + + test('reports Unknown health with a reason when nothing is linked', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + let metricId: string | undefined; + + try { + const metric = await createMetric(apiContext, { + name: `pw-metric-health-${uuid()}`, + description: 'No assets linked', + }); + metricId = metric.id; + + const response = await apiContext.get( + `/api/v1/metrics/${metric.id}/observability` + ); + + expect(response.ok()).toBeTruthy(); + + const observability = await response.json(); + + expect(observability.health).toBe('Unknown'); + expect(observability.upstreamAssetCount).toBe(0); + expect(observability.reasonCode).toBe('NoLinkedAssets'); + expect(observability.statusCounts).toEqual({ + aborted: 0, + failed: 0, + missing: 0, + passed: 0, + queued: 0, + terminal: 0, + }); + } finally { + if (metricId) { + await apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ); + } + await afterAction(); + } + }); + + test('renders the dedicated governance tabs and narrow assets state', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + + try { + await metric.create(apiContext); + await metric.visitEntityPage(page); + + await expect(page.getByTestId('assets')).toBeVisible(); + await expect(page.getByTestId('data_observability')).toBeVisible(); + await expect(page.getByTestId('activity_feed')).toBeVisible(); + await expect(page.getByTestId('approval')).toBeVisible(); + + const assetsResponse = await apiContext.get( + `/api/v1/metrics/${metric.entityResponseData.id}/assets?limit=10&offset=0` + ); + expect(assetsResponse.ok()).toBeTruthy(); + expect(await assetsResponse.json()).toEqual( + expect.objectContaining({ data: [], paging: expect.any(Object) }) + ); + + await page.setViewportSize({ height: 844, width: 390 }); + await page.getByTestId('assets').click(); + await expect(page.getByTestId('metric-assets-tab')).toBeVisible(); + await expect(page.getByTestId('metric-assets-results')).toBeVisible(); + const assetsBounds = await page + .getByTestId('metric-assets-tab') + .boundingBox(); + expect(assetsBounds?.width).toBeLessThanOrEqual(390); + await attachScreenshot(page, 'metric-assets-tab', 'metric-assets-narrow'); + + await page.getByTestId('activity_feed').click(); + await expect(page.getByTestId('metric-activity-tab')).toBeVisible(); + await expect( + page.getByRole('tablist', { name: /activity/i }) + ).toBeVisible(); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); + + test('renders the generic lineage graph and hides editing from read-only users', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + const readOnlyUser = new UserClass(); + let readOnlyAfterAction: (() => Promise) | undefined; + let userCreated = false; + + try { + await metric.create(apiContext); + await readOnlyUser.create(apiContext); + userCreated = true; + await metric.visitEntityPage(page); + + const adminLineageResponse = page.waitForResponse((response) => + new URL(response.url()).pathname.endsWith('/api/v1/lineage/getLineage') + ); + await page.getByTestId('lineage').click(); + expect((await adminLineageResponse).ok()).toBeTruthy(); + const adminLineage = page.getByTestId('lineage-details'); + await expect(adminLineage).toBeVisible(); + await expect( + page.getByTestId('lineage-container').locator('.react-flow') + ).toBeVisible(); + await expect(page.getByTestId('edit-lineage')).toBeVisible(); + + const readOnlySession = await performUserLogin(browser, readOnlyUser); + readOnlyAfterAction = readOnlySession.afterAction; + await readOnlySession.page.goto( + `/metric/${encodeURIComponent( + metric.entityResponseData.fullyQualifiedName + )}`, + { waitUntil: 'domcontentloaded' } + ); + await expect( + readOnlySession.page.getByTestId('metric-details-page') + ).toBeVisible({ timeout: 60_000 }); + const readOnlyLineageResponse = readOnlySession.page.waitForResponse( + (response) => + new URL(response.url()).pathname.endsWith( + '/api/v1/lineage/getLineage' + ) + ); + await readOnlySession.page.getByTestId('lineage').click(); + expect((await readOnlyLineageResponse).ok()).toBeTruthy(); + await expect( + readOnlySession.page + .getByTestId('lineage-container') + .locator('.react-flow') + ).toBeVisible(); + await expect( + readOnlySession.page.getByTestId('edit-lineage') + ).toBeHidden(); + } finally { + try { + await readOnlyAfterAction?.(); + } finally { + try { + await metric.delete(apiContext); + } finally { + try { + if (userCreated) { + await readOnlyUser.delete(apiContext); + } + } finally { + await afterAction(); + } + } + } + } + }); + + test('filters, summarizes, selects, and unlinks Assets in bulk', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + const upstreamAsset = { + displayName: 'Orders fact', + fullyQualifiedName: 'sample.database.schema.orders_fact', + id: '11111111-1111-4111-8111-111111111111', + name: 'orders_fact', + type: 'table', + }; + const downstreamAsset = { + displayName: 'Revenue dashboard', + fullyQualifiedName: 'sample.dashboard.revenue_dashboard', + id: '22222222-2222-4222-8222-222222222222', + name: 'revenue_dashboard', + type: 'dashboard', + }; + const relations = [ + { + affectsHealth: true, + asset: upstreamAsset, + direction: 'upstream', + }, + { + affectsHealth: false, + asset: downstreamAsset, + direction: 'downstream', + }, + ]; + const linkedAssetIds = new Set(); + let removedAssetIds: string[] = []; + + try { + await metric.create(apiContext); + + await page.route('**/api/v1/metrics/**/assets**', async (route) => { + const request = route.request(); + const url = new URL(request.url()); + const pathname = url.pathname; + if (request.method() === 'PUT') { + const payload = request.postDataJSON() as { + assets?: Array<{ id: string }>; + }; + const requestedAssets = payload.assets ?? []; + if (pathname.endsWith('/assets/add')) { + requestedAssets.forEach(({ id }) => linkedAssetIds.add(id)); + } else if (pathname.endsWith('/assets/remove')) { + removedAssetIds = requestedAssets.map(({ id }) => id); + removedAssetIds.forEach((id) => linkedAssetIds.delete(id)); + } + + return fulfillJson(route, { + failedRequest: [], + status: 'success', + successRequest: requestedAssets.map((requestAsset) => ({ + request: requestAsset, + status: 200, + })), + }); + } + + const query = (url.searchParams.get('q') ?? '').toLowerCase(); + const entityType = url.searchParams.get('entityType'); + const direction = url.searchParams.get('direction'); + const filtered = relations.filter( + (relation) => + linkedAssetIds.has(relation.asset.id) && + (!query || + relation.asset.name.toLowerCase().includes(query) || + relation.asset.displayName.toLowerCase().includes(query) || + relation.asset.fullyQualifiedName + .toLowerCase() + .includes(query)) && + (!entityType || relation.asset.type === entityType) && + (!direction || relation.direction === direction) + ); + const limit = Number(url.searchParams.get('limit')) || 10; + const offset = Number(url.searchParams.get('offset')) || 0; + + return fulfillJson(route, { + data: filtered.slice(offset, offset + limit), + paging: { limit, offset, total: filtered.length }, + }); + }); + await page.route('**/api/v1/metrics/*/observability**', (route) => + fulfillJson(route, { + assets: [ + { + asset: upstreamAsset, + failed: 0, + health: 'Healthy', + passed: 2, + score: 100, + total: 2, + }, + ], + dimensions: [], + health: 'Healthy', + incidents: [], + linkedAssets: relations.filter(({ asset }) => + linkedAssetIds.has(asset.id) + ), + reasonCode: 'ScoreComputed', + score: 100, + statusCounts: { + aborted: 0, + failed: 0, + missing: 0, + passed: 2, + queued: 0, + terminal: 2, + }, + tests: [], + upstreamAssetCount: linkedAssetIds.has(upstreamAsset.id) ? 1 : 0, + }) + ); + await page.route('**/api/v1/search/query**', (route) => + fulfillJson(route, { + aggregations: {}, + hits: { + hits: [upstreamAsset, downstreamAsset].map((asset) => ({ + _id: asset.id, + _index: `${asset.type}_search_index`, + _source: { + description: `${asset.displayName} used by this metric`, + displayName: asset.displayName, + entityType: asset.type, + fullyQualifiedName: asset.fullyQualifiedName, + name: asset.name, + }, + })), + total: { value: 2 }, + }, + }) + ); + await page.route('**/api/v1/tables/name/**', (route) => + fulfillJson(route, { + ...upstreamAsset, + columns: [ + { displayName: 'Gross Amount', name: 'amount' }, + { name: 'order_id' }, + ], + description: 'Orders used to compute the metric', + domains: [{ id: 'domain-1', name: 'Commerce', type: 'domain' }], + owners: [{ id: 'owner-1', name: 'Data Steward', type: 'user' }], + tags: [ + { source: 'Classification', tagFQN: 'Tier.Tier1' }, + { source: 'Classification', tagFQN: 'PII.Sensitive' }, + { source: 'Glossary', tagFQN: 'BusinessGlossary.Revenue' }, + ], + usageSummary: { weeklyStats: { count: 42, percentileRank: 95 } }, + }) + ); + await page.route('**/api/v1/dashboards/name/**', (route) => + fulfillJson(route, { + ...downstreamAsset, + description: 'Dashboard that consumes this metric', + domains: [], + owners: [], + tags: [], + usageSummary: { weeklyStats: { count: 7, percentileRank: 50 } }, + }) + ); + await page.route('**/api/v1/lineage/getLineage**', (route) => + fulfillJson(route, { + downstreamEdges: [], + entity: { id: metric.entityResponseData.id, type: 'metric' }, + nodes: [], + upstreamEdges: [ + { + fromEntity: upstreamAsset.id, + lineageDetails: { + columnsLineage: [ + { + fromColumns: [`${upstreamAsset.fullyQualifiedName}.amount`], + toColumn: `${metric.entityResponseData.fullyQualifiedName}.gross_revenue`, + }, + ], + }, + toEntity: metric.entityResponseData.id, + }, + ], + }) + ); + + await metric.visitEntityPage(page); + await page.getByTestId('assets').click(); + await page.getByTestId('metric-assets-add').click(); + const addDialog = page.getByTestId('metric-asset-add-dialog'); + await expect(addDialog).toBeVisible(); + const upstreamAddCheckbox = addDialog.getByRole('checkbox', { + name: upstreamAsset.displayName, + }); + const downstreamAddCheckbox = addDialog.getByRole('checkbox', { + name: downstreamAsset.displayName, + }); + await upstreamAddCheckbox.focus(); + await upstreamAddCheckbox.press('Space'); + await expect(upstreamAddCheckbox).toBeChecked(); + await downstreamAddCheckbox.focus(); + await downstreamAddCheckbox.press('Space'); + await expect(downstreamAddCheckbox).toBeChecked(); + + const addRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'PUT' && url.pathname.endsWith('/assets/add') + ); + }); + await page.getByTestId('metric-asset-add-confirm').click(); + const addRequest = await addRequestPromise; + const addPayload = addRequest.postDataJSON() as { + assets: Array<{ id: string }>; + }; + expect(addPayload.assets.map(({ id }) => id).sort()).toEqual( + [upstreamAsset.id, downstreamAsset.id].sort() + ); + await expect(addDialog).toBeHidden(); + + const upstreamCard = page.getByTestId( + `metric-asset-card-${upstreamAsset.id}` + ); + const downstreamCard = page.getByTestId( + `metric-asset-card-${downstreamAsset.id}` + ); + await expect(upstreamCard).toBeVisible(); + await expect(upstreamCard).toContainText(upstreamAsset.displayName); + await expect(upstreamCard).toContainText('Upstream'); + await expect(downstreamCard).toBeVisible(); + await expect(downstreamCard).toContainText(downstreamAsset.displayName); + await expect(downstreamCard).toContainText('Downstream'); + await attachScreenshot(page, 'metric-assets-tab', 'metric-assets-linked'); + + await page + .getByTestId(`metric-asset-activate-${upstreamAsset.id}`) + .click(); + const summary = page.getByTestId('metric-asset-summary'); + await expect(summary).toBeVisible(); + await expect(summary).toContainText('Orders used to compute the metric'); + await expect(summary).toContainText('Upstream'); + await expect(summary.getByText('sample', { exact: true })).toBeVisible(); + await expect( + summary.getByText('database', { exact: true }) + ).toBeVisible(); + await expect(summary.getByText('schema', { exact: true })).toBeVisible(); + await expect(summary.getByText('42', { exact: true })).toBeVisible(); + await expect(summary).toContainText('Data Steward'); + await expect(summary).toContainText('Commerce'); + await expect(summary).toContainText('Tier.Tier1'); + await expect(summary).toContainText('PII.Sensitive'); + await expect(summary).toContainText('BusinessGlossary.Revenue'); + await expect(summary).toContainText('Gross Amount'); + await expect(summary).toContainText('order_id'); + await expect(summary).toContainText('Columns feeding this metric'); + await expect(summary).toContainText( + `${upstreamAsset.fullyQualifiedName}.amount → ${metric.entityResponseData.fullyQualifiedName}.gross_revenue` + ); + const viewAssetLink = summary.getByRole('link', { + name: 'View Asset', + }); + await expect(viewAssetLink).toHaveAttribute( + 'href', + `/table/${upstreamAsset.fullyQualifiedName}` + ); + await summary.getByRole('button', { name: 'Close' }).click(); + await page + .getByTestId(`metric-asset-activate-${upstreamAsset.id}`) + .click(); + const navigationLink = page + .getByTestId('metric-asset-summary') + .getByRole('link', { name: 'View Asset' }); + await Promise.all([ + page.waitForURL( + (url) => url.pathname === `/table/${upstreamAsset.fullyQualifiedName}` + ), + navigationLink.click(), + ]); + await page.goBack({ waitUntil: 'domcontentloaded' }); + await expect(page.getByTestId('metric-assets-tab')).toBeVisible({ + timeout: 60_000, + }); + + const searchRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'GET' && + url.pathname.endsWith(`/${metric.entityResponseData.id}/assets`) && + url.searchParams.get('q') === upstreamAsset.name + ); + }); + await page.getByTestId('metric-assets-search').fill(upstreamAsset.name); + await searchRequestPromise; + await expect(upstreamCard).toBeVisible(); + await expect(downstreamCard).toBeHidden(); + + const clearSearchRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'GET' && + url.pathname.endsWith(`/${metric.entityResponseData.id}/assets`) && + url.searchParams.get('limit') === '10' && + !url.searchParams.has('q') + ); + }); + await page.getByTestId('metric-assets-search').fill(''); + await clearSearchRequestPromise; + await expect(downstreamCard).toBeVisible(); + + const typeFilterRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'GET' && + url.pathname.endsWith(`/${metric.entityResponseData.id}/assets`) && + url.searchParams.get('entityType') === 'table' + ); + }); + await page.getByTestId('metric-assets-type-filter').click(); + await page.getByRole('option', { exact: true, name: 'Table' }).click(); + await typeFilterRequestPromise; + await expect(upstreamCard).toBeVisible(); + await expect(downstreamCard).toBeHidden(); + + const clearTypeRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'GET' && + url.pathname.endsWith(`/${metric.entityResponseData.id}/assets`) && + url.searchParams.get('limit') === '10' && + !url.searchParams.has('entityType') + ); + }); + await page.getByTestId('metric-assets-type-filter').click(); + await page.getByRole('option', { exact: true, name: 'All' }).click(); + await clearTypeRequestPromise; + await expect(downstreamCard).toBeVisible(); + + const directionFilterRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'GET' && + url.pathname.endsWith(`/${metric.entityResponseData.id}/assets`) && + url.searchParams.get('direction') === 'downstream' + ); + }); + await page.getByTestId('metric-assets-direction-filter').click(); + await page + .getByRole('option', { exact: true, name: 'Downstream' }) + .click(); + await directionFilterRequestPromise; + await expect(upstreamCard).toBeHidden(); + await expect(downstreamCard).toBeVisible(); + + const clearDirectionRequestPromise = page.waitForRequest((request) => { + const url = new URL(request.url()); + + return ( + request.method() === 'GET' && + url.pathname.endsWith(`/${metric.entityResponseData.id}/assets`) && + url.searchParams.get('limit') === '10' && + !url.searchParams.has('direction') + ); + }); + await page.getByTestId('metric-assets-direction-filter').click(); + await page.getByRole('option', { exact: true, name: 'All' }).click(); + await clearDirectionRequestPromise; + await expect(upstreamCard).toBeVisible(); + + const selectAll = page.getByRole('checkbox', { name: 'Select all' }); + await selectAll.focus(); + await selectAll.press('Space'); + await expect(selectAll).toBeChecked(); + await expect(upstreamCard.getByRole('checkbox')).toBeChecked(); + await expect(downstreamCard.getByRole('checkbox')).toBeChecked(); + await expect(page.getByText('2 items selected')).toBeVisible(); + + const unlinkResponsePromise = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'PUT' && + url.pathname.endsWith('/assets/remove') + ); + }); + await page.getByTestId('metric-assets-bulk-unlink').click(); + const unlinkResponse = await unlinkResponsePromise; + const unlinkRequest = unlinkResponse.request(); + const unlinkPayload = unlinkRequest.postDataJSON() as { + assets: Array<{ id: string }>; + }; + expect(unlinkPayload.assets.map(({ id }) => id).sort()).toEqual( + [upstreamAsset.id, downstreamAsset.id].sort() + ); + expect(removedAssetIds.sort()).toEqual( + [upstreamAsset.id, downstreamAsset.id].sort() + ); + await expect(upstreamCard).toBeHidden(); + await expect(downstreamCard).toBeHidden(); + await expect(page.getByTestId('metric-assets-bulk-result')).toContainText( + 'Success' + ); + await expect(page.getByTestId('metric-assets-results')).toContainText( + 'No data found' + ); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); + + test('keeps Assets visible but hides relationship mutations for read-only users', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const metric = new MetricClass(); + const readOnlyUser = new UserClass(); + const asset = { + displayName: 'Read-only orders', + fullyQualifiedName: 'sample.database.schema.read_only_orders', + id: '33333333-3333-4333-8333-333333333333', + name: 'read_only_orders', + type: 'table', + }; + let readOnlyAfterAction: (() => Promise) | undefined; + let userCreated = false; + const relationshipMutations: string[] = []; + + try { + await metric.create(apiContext); + await readOnlyUser.create(apiContext); + userCreated = true; + const readOnlySession = await performUserLogin(browser, readOnlyUser); + readOnlyAfterAction = readOnlySession.afterAction; + const readOnlyPage = readOnlySession.page; + + await readOnlyPage.route( + '**/api/v1/metrics/**/assets**', + async (route) => { + const request = route.request(); + if (request.method() === 'PUT') { + relationshipMutations.push(request.method()); + + return fulfillJson(route, { message: 'Forbidden' }, 403); + } + + return fulfillJson(route, { + data: [ + { + affectsHealth: true, + asset, + direction: 'upstream', + }, + ], + paging: { limit: 10, offset: 0, total: 1 }, + }); + } + ); + await readOnlyPage.route('**/api/v1/metrics/*/observability**', (route) => + fulfillJson(route, { + assets: [], + dimensions: [], + health: 'Unknown', + incidents: [], + linkedAssets: [{ affectsHealth: true, asset, direction: 'upstream' }], + reasonCode: 'NoTerminalResults', + statusCounts: { + aborted: 0, + failed: 0, + missing: 0, + passed: 0, + queued: 0, + terminal: 0, + }, + tests: [], + upstreamAssetCount: 1, + }) + ); + await readOnlyPage.route('**/api/v1/tables/name/**', (route) => + fulfillJson(route, { + ...asset, + columns: [], + description: 'Visible without relationship edit permission', + domains: [], + owners: [], + tags: [], + }) + ); + + await readOnlyPage.goto( + `/metric/${encodeURIComponent( + metric.entityResponseData.fullyQualifiedName + )}`, + { waitUntil: 'domcontentloaded' } + ); + await expect(readOnlyPage.getByTestId('metric-details-page')).toBeVisible( + { timeout: 60_000 } + ); + await readOnlyPage.getByTestId('assets').click(); + + const readOnlyCard = readOnlyPage.getByTestId( + `metric-asset-card-${asset.id}` + ); + await expect(readOnlyCard).toBeVisible(); + await expect(readOnlyCard).toContainText(asset.displayName); + await expect( + readOnlyPage.getByTestId('metric-assets-search') + ).toBeVisible(); + await expect( + readOnlyPage.getByTestId('metric-assets-type-filter') + ).toBeVisible(); + await expect( + readOnlyPage.getByTestId('metric-assets-direction-filter') + ).toBeVisible(); + await expect(readOnlyPage.getByTestId('metric-assets-add')).toHaveCount( + 0 + ); + await expect( + readOnlyPage.getByTestId('metric-assets-bulk-unlink') + ).toHaveCount(0); + await expect(readOnlyCard.getByRole('checkbox')).toHaveCount(0); + expect(relationshipMutations).toEqual([]); + } finally { + try { + await readOnlyAfterAction?.(); + } finally { + try { + await metric.delete(apiContext); + } finally { + try { + if (userCreated) { + await readOnlyUser.delete(apiContext); + } + } finally { + await afterAction(); + } + } + } + } + }); + + test('shows the health pill and rollup reason on the observability tab', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + + try { + await metric.create(apiContext); + await metric.visitEntityPage(page); + await page.getByTestId('data_observability').click(); + + await expect(page.getByTestId('metric-health-pill')).toBeVisible(); + await expect(page.getByTestId('metric-rollup-reason')).toBeVisible(); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); + + test('scores only direct upstream table and column tests using their latest results', async ({ + browser, + }) => { + test.setTimeout(5 * 60 * 1_000); + + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const suffix = uuid(); + const table = new TableClass(`pw-metric-upstream-${suffix}`); + const restrictedPolicy = new PolicyClass(); + const restrictedRole = new RolesClass(); + const restrictedUser = new UserClass(); + const lineageEdges: Array<{ + from: { id: string; type: string }; + to: { id: string; type: string }; + }> = []; + let customDefinitionId: string | undefined; + let metricId: string | undefined; + let restrictedAfterAction: (() => Promise) | undefined; + let tableCreated = false; + + try { + await table.create(apiContext); + tableCreated = true; + + const upstream = table.entityResponseData as EntityFixture; + const downstream = (await table.createAdditionalTable( + { + displayName: `Metric downstream ${suffix}`, + name: `pw-metric-downstream-${suffix}`, + }, + apiContext + )) as EntityFixture; + const unrelated = (await table.createAdditionalTable( + { + displayName: `Metric unrelated ${suffix}`, + name: `pw-metric-unrelated-${suffix}`, + }, + apiContext + )) as EntityFixture; + const metric = await createMetric(apiContext, { + description: 'Metric with direct upstream observability coverage', + name: `pw-metric-observability-${suffix}`, + }); + metricId = metric.id; + + const definitionResponse = await apiContext.post( + '/api/v1/dataQuality/testDefinitions', + { + data: { + dataQualityDimension: 'Consistency', + entityType: 'TABLE', + name: `pw-metric-consistency-${suffix}`, + supportedDataTypes: ['NUMBER'], + testPlatforms: ['OpenMetadata'], + }, + } + ); + expect(definitionResponse.status()).toBe(201); + const customDefinition = + (await definitionResponse.json()) as EntityFixture; + customDefinitionId = customDefinition.id; + + const upstreamTableTest = await createQualityTestCase(apiContext, { + entityLink: `<#E::table::${upstream.fullyQualifiedName}>`, + name: `pw_upstream_consistency_${suffix}`, + parameterValues: [], + testDefinition: customDefinition.fullyQualifiedName, + }); + const upstreamColumnTest = await createQualityTestCase(apiContext, { + entityLink: `<#E::table::${upstream.fullyQualifiedName}::columns::${table.columnsName[0]}>`, + name: `pw_upstream_column_${suffix}`, + parameterValues: [], + testDefinition: 'columnValuesToBeNotNull', + }); + const downstreamTest = await createQualityTestCase(apiContext, { + entityLink: `<#E::table::${downstream.fullyQualifiedName}>`, + name: `pw_downstream_failed_${suffix}`, + parameterValues: [ + { name: 'minValue', value: 1 }, + { name: 'maxValue', value: 2 }, + ], + testDefinition: 'tableRowCountToBeBetween', + }); + const unrelatedTest = await createQualityTestCase(apiContext, { + entityLink: `<#E::table::${unrelated.fullyQualifiedName}>`, + name: `pw_unrelated_failed_${suffix}`, + parameterValues: [ + { name: 'minValue', value: 1 }, + { name: 'maxValue', value: 2 }, + ], + testDefinition: 'tableRowCountToBeBetween', + }); + + const resultStart = Date.now() - 10_000; + await addQualityTestResult( + apiContext, + upstreamTableTest.fullyQualifiedName, + 'Failed', + resultStart + 100 + ); + await addQualityTestResult( + apiContext, + upstreamColumnTest.fullyQualifiedName, + 'Success', + resultStart + 200 + ); + await addQualityTestResult( + apiContext, + upstreamTableTest.fullyQualifiedName, + 'Success', + resultStart + 300 + ); + await addQualityTestResult( + apiContext, + upstreamColumnTest.fullyQualifiedName, + 'Failed', + resultStart + 400 + ); + await addQualityTestResult( + apiContext, + downstreamTest.fullyQualifiedName, + 'Failed', + resultStart + 500 + ); + await addQualityTestResult( + apiContext, + unrelatedTest.fullyQualifiedName, + 'Failed', + resultStart + 600 + ); + + const linkResponse = await apiContext.put( + `/api/v1/metrics/${encodeURIComponent( + metric.fullyQualifiedName + )}/assets/add`, + { + data: { + assets: [upstream, downstream, unrelated].map((asset) => ({ + id: asset.id, + type: 'table', + })), + }, + } + ); + expect(linkResponse.ok()).toBeTruthy(); + + const upstreamEdge = { + from: { id: upstream.id, type: 'table' }, + to: { id: metric.id, type: 'metric' }, + }; + const upstreamLineageResponse = await connectEdgeBetweenNodesViaAPI( + apiContext, + upstreamEdge.from, + upstreamEdge.to + ); + expect(upstreamLineageResponse.ok()).toBeTruthy(); + lineageEdges.push(upstreamEdge); + + const downstreamEdge = { + from: { id: metric.id, type: 'metric' }, + to: { id: downstream.id, type: 'table' }, + }; + const downstreamLineageResponse = await connectEdgeBetweenNodesViaAPI( + apiContext, + downstreamEdge.from, + downstreamEdge.to + ); + expect(downstreamLineageResponse.ok()).toBeTruthy(); + lineageEdges.push(downstreamEdge); + + await expect + .poll( + async () => { + const observability = await getMetricObservability( + apiContext, + metric.id + ); + + return { + failed: observability.statusCounts.failed, + passed: observability.statusCounts.passed, + score: observability.score, + terminal: observability.statusCounts.terminal, + upstreamAssetCount: observability.upstreamAssetCount, + }; + }, + { + intervals: [1_000, 2_000, 5_000], + timeout: 120_000, + } + ) + .toEqual({ + failed: 1, + passed: 1, + score: 50, + terminal: 2, + upstreamAssetCount: 1, + }); + + const observability = await getMetricObservability(apiContext, metric.id); + expect(observability.health).toBe('Degraded'); + expect(observability.reasonCode).toBe('Degraded'); + expect(observability.statusCounts).toEqual({ + aborted: 0, + failed: 1, + missing: 0, + passed: 1, + queued: 0, + terminal: 2, + }); + expect(observability.assets).toHaveLength(1); + expect(observability.assets[0]).toEqual( + expect.objectContaining({ + asset: expect.objectContaining({ id: upstream.id }), + failed: 1, + passed: 1, + score: 50, + }) + ); + + const linkedDirections = new Map( + observability.linkedAssets.map(({ asset, direction }) => [ + asset.id, + direction, + ]) + ); + expect(linkedDirections).toEqual( + new Map([ + [upstream.id, 'upstream'], + [downstream.id, 'downstream'], + [unrelated.id, 'unrelated'], + ]) + ); + + const consistency = observability.dimensions.find( + ({ dimension }) => dimension === 'Consistency' + ); + expect(consistency).toEqual( + expect.objectContaining({ failed: 0, passed: 1, score: 100, total: 1 }) + ); + expect(observability.tests).toHaveLength(2); + expect(observability.tests.map(({ testCase }) => testCase.id)).toEqual( + expect.arrayContaining([upstreamTableTest.id, upstreamColumnTest.id]) + ); + expect( + observability.tests.every(({ asset }) => asset?.id === upstream.id) + ).toBeTruthy(); + expect( + observability.tests.some(({ testCase }) => + [downstreamTest.id, unrelatedTest.id].includes(testCase.id) + ) + ).toBeFalsy(); + expect(observability.incidents.length).toBeGreaterThan(0); + expect( + observability.incidents.some( + ({ testCase }) => testCase.id === upstreamColumnTest.id + ) + ).toBeTruthy(); + + await page.goto( + `/metric/${encodeURIComponent(metric.fullyQualifiedName)}`, + { waitUntil: 'domcontentloaded' } + ); + await page.getByTestId('data_observability').click(); + + await expect( + page.getByTestId('metric-health-summary').getByRole('progressbar') + ).toHaveAttribute('aria-valuenow', '50'); + const statusCounts = page.getByTestId('metric-global-status-counts'); + await expect( + statusCounts.locator(':scope > div').filter({ hasText: 'Passed' }) + ).toContainText('1'); + await expect( + statusCounts.locator(':scope > div').filter({ hasText: 'Failed' }) + ).toContainText('1'); + await expect( + page.getByTestId('metric-dimension-Consistency') + ).toContainText('100%'); + await expect( + page.getByTestId('metric-dimension-Consistency') + ).toContainText('1/1'); + await expect(page.getByTestId('metric-asset-rollups')).toContainText( + upstream.displayName ?? upstream.name + ); + await expect(page.getByTestId('metric-asset-rollups')).not.toContainText( + downstream.displayName ?? downstream.name + ); + await expect(page.getByTestId('metric-asset-rollups')).not.toContainText( + unrelated.displayName ?? unrelated.name + ); + await expect(page.getByTestId('metric-tests')).toContainText( + upstreamTableTest.name + ); + await expect(page.getByTestId('metric-tests')).toContainText( + upstreamColumnTest.name + ); + await expect(page.getByTestId('metric-tests')).not.toContainText( + downstreamTest.name + ); + await expect(page.getByTestId('metric-tests')).not.toContainText( + unrelatedTest.name + ); + await expect(page.getByTestId('metric-incidents')).toContainText( + upstreamColumnTest.name + ); + await attachScreenshot( + page, + 'metric-observability-tab', + 'metric-observability-real' + ); + + await restrictedUser.create(apiContext, false); + const policy = await restrictedPolicy.create(apiContext, [ + { + effect: 'allow', + name: `pw-metric-observability-view-${suffix}`, + operations: ['ViewAll', 'ViewBasic'], + resources: ['metric'], + }, + ]); + const role = await restrictedRole.create(apiContext, [ + policy.fullyQualifiedName ?? policy.name, + ]); + await restrictedUser.patch({ + apiContext, + patchData: [ + { + op: 'add', + path: '/roles/0', + value: { + id: role.id, + name: role.name, + type: 'role', + }, + }, + ], + }); + + const restrictedSession = await performUserLogin(browser, restrictedUser); + restrictedAfterAction = restrictedSession.afterAction; + const restrictedObservability = await getMetricObservability( + restrictedSession.apiContext, + metric.id + ); + + expect(restrictedObservability.score).toBe(50); + expect(restrictedObservability.statusCounts).toEqual( + observability.statusCounts + ); + expect(restrictedObservability.sourceCoverage).toEqual( + expect.objectContaining({ + restrictedTables: 1, + upstreamTables: 1, + visibleTables: 0, + }) + ); + expect( + restrictedObservability.assets.every( + ({ asset, redacted }) => redacted || !asset.name + ) + ).toBeTruthy(); + expect( + restrictedObservability.tests.every( + ({ testCase, redacted }) => redacted || !testCase.name + ) + ).toBeTruthy(); + expect( + restrictedObservability.incidents.every( + ({ testCase, redacted }) => redacted || !testCase.name + ) + ).toBeTruthy(); + + await restrictedSession.page.goto( + `/metric/${encodeURIComponent(metric.fullyQualifiedName)}`, + { waitUntil: 'domcontentloaded' } + ); + await expect( + restrictedSession.page.getByTestId('metric-details-page') + ).toBeVisible({ timeout: 60_000 }); + await restrictedSession.page.getByTestId('data_observability').click(); + await expect( + restrictedSession.page + .getByTestId('metric-health-summary') + .getByRole('progressbar') + ).toHaveAttribute('aria-valuenow', '50'); + await expect( + restrictedSession.page.getByTestId('metric-observability-redacted') + ).toBeVisible(); + await expect( + restrictedSession.page.getByTestId('metric-tests') + ).not.toContainText(upstreamColumnTest.name); + await expect( + restrictedSession.page.getByTestId('metric-incidents') + ).not.toContainText(upstreamColumnTest.name); + } finally { + await restrictedAfterAction?.(); + if (restrictedUser.responseData.id) { + await restrictedUser.delete(apiContext); + } + if (restrictedRole.responseData.id) { + await restrictedRole.delete(apiContext); + } + if (restrictedPolicy.responseData.id) { + await restrictedPolicy.delete(apiContext); + } + await Promise.allSettled( + lineageEdges.map(({ from, to }) => + apiContext.delete( + `/api/v1/lineage/${from.type}/${from.id}/${to.type}/${to.id}` + ) + ) + ); + const entityCleanup: Array> = []; + if (metricId) { + entityCleanup.push( + apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ) + ); + } + if (tableCreated) { + entityCleanup.push(table.delete(apiContext)); + } + await Promise.allSettled(entityCleanup); + try { + if (customDefinitionId) { + await apiContext.delete( + `/api/v1/dataQuality/testDefinitions/${customDefinitionId}?hardDelete=true` + ); + } + } finally { + await afterAction(); + } + } + }); + + test('renders scored observability from upstream tests and incidents', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + const now = Date.now(); + const asset = { + displayName: 'Orders fact', + fullyQualifiedName: 'sample.database.schema.orders_fact', + id: '22222222-2222-4222-8222-222222222222', + name: 'orders_fact', + type: 'table', + }; + const testCase = { + displayName: 'Orders are complete', + fullyQualifiedName: 'sample.database.schema.orders_fact.orders_complete', + id: '33333333-3333-4333-8333-333333333333', + name: 'orders_complete', + type: 'testCase', + }; + + try { + await metric.create(apiContext); + await page.route('**/api/v1/metrics/*/observability**', (route) => + fulfillJson(route, { + assets: [ + { + aborted: 0, + asset, + failed: 1, + health: 'AtRisk', + latestRunTime: now, + passed: 3, + score: 75, + total: 4, + }, + ], + dimensions: [ + { + aborted: 0, + dimension: 'Completeness', + failed: 1, + passed: 3, + score: 75, + total: 4, + }, + ], + evaluatedAssetCount: 1, + evaluatedAt: now, + health: 'AtRisk', + incidents: [ + { + asset, + id: 'incident-1', + severity: 'Severity1', + status: 'New', + testCase, + timestamp: now, + }, + ], + latestRunTime: now, + linkedAssets: [{ affectsHealth: true, asset, direction: 'upstream' }], + metric: { + id: metric.entityResponseData.id, + name: metric.entity.name, + type: 'metric', + }, + reasonCode: 'AtRisk', + score: 75, + sourceCoverage: { + coveragePercent: 100, + partial: false, + restrictedTables: 0, + testedTables: 1, + upstreamTables: 1, + visibleTables: 1, + }, + statusCounts: { + aborted: 0, + failed: 1, + missing: 0, + passed: 3, + queued: 0, + terminal: 4, + }, + tests: [ + { + asset, + dimension: 'Completeness', + status: 'Success', + testCase, + timestamp: now, + }, + ], + upstreamAssetCount: 1, + }) + ); + + await metric.visitEntityPage(page); + await page.getByTestId('data_observability').click(); + + await expect( + page.getByTestId('metric-health-summary').getByRole('progressbar') + ).toHaveAttribute('aria-valuenow', '75'); + await expect(page.getByTestId('metric-rollup-reason')).toContainText( + '75%' + ); + await expect(page.getByTestId('metric-asset-rollups')).toContainText( + asset.displayName + ); + await expect(page.getByTestId('metric-tests')).toContainText( + testCase.displayName + ); + await expect(page.getByTestId('metric-incidents')).toContainText( + testCase.displayName + ); + await attachScreenshot( + page, + 'metric-observability-tab', + 'metric-observability-scored' + ); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); + + test('creates a conversation and a task from the Activity tab', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + const comment = `Validate metric definition ${uuid()}`; + const taskTitle = `Clarify definition ${uuid()}`; + const assignee = { + displayName: 'Review User', + fullyQualifiedName: 'review.user', + id: '44444444-4444-4444-8444-444444444444', + name: 'review.user', + type: 'user', + }; + const threads: Array> = []; + const tasks: Array> = []; + + try { + await metric.create(apiContext); + await page.route('**/api/v1/activity/entity/metric/name/**', (route) => + fulfillJson(route, { data: [], paging: { total: 0 } }) + ); + await page.route('**/api/v1/feed**', async (route) => { + const request = route.request(); + const pathname = new URL(request.url()).pathname; + if (pathname.endsWith('/feed/count')) { + return fulfillJson(route, { + data: [ + { + conversationCount: threads.length, + entityLink: `<#E::metric::${metric.entity.name}>`, + mentionCount: 0, + taskCount: tasks.length, + }, + ], + }); + } + if (request.method() === 'POST' && pathname.endsWith('/feed')) { + const payload = request.postDataJSON() as { + about?: string; + message?: string; + type?: string; + }; + const thread = { + about: payload.about ?? '', + createdBy: 'admin', + id: 'thread-1', + message: payload.message ?? '', + posts: [], + postsCount: 0, + threadTs: Date.now(), + type: payload.type ?? 'Conversation', + updatedAt: Date.now(), + }; + threads.splice(0, threads.length, thread); + + return fulfillJson(route, thread, 201); + } + + return fulfillJson(route, { + data: threads, + paging: { total: threads.length }, + }); + }); + await page.route('**/api/v1/tasks**', async (route) => { + const request = route.request(); + const pathname = new URL(request.url()).pathname; + if (pathname.endsWith('/tasks/count')) { + return fulfillJson(route, { + completed: 0, + open: tasks.length, + total: tasks.length, + }); + } + if (request.method() === 'POST' && pathname.endsWith('/tasks')) { + const payload = request.postDataJSON() as { + name?: string; + payload?: Record; + }; + const task = { + assignees: [assignee], + category: 'MetadataUpdate', + createdAt: Date.now(), + createdBy: { + id: 'admin-user', + name: 'admin', + type: 'user', + }, + description: String(payload.payload?.newDescription ?? ''), + displayName: payload.name ?? taskTitle, + id: 'task-1', + name: payload.name ?? taskTitle, + status: 'Open', + updatedAt: Date.now(), + }; + tasks.splice(0, tasks.length, task); + + return fulfillJson(route, task, 201); + } + + return fulfillJson(route, { + data: tasks, + paging: { total: tasks.length }, + }); + }); + await page.route('**/api/v1/search/query**', (route) => + fulfillJson(route, { + aggregations: {}, + hits: { + hits: [ + { + _id: assignee.id, + _index: 'user_search_index', + _source: { + displayName: assignee.displayName, + entityType: assignee.type, + fullyQualifiedName: assignee.fullyQualifiedName, + name: assignee.name, + }, + }, + ], + total: { value: 1 }, + }, + }) + ); + + await metric.visitEntityPage(page); + await page.getByTestId('activity_feed').click(); + await page + .getByTestId('metric-activity-composer') + .getByRole('textbox') + .fill(comment); + await page.getByTestId('metric-activity-composer-submit').click(); + await expect(page.getByText(comment, { exact: true })).toBeVisible(); + + const activityTab = page.getByTestId('metric-activity-tab'); + await activityTab.getByRole('tab', { name: /Tasks/ }).click(); + await page.getByTestId('metric-task-create').click(); + await expect(page.getByTestId('metric-task-create-dialog')).toBeVisible(); + await page.getByTestId('metric-task-create-title').fill(taskTitle); + const assigneeCheckbox = page.getByRole('checkbox', { + name: assignee.displayName, + }); + await assigneeCheckbox.focus(); + await assigneeCheckbox.press('Space'); + await expect(assigneeCheckbox).toBeChecked(); + await page + .getByTestId('metric-task-create-value') + .getByRole('textbox') + .fill('Use the governed net revenue definition.'); + await page.getByTestId('metric-task-create-submit').click(); + + const taskCard = page.getByTestId('metric-task-item-task-1'); + await expect(taskCard).toBeVisible(); + await expect(taskCard).toContainText(taskTitle); + await attachScreenshot( + page, + 'metric-activity-tab', + 'metric-activity-task' + ); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); + + test('shows the approval status pill on the approval tab', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + + try { + await metric.create(apiContext); + await metric.visitEntityPage(page); + await page.getByTestId('approval').click(); + + await expect(page.getByTestId('metric-approval-status')).toBeVisible(); + // No reviewers, so the metric was auto-approved and needs no decision. + await expect( + page.getByTestId('metric-approval-status-pill') + ).toContainText('Approved'); + await expect( + page.getByTestId('metric-approval-approve-btn') + ).toBeHidden(); + await expect(page.getByRole('button', { name: 'Submit' })).toHaveCount(0); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); + + test('uses real workflows for rejection, rollback, and reverse-chronological history', async ({ + browser, + }) => { + test.setTimeout(10 * 60 * 1_000); + + const { apiContext, afterAction } = await performAdminLogin(browser); + const reviewer = new UserClass(undefined, true); + const metricIds: string[] = []; + let reviewerCreated = false; + let reviewerAfterAction: (() => Promise) | undefined; + + try { + await reviewer.create(apiContext); + reviewerCreated = true; + + const approvedDescription = `Approved definition ${uuid()}`; + const pendingDescription = `Pending definition ${uuid()}`; + const approvalNote = `Approved baseline ${uuid()}`; + const rollbackNote = `Keep the approved definition ${uuid()}`; + const rollbackMetric = await createMetric(apiContext, { + description: approvedDescription, + name: `pw-metric-real-rollback-${uuid()}`, + reviewers: [{ id: reviewer.responseData.id, type: 'user' }], + }); + metricIds.push(rollbackMetric.id); + + await expectMetricStatus(apiContext, rollbackMetric.id, 'In Review'); + const approvalTaskId = await waitForOpenApprovalTask( + apiContext, + rollbackMetric.fullyQualifiedName, + 'Approved' + ); + const reviewerSession = await performUserLogin(browser, reviewer); + reviewerAfterAction = reviewerSession.afterAction; + const reviewerPage = reviewerSession.page; + + await visitMetricApproval( + reviewerPage, + rollbackMetric.fullyQualifiedName, + 'approve' + ); + await resolveApprovalInUi( + reviewerPage, + approvalTaskId, + 'Approved', + approvalNote + ); + await expectMetricSnapshot( + reviewerSession.apiContext, + rollbackMetric.id, + { + description: approvedDescription, + entityStatus: 'Approved', + } + ); + + await patchMetricDescription( + apiContext, + rollbackMetric.id, + pendingDescription + ); + await expectMetricSnapshot(apiContext, rollbackMetric.id, { + description: pendingDescription, + entityStatus: 'In Review', + }); + const rollbackTaskId = await waitForOpenApprovalTask( + apiContext, + rollbackMetric.fullyQualifiedName, + 'Rejected', + approvalTaskId + ); + + await visitMetricApproval( + reviewerPage, + rollbackMetric.fullyQualifiedName, + 'reject' + ); + await resolveApprovalInUi( + reviewerPage, + rollbackTaskId, + 'Rejected', + rollbackNote + ); + await expectMetricSnapshot( + reviewerSession.apiContext, + rollbackMetric.id, + { + description: approvedDescription, + entityStatus: 'Approved', + } + ); + + await reviewerPage.reload({ waitUntil: 'domcontentloaded' }); + await reviewerPage.getByTestId('approval').click(); + await expect( + reviewerPage.getByTestId('metric-approval-rollback') + ).toBeVisible({ timeout: 60_000 }); + const rollbackHistory = reviewerPage.getByTestId( + 'metric-approval-history' + ); + await expect(rollbackHistory).toContainText(rollbackNote, { + timeout: 60_000, + }); + await expect(rollbackHistory).toContainText(approvalNote); + await expect + .poll(async () => { + const historyItems = await rollbackHistory + .locator('li') + .allTextContents(); + const rollbackIndex = historyItems.findIndex((item) => + item.includes(rollbackNote) + ); + const approvalIndex = historyItems.findIndex((item) => + item.includes(approvalNote) + ); + + return ( + rollbackIndex >= 0 && + approvalIndex >= 0 && + rollbackIndex < approvalIndex + ); + }) + .toBe(true); + + const rejectionNote = `Reject incomplete metric ${uuid()}`; + const rejectedMetric = await createMetric(apiContext, { + description: `Incomplete definition ${uuid()}`, + name: `pw-metric-real-rejection-${uuid()}`, + reviewers: [{ id: reviewer.responseData.id, type: 'user' }], + }); + metricIds.push(rejectedMetric.id); + + await expectMetricStatus(apiContext, rejectedMetric.id, 'In Review'); + const rejectionTaskId = await waitForOpenApprovalTask( + apiContext, + rejectedMetric.fullyQualifiedName, + 'Rejected' + ); + await visitMetricApproval( + reviewerPage, + rejectedMetric.fullyQualifiedName, + 'reject' + ); + await resolveApprovalInUi( + reviewerPage, + rejectionTaskId, + 'Rejected', + rejectionNote + ); + await expectMetricStatus( + reviewerSession.apiContext, + rejectedMetric.id, + 'Rejected' + ); + + await reviewerPage.reload({ waitUntil: 'domcontentloaded' }); + await reviewerPage.getByTestId('approval').click(); + await expect( + reviewerPage.getByTestId('metric-approval-rejected') + ).toBeVisible({ timeout: 60_000 }); + await expect( + reviewerPage.getByTestId('metric-approval-history') + ).toContainText(rejectionNote, { timeout: 60_000 }); + await attachScreenshot( + reviewerPage, + 'metric-approval-tab', + 'metric-approval-history-real' + ); + } finally { + try { + await reviewerAfterAction?.(); + } finally { + try { + await Promise.all( + metricIds.map((metricId) => + apiContext.delete( + `/api/v1/metrics/${metricId}?recursive=true&hardDelete=true` + ) + ) + ); + } finally { + try { + if (reviewerCreated) { + await reviewer.delete(apiContext); + } + } finally { + await afterAction(); + } + } + } + } + }); + + test('edits the Metric definition from Overview', async ({ browser }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const metric = new MetricClass(); + const updatedExpression = `SUM(governed_revenue_${uuid()})`; + + try { + await metric.create(apiContext); + await metric.visitEntityPage(page); + await expect(page.getByTestId('metric-overview')).toBeVisible(); + await page.getByTestId('metric-definition-edit').click(); + const dialog = page.getByTestId('metric-definition-edit-dialog'); + await expect(dialog).toBeVisible(); + await dialog + .getByRole('textbox', { name: /Code/ }) + .fill(updatedExpression); + const patchResponse = page.waitForResponse( + (response) => + response.request().method() === 'PATCH' && + response.url().includes('/api/v1/metrics/') + ); + await page.getByTestId('metric-definition-save').click(); + expect((await patchResponse).ok()).toBeTruthy(); + await expect(dialog).toBeHidden(); + await expect(page.getByTestId('metric-definition-card')).toContainText( + updatedExpression + ); + await attachScreenshot(page, 'metric-overview', 'metric-overview-edited'); + } finally { + await metric.delete(apiContext); + await afterAction(); + } + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricHierarchy.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricHierarchy.spec.ts new file mode 100644 index 000000000000..ea702b80878f --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/MetricHierarchy.spec.ts @@ -0,0 +1,1163 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import type { APIRequestContext, Page } from '@playwright/test'; +import { expect, test } from '@playwright/test'; +import { RDG_ACTIVE_CELL_SELECTOR } from '../../constant/bulkImportExport'; +import { PLAYWRIGHT_BASIC_TEST_TAG_OBJ } from '../../constant/config'; +import { VIEW_ONLY_RULE } from '../../constant/permission'; +import { PolicyClass } from '../../support/access-control/PoliciesClass'; +import { RolesClass } from '../../support/access-control/RolesClass'; +import { UserClass } from '../../support/user/UserClass'; +import { performAdminLogin } from '../../utils/admin'; +import { uuid } from '../../utils/common'; +import { setupUserWithPolicy } from '../../utils/permission'; +import { performUserLogin } from '../../utils/user'; + +/** + * Metric hierarchy is a relationship-based tree over flat fully qualified names, so these tests + * exercise the API contract directly: that a child is reachable from its parent, that the parent + * filter partitions the list correctly, and that reparenting never rewrites a name. + */ + +interface EntityReferenceResponse { + id: string; + name?: string; + fullyQualifiedName?: string; + type?: string; +} + +interface MetricResponse { + id: string; + name: string; + fullyQualifiedName: string; + displayName?: string; + entityStatus?: string; + parent?: EntityReferenceResponse; + children?: EntityReferenceResponse[]; + childrenCount?: number; + metricGroup?: EntityReferenceResponse; + reviewers?: EntityReferenceResponse[]; +} + +interface MetricListResponse { + data: MetricResponse[]; +} + +interface MetricGroupResponse { + id: string; + name: string; + fullyQualifiedName: string; + metricCount?: number; +} + +const createMetric = async ( + apiContext: APIRequestContext, + name: string, + parent?: string, + metricGroup?: string, + owners?: EntityReferenceResponse[] +): Promise => { + const response = await apiContext.post('/api/v1/metrics', { + data: { + name, + description: `Metric ${name}`, + displayName: name, + granularity: 'DAY', + metricExpression: { code: 'COUNT(*)', language: 'SQL' }, + metricType: 'COUNT', + unitOfMeasurement: 'COUNT', + ...(parent ? { parent } : {}), + ...(metricGroup ? { metricGroup } : {}), + ...(owners?.length ? { owners } : {}), + }, + }); + + expect(response.status()).toBe(201); + + return (await response.json()) as MetricResponse; +}; + +const createMetricGroup = async ( + apiContext: APIRequestContext, + name: string +): Promise => { + const response = await apiContext.post('/api/v1/metricGroups', { + data: { name, displayName: name, description: `Metric group ${name}` }, + }); + + expect(response.status()).toBe(201); + + return (await response.json()) as MetricGroupResponse; +}; + +const getMetric = async ( + apiContext: APIRequestContext, + id: string, + fields = 'parent,children,childrenCount' +): Promise => { + const response = await apiContext.get( + `/api/v1/metrics/${id}?fields=${fields}` + ); + + expect(response.ok()).toBeTruthy(); + + return (await response.json()) as MetricResponse; +}; + +const listByParent = async ( + apiContext: APIRequestContext, + parent: string +): Promise => { + const response = await apiContext.get( + `/api/v1/metrics?parent=${encodeURIComponent( + parent + )}&fields=parent,childrenCount&limit=1000` + ); + + expect(response.ok()).toBeTruthy(); + + return (await response.json()) as MetricListResponse; +}; + +const waitForMetricIndexed = async ( + apiContext: APIRequestContext, + name: string +) => { + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/search/query?q=${encodeURIComponent( + name + )}&index=metric&from=0&size=10` + ); + const data = (await response.json()) as { + hits?: { total?: { value?: number } }; + }; + + return data.hits?.total?.value ?? 0; + }, + { timeout: 90_000 } + ) + .toBeGreaterThan(0); +}; + +const waitForMetricHierarchySearch = (page: Page, query: string) => + page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'GET' && + url.pathname.endsWith('/api/v1/metrics/hierarchy') && + url.searchParams.get('q') === query + ); + }); + +const attachScreenshot = async (page: Page, testId: string, name: string) => { + const target = page.getByTestId(testId); + await expect(target).toBeVisible(); + await page.evaluate(async () => { + await document.fonts.ready; + }); + const firstBounds = await target.boundingBox(); + + expect(firstBounds).not.toBeNull(); + expect(firstBounds?.width).toBeGreaterThan(0); + expect(firstBounds?.height).toBeGreaterThan(0); + + await target.evaluate( + () => + new Promise((resolve) => { + requestAnimationFrame(() => requestAnimationFrame(() => resolve())); + }) + ); + + const stableBounds = await target.boundingBox(); + + expect(stableBounds).not.toBeNull(); + expect( + Math.abs((stableBounds?.x ?? 0) - (firstBounds?.x ?? 0)) + ).toBeLessThanOrEqual(1); + expect( + Math.abs((stableBounds?.y ?? 0) - (firstBounds?.y ?? 0)) + ).toBeLessThanOrEqual(1); + expect( + Math.abs((stableBounds?.width ?? 0) - (firstBounds?.width ?? 0)) + ).toBeLessThanOrEqual(1); + expect( + Math.abs((stableBounds?.height ?? 0) - (firstBounds?.height ?? 0)) + ).toBeLessThanOrEqual(1); + + const body = await target.screenshot({ animations: 'disabled' }); + const devicePixelRatio = await page.evaluate(() => window.devicePixelRatio); + const pngWidth = body.readUInt32BE(16); + const pngHeight = body.readUInt32BE(20); + + expect(body.subarray(0, 8).toString('hex')).toBe('89504e470d0a1a0a'); + expect(body.byteLength).toBeGreaterThan(1_024); + expect(pngWidth).toBeGreaterThan(0); + expect(pngHeight).toBeGreaterThan(0); + expect( + Math.abs( + pngWidth - Math.round((stableBounds?.width ?? 0) * devicePixelRatio) + ) + ).toBeLessThanOrEqual(2); + expect( + Math.abs( + pngHeight - Math.round((stableBounds?.height ?? 0) * devicePixelRatio) + ) + ).toBeLessThanOrEqual(2); + + await test.info().attach(name, { + body, + contentType: 'image/png', + }); +}; + +const fillRequiredMetricFields = async (page: Page, name: string) => { + await page.getByTestId('name').fill(name); + await page.getByTestId('metric-code').getByRole('textbox').fill('COUNT(*)'); +}; + +const waitForMetricBulkEditGrid = async (page: Page, metricName: string) => { + await expect(page).toHaveURL(/\/bulk\/edit\/metric\/\*/); + await expect(page.locator('.rdg-header-row')).toBeVisible({ + timeout: 90_000, + }); + await expect( + page.locator('.bulk-edit-name-value').filter({ hasText: metricName }) + ).toBeVisible(); +}; + +const editMetricDisplayName = async ( + page: Page, + metricName: string, + displayName: string +) => { + const displayNameCell = page + .locator('.rdg-row') + .filter({ hasText: metricName }) + .locator('[aria-colindex="3"]'); + + await displayNameCell.dblclick(); + const editor = page.locator(`${RDG_ACTIVE_CELL_SELECTOR} input`); + await expect(editor).toBeVisible(); + await editor.fill(displayName); + await editor.press('Enter'); + await expect(displayNameCell).toContainText(displayName); +}; + +const waitForMetricImportResponse = (page: Page, dryRun: boolean) => + page.waitForResponse( + (response) => + response.request().method() === 'PUT' && + response.url().includes('/api/v1/metrics/name/') && + response.url().includes('/importAsync') && + response.url().includes(`dryRun=${String(dryRun)}`) + ); + +const expectMetricImportStatus = async (page: Page) => { + await expect(page.getByTestId('processed-row')).toContainText('1'); + await expect(page.getByTestId('passed-row')).toContainText('1'); + await expect(page.getByTestId('failed-row')).toContainText('0'); + await expect(page.locator('.rdg-header-row')).toBeVisible(); +}; + +test.describe('Metric Hierarchy', PLAYWRIGHT_BASIC_TEST_TAG_OBJ, () => { + test('establishes a parent-child relationship without changing names', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const suffix = uuid(); + const parentName = `pw-metric-parent-${suffix}`; + const childName = `pw-metric-child-${suffix}`; + + try { + const parent = await createMetric(apiContext, parentName); + const child = await createMetric(apiContext, childName, parentName); + + expect(child.parent?.id).toBe(parent.id); + expect(child.fullyQualifiedName).toBe(childName); + + const fetchedParent = await getMetric(apiContext, parent.id); + + expect(fetchedParent.childrenCount).toBe(1); + expect(fetchedParent.children).toHaveLength(1); + expect(fetchedParent.children?.[0].id).toBe(child.id); + } finally { + await afterAction(); + } + }); + + test('partitions the listing into roots and immediate children', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const suffix = uuid(); + const parentName = `pw-metric-roots-${suffix}`; + const childName = `pw-metric-kid-${suffix}`; + const grandChildName = `pw-metric-grandkid-${suffix}`; + + try { + const parent = await createMetric(apiContext, parentName); + const child = await createMetric(apiContext, childName, parentName); + const grandChild = await createMetric( + apiContext, + grandChildName, + childName + ); + + const roots = await listByParent(apiContext, 'null'); + const rootIds = roots.data.map((m: { id: string }) => m.id); + + expect(rootIds).toContain(parent.id); + expect(rootIds).not.toContain(child.id); + + const children = await listByParent(apiContext, parentName); + const childIds = children.data.map((m: { id: string }) => m.id); + + expect(childIds).toEqual([child.id]); + expect(childIds).not.toContain(grandChild.id); + } finally { + await afterAction(); + } + }); + + test('rejects a cycle when reparenting', async ({ browser }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const suffix = uuid(); + const parentName = `pw-metric-cyc-a-${suffix}`; + const childName = `pw-metric-cyc-b-${suffix}`; + + try { + const parent = await createMetric(apiContext, parentName); + const child = await createMetric(apiContext, childName, parentName); + + const response = await apiContext.patch(`/api/v1/metrics/${parent.id}`, { + data: [ + { + op: 'add', + path: '/parent', + value: { id: child.id, type: 'metric' }, + }, + ], + headers: { 'Content-Type': 'application/json-patch+json' }, + }); + + expect(response.status()).toBe(400); + } finally { + await afterAction(); + } + }); + + test('moves the edge on reparent and keeps the fully qualified name', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const suffix = uuid(); + const oldParentName = `pw-metric-old-${suffix}`; + const newParentName = `pw-metric-new-${suffix}`; + const childName = `pw-metric-moved-${suffix}`; + + try { + const oldParent = await createMetric(apiContext, oldParentName); + const newParent = await createMetric(apiContext, newParentName); + const child = await createMetric(apiContext, childName, oldParentName); + + const response = await apiContext.patch(`/api/v1/metrics/${child.id}`, { + data: [ + { + op: 'replace', + path: '/parent', + value: { id: newParent.id, type: 'metric' }, + }, + ], + headers: { 'Content-Type': 'application/json-patch+json' }, + }); + + expect(response.ok()).toBeTruthy(); + + const moved = await response.json(); + + expect(moved.fullyQualifiedName).toBe(childName); + + const oldParentAfter = await getMetric(apiContext, oldParent.id); + const newParentAfter = await getMetric(apiContext, newParent.id); + + expect(oldParentAfter.childrenCount).toBe(0); + expect(newParentAfter.childrenCount).toBe(1); + } finally { + await afterAction(); + } + }); + + test('lists roots and reveals children on expand in the list page', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const suffix = uuid(); + const parentName = `pw-metric-ui-parent-${suffix}`; + const childName = `pw-metric-ui-child-${suffix}`; + // Declared out here so the cleanup can still reach it. + let parentId: string | undefined; + + try { + parentId = (await createMetric(apiContext, parentName)).id; + await createMetric(apiContext, childName, parentName); + + const rootsRequest = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + url.pathname.endsWith('/api/v1/metrics/hierarchy') && + url.searchParams.get('offset') === '0' + ); + }); + await page.goto('/metrics'); + await rootsRequest; + + const searchResponse = waitForMetricHierarchySearch(page, parentName); + await page + .getByTestId('metric-search') + .getByRole('textbox') + .fill(parentName); + expect((await searchResponse).ok()).toBeTruthy(); + + // Metric variants remain collapsed until their parent is explicitly expanded. + await expect(page.getByText(parentName, { exact: true })).toBeVisible(); + await expect(page.getByText(childName, { exact: true })).toBeHidden(); + + const parentRow = page.getByRole('row', { + name: new RegExp(parentName), + }); + const metricsListUrl = page.url(); + + await parentRow.locator('label[slot="selection"]').click(); + await expect(page).toHaveURL(metricsListUrl); + await expect(page.getByTestId('bulk-edit-metric')).toBeVisible(); + await page.getByRole('button', { name: 'Clear' }).click(); + + await parentRow.getByTestId(`expand-${parentId}`).click(); + + await expect(page.getByText(childName, { exact: true })).toBeVisible(); + + await parentRow.getByRole('link', { name: parentName }).click(); + await expect(page).toHaveURL(new RegExp(`/metric/${parentName}$`)); + await expect(page.getByTestId('metric-details-page')).toBeVisible(); + } finally { + if (parentId) { + await apiContext.delete( + `/api/v1/metrics/${parentId}?hardDelete=true&recursive=true` + ); + } + await afterAction(); + } + }); + + test('switches list layouts and exercises group, search, filter, columns, and bulk controls', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const suffix = uuid(); + const groupName = `pw-metric-group-ui-${suffix}`; + const rootName = `pw-metric-list-root-${suffix}`; + const childName = `pw-metric-list-child-${suffix}`; + let root: MetricResponse | undefined; + let group: MetricGroupResponse | undefined; + + try { + const createdGroup = await createMetricGroup(apiContext, groupName); + group = createdGroup; + root = await createMetric( + apiContext, + rootName, + undefined, + createdGroup.fullyQualifiedName + ); + await createMetric(apiContext, childName, rootName); + await waitForMetricIndexed(apiContext, rootName); + + const groupMetricsResponse = page.waitForResponse((response) => + response + .url() + .includes(`/api/v1/metricGroups/${createdGroup.id}/metrics`) + ); + const hierarchyResponse = page.waitForResponse((response) => + response.url().includes('/api/v1/metrics/hierarchy') + ); + await page.goto('/metrics'); + await Promise.all([hierarchyResponse, groupMetricsResponse]); + + const groupToggle = page.getByTestId(`metric-group-${groupName}`); + await expect(groupToggle).toBeVisible(); + await expect(page.getByText(rootName, { exact: true })).toBeVisible(); + await expect(page.getByText(childName, { exact: true })).toBeHidden(); + + await page.getByTestId('metric-card-view-button').click(); + await expect(page.getByTestId('metric-card-view')).toBeVisible(); + await expect( + page.getByTestId(`metric-group-card-${groupName}`) + ).toBeVisible(); + await attachScreenshot(page, 'metric-list-page', 'metric-list-card-view'); + await groupToggle.click(); + await expect(page.getByText(rootName, { exact: true })).toBeHidden(); + await groupToggle.click(); + await expect(page.getByText(rootName, { exact: true })).toBeVisible(); + + await page.getByTestId('metric-table-view-button').click(); + await expect(page.getByRole('grid', { name: 'Metrics' })).toBeVisible(); + await page.getByTestId(`expand-${root.id}`).click(); + await expect(page.getByText(childName, { exact: true })).toBeVisible(); + + const rootRow = page.getByRole('row', { name: new RegExp(rootName) }); + await rootRow.locator('label[slot="selection"]').click(); + await expect(page.getByTestId('bulk-edit-metric')).toBeVisible(); + await expect(page.getByTestId('bulk-delete-metric')).toBeVisible(); + await page.getByRole('button', { name: 'Clear' }).click(); + + const searchResponse = waitForMetricHierarchySearch(page, rootName); + await page + .getByTestId('metric-search') + .getByRole('textbox') + .fill(rootName); + await searchResponse; + await expect(page.getByTestId('metric-name')).toHaveCount(1); + await expect(page.getByText(rootName, { exact: true })).toBeVisible(); + + const statusResponse = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + url.pathname.endsWith('/api/v1/search/query') && + decodeURIComponent( + url.searchParams.get('query_filter') ?? '' + ).includes('Approved') + ); + }); + await page.getByTestId('metric-search').getByRole('textbox').fill(''); + await page.getByRole('button', { name: 'Status', exact: true }).click(); + await page.getByRole('menuitemradio', { name: 'Approved' }).click(); + await statusResponse; + await expect(rootRow.getByTestId('metric-status-pill')).toContainText( + 'Approved' + ); + + await page.getByRole('button', { name: 'Customize' }).click(); + await page + .getByRole('button', { name: 'Description', exact: true }) + .click(); + await expect( + page.getByRole('columnheader', { name: 'Description' }) + ).toHaveCount(0); + } finally { + if (root) { + await apiContext.delete( + `/api/v1/metrics/${root.id}?hardDelete=true&recursive=true` + ); + } + if (group) { + await apiContext.delete( + `/api/v1/metricGroups/${group.id}?hardDelete=true&recursive=true` + ); + } + await afterAction(); + } + }); + + test('executes bulk edit and bulk delete for selected metrics', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const suffix = uuid(); + const editableMetricName = `pw-metric-bulk-edit-${suffix}`; + const deletableMetricName = `pw-metric-bulk-delete-${suffix}`; + const updatedDisplayName = `Bulk edited metric ${suffix}`; + let editableMetric: MetricResponse | undefined; + let deletableMetric: MetricResponse | undefined; + + try { + editableMetric = await createMetric(apiContext, editableMetricName); + deletableMetric = await createMetric(apiContext, deletableMetricName); + await Promise.all([ + waitForMetricIndexed(apiContext, editableMetricName), + waitForMetricIndexed(apiContext, deletableMetricName), + ]); + + const hierarchyResponse = page.waitForResponse((response) => + response.url().includes('/api/v1/metrics/hierarchy') + ); + await page.goto('/metrics'); + await hierarchyResponse; + + const editableSearchResponse = waitForMetricHierarchySearch( + page, + editableMetricName + ); + await page + .getByTestId('metric-search') + .getByRole('textbox') + .fill(editableMetricName); + await editableSearchResponse; + + const editableRow = page.getByRole('row', { + name: new RegExp(editableMetricName), + }); + await expect(editableRow).toBeVisible(); + await editableRow.locator('label[slot="selection"]').click(); + await page.getByTestId('bulk-edit-metric').click(); + await waitForMetricBulkEditGrid(page, editableMetricName); + await editMetricDisplayName(page, editableMetricName, updatedDisplayName); + + const validateResponse = waitForMetricImportResponse(page, true); + await page + .locator('.bulk-edit-add-row-actions') + .getByRole('button', { name: 'Next' }) + .click(); + expect((await validateResponse).ok()).toBeTruthy(); + await expectMetricImportStatus(page); + + const updateResponse = waitForMetricImportResponse(page, false); + await page.getByRole('button', { name: 'Update' }).click(); + expect((await updateResponse).ok()).toBeTruthy(); + await page.waitForURL(/\/metrics(?:\?|$)/, { timeout: 90_000 }); + + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/metrics/name/${encodeURIComponent(editableMetricName)}` + ); + + if (!response.ok()) { + return undefined; + } + + return ((await response.json()) as MetricResponse).displayName; + }, + { timeout: 90_000 } + ) + .toBe(updatedDisplayName); + + const deletableSearchResponse = waitForMetricHierarchySearch( + page, + deletableMetricName + ); + await page + .getByTestId('metric-search') + .getByRole('textbox') + .fill(deletableMetricName); + await deletableSearchResponse; + + const deletableRow = page.getByRole('row', { + name: new RegExp(deletableMetricName), + }); + await expect(deletableRow).toBeVisible(); + await deletableRow.locator('label[slot="selection"]').click(); + await page.getByTestId('bulk-delete-metric').click(); + await expect( + page.getByRole('dialog', { name: 'Delete Metrics' }) + ).toBeVisible(); + + const deleteResponse = page.waitForResponse( + (response) => + response.request().method() === 'DELETE' && + new URL(response.url()).pathname.endsWith( + `/api/v1/metrics/async/${deletableMetric?.id}` + ) + ); + await page.getByTestId('confirm-button').click(); + expect((await deleteResponse).ok()).toBeTruthy(); + await expect( + page.getByRole('dialog', { name: 'Delete Metrics' }) + ).toBeHidden(); + + await expect + .poll( + async () => + ( + await apiContext.get(`/api/v1/metrics/${deletableMetric?.id}`) + ).status(), + { timeout: 90_000 } + ) + .toBe(404); + } finally { + await Promise.all( + [editableMetric, deletableMetric] + .filter((metric): metric is MetricResponse => Boolean(metric)) + .map(({ id }) => + apiContext.delete( + `/api/v1/metrics/${id}?hardDelete=true&recursive=true` + ) + ) + ); + await afterAction(); + } + }); + + test('creates a group, root, and child from the UI and completes the Overview edit flow', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const suffix = uuid(); + const groupName = `pw-ui-created-group-${suffix}`; + const rootName = `pw-ui-created-root-${suffix}`; + const childName = `pw-ui-created-child-${suffix}`; + let root: MetricResponse | undefined; + let group: MetricGroupResponse | undefined; + + try { + await page.goto('/metrics/add-metric'); + await fillRequiredMetricFields(page, rootName); + const groupCombo = page + .getByTestId('metric-group-select') + .getByRole('combobox'); + const groupResolution = page.waitForResponse((response) => + new URL(response.url()).pathname.endsWith( + `/api/v1/metricGroups/name/${encodeURIComponent(groupName)}` + ) + ); + await groupCombo.fill(groupName); + expect((await groupResolution).status()).toBe(404); + const createGroupOption = page.getByRole('option', { + name: new RegExp(`^Create ${groupName}`), + }); + await groupCombo.press('ArrowDown'); + await expect(createGroupOption).toBeVisible(); + await groupCombo.press('End'); + await expect(createGroupOption).toHaveAttribute('data-focused', 'true'); + await groupCombo.press('Enter'); + await expect(groupCombo).toHaveValue(groupName); + + const groupCreateResponse = page.waitForResponse( + (response) => + response.request().method() === 'POST' && + new URL(response.url()).pathname.endsWith('/api/v1/metricGroups') + ); + const rootResponse = page.waitForResponse( + (response) => + response.request().method() === 'POST' && + new URL(response.url()).pathname.endsWith('/api/v1/metrics') + ); + await page.getByTestId('create-button').click(); + expect((await groupCreateResponse).ok()).toBeTruthy(); + root = (await (await rootResponse).json()) as MetricResponse; + + await expect(page.getByTestId('metric-details-page')).toBeVisible(); + await expect(page.getByRole('heading', { name: rootName })).toBeVisible(); + const detailHeader = page.getByTestId('metric-detail-header'); + await expect(detailHeader).toContainText(root.fullyQualifiedName); + await expect( + detailHeader.getByTestId('metric-status-pill') + ).toContainText('Approved'); + await expect(detailHeader.getByTestId('metric-type')).toBeVisible(); + await expect(page.getByTestId('metric-definition-unit')).toBeVisible(); + await expect(detailHeader.getByTestId('granularity')).toBeVisible(); + await expect( + detailHeader.getByTestId('metric-header-health-pill') + ).toBeVisible({ timeout: 60_000 }); + await expect(page.getByTestId('metric-header-owner')).toBeVisible(); + await expect(page.getByTestId('metric-header-domain')).toBeVisible(); + await expect(page.getByTestId('metric-header-tier')).toBeVisible(); + await expect(page.getByTestId('metric-tree-group')).toContainText( + groupName + ); + await expect(page.getByTestId('metric-tree-current')).toContainText( + rootName + ); + + const groupResponse = await apiContext.get( + `/api/v1/metricGroups/name/${encodeURIComponent(groupName)}` + ); + expect(groupResponse.ok()).toBeTruthy(); + group = (await groupResponse.json()) as MetricGroupResponse; + + await page.getByRole('link', { name: 'Add Child Metric' }).click(); + await expect(page.getByTestId('metric-group-inherited')).toContainText( + rootName + ); + await attachScreenshot( + page, + 'add-metric-container', + 'metric-add-child-inherited' + ); + await fillRequiredMetricFields(page, childName); + const childResponse = page.waitForResponse( + (response) => + response.request().method() === 'POST' && + new URL(response.url()).pathname.endsWith('/api/v1/metrics') + ); + await page.getByTestId('create-button').click(); + const child = (await (await childResponse).json()) as MetricResponse; + + expect(child.parent?.id).toBe(root.id); + expect(child.metricGroup?.id).toBe(group.id); + await expect( + page.getByTestId(`metric-tree-ancestor-${root.id}`) + ).toContainText(rootName); + await page.getByTestId(`metric-tree-ancestor-${root.id}`).click(); + await expect(page.getByRole('heading', { name: rootName })).toBeVisible(); + await expect( + page.getByTestId(`metric-tree-child-${child.id}`) + ).toContainText(childName); + + await page.getByTestId('metric-definition-edit').click(); + const expression = page + .getByTestId('metric-definition-edit-dialog') + .getByRole('textbox', { name: 'Code' }); + await expression.fill('COUNT(DISTINCT order_id)'); + const patchResponse = page.waitForResponse( + (response) => + response.request().method() === 'PATCH' && + new URL(response.url()).pathname.endsWith( + `/api/v1/metrics/${root?.id}` + ) + ); + await page.getByTestId('metric-definition-save').click(); + await patchResponse; + await expect(page.getByTestId('metric-expression-code')).toContainText( + 'COUNT(DISTINCT order_id)' + ); + + await expect(page.getByTestId('edit-metric-metadata')).toBeVisible(); + await page.getByTestId('edit-metric-metadata').click(); + await expect( + page.getByTestId('metric-metadata-edit-dialog') + ).toBeVisible(); + await page + .getByTestId('metric-metadata-edit-dialog') + .getByRole('button', { name: 'Cancel' }) + .click(); + + const definitionDesktop = await page + .getByTestId('metric-definition-card') + .boundingBox(); + const railDesktop = await page + .getByTestId('metric-metadata-rail') + .boundingBox(); + expect(definitionDesktop).not.toBeNull(); + expect(railDesktop).not.toBeNull(); + expect(railDesktop?.x).toBeGreaterThan(definitionDesktop?.x ?? 0); + + await page.setViewportSize({ height: 844, width: 390 }); + const definitionNarrow = await page + .getByTestId('metric-definition-card') + .boundingBox(); + const railNarrow = await page + .getByTestId('metric-metadata-rail') + .boundingBox(); + expect(railNarrow?.width).toBeLessThanOrEqual(390); + expect(railNarrow?.y).toBeGreaterThan(definitionNarrow?.y ?? 0); + await attachScreenshot( + page, + 'metric-details-page', + 'metric-overview-narrow' + ); + } finally { + if (root) { + await apiContext.delete( + `/api/v1/metrics/${root.id}?hardDelete=true&recursive=true` + ); + } + if (group) { + await apiContext.delete( + `/api/v1/metricGroups/${group.id}?hardDelete=true&recursive=true` + ); + } + await afterAction(); + } + }); + + test('keeps Overview metadata visible while hiding edits from read-only users', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const readOnlyUser = new UserClass(); + const readOnlyPolicy = new PolicyClass(); + const readOnlyRole = new RolesClass(); + const metricName = `pw-metric-read-only-overview-${uuid()}`; + let metric: MetricResponse | undefined; + let readOnlyAfterAction: (() => Promise) | undefined; + let userCreated = false; + + try { + const adminResponse = await apiContext.get('/api/v1/users/name/admin'); + expect(adminResponse.ok()).toBeTruthy(); + const admin = (await adminResponse.json()) as EntityReferenceResponse; + metric = await createMetric( + apiContext, + metricName, + undefined, + undefined, + [{ id: admin.id, name: admin.name, type: 'user' }] + ); + await setupUserWithPolicy( + apiContext, + readOnlyUser, + readOnlyPolicy, + readOnlyRole, + VIEW_ONLY_RULE + ); + userCreated = true; + + const readOnlySession = await performUserLogin(browser, readOnlyUser); + readOnlyAfterAction = readOnlySession.afterAction; + await readOnlySession.page.goto( + `/metric/${encodeURIComponent(metric.fullyQualifiedName)}`, + { waitUntil: 'domcontentloaded' } + ); + + const detailsPage = readOnlySession.page.getByTestId( + 'metric-details-page' + ); + await expect(detailsPage).toBeVisible({ timeout: 60_000 }); + const detailHeader = detailsPage.getByTestId('metric-detail-header'); + await expect(detailHeader).toContainText(metric.fullyQualifiedName); + await expect(detailHeader.getByTestId('metric-type')).toContainText( + 'Count' + ); + await expect( + detailsPage.getByTestId('metric-definition-unit') + ).toContainText('Count'); + await expect(detailHeader.getByTestId('granularity')).toContainText( + 'Day' + ); + await expect( + detailHeader.getByTestId('metric-status-pill') + ).toContainText('Approved'); + await expect( + detailHeader.getByTestId('metric-header-health-pill') + ).toBeVisible({ timeout: 60_000 }); + await expect( + detailsPage.getByTestId('metric-definition-edit') + ).toHaveCount(0); + await expect(detailsPage.getByTestId('edit-metric-metadata')).toHaveCount( + 0 + ); + } finally { + try { + await readOnlyAfterAction?.(); + } finally { + try { + if (metric) { + await apiContext.delete( + `/api/v1/metrics/${metric.id}?hardDelete=true&recursive=true` + ); + } + } finally { + try { + if (userCreated) { + await readOnlyUser.delete(apiContext); + } + } finally { + try { + if (readOnlyRole.responseData?.id) { + await readOnlyRole.delete(apiContext); + } + } finally { + try { + if (readOnlyPolicy.responseData?.id) { + await readOnlyPolicy.delete(apiContext); + } + } finally { + await afterAction(); + } + } + } + } + } + } + }); + + test('paginates top-level hierarchy results', async ({ browser }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const suffix = uuid(); + const metrics: MetricResponse[] = []; + + try { + metrics.push( + ...(await Promise.all( + Array.from({ length: 21 }, (_, index) => + createMetric( + apiContext, + `pw-metric-page-${String(index).padStart(2, '0')}-${suffix}` + ) + ) + )) + ); + const firstPage = page.waitForResponse((response) => + response.url().includes('/api/v1/metrics/hierarchy') + ); + await page.goto('/metrics'); + await firstPage; + await expect(page.getByTestId('metric-page-next')).toBeVisible(); + + const secondPage = page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + url.pathname.endsWith('/api/v1/metrics/hierarchy') && + url.searchParams.get('offset') === '20' + ); + }); + await page.getByTestId('metric-page-next').click(); + await secondPage; + await expect(page.getByTestId('metric-page-previous')).toBeEnabled(); + await expect( + page.getByRole('navigation', { name: 'Page' }) + ).toContainText('Page 2'); + } finally { + await Promise.all( + metrics.map(({ id }) => + apiContext.delete( + `/api/v1/metrics/${id}?hardDelete=true&recursive=true` + ) + ) + ); + await afterAction(); + } + }); + + test('creates an In Review metric through the UI when a reviewer is selected', async ({ + browser, + }) => { + const { page, apiContext, afterAction } = await performAdminLogin(browser, { + navigate: true, + }); + const reviewer = new UserClass(); + const metricName = `pw-ui-review-${uuid()}`; + let metric: MetricResponse | undefined; + + try { + await reviewer.create(apiContext); + const reviewerName = reviewer.responseData.name; + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/search/query?q=${encodeURIComponent( + reviewerName + )}&index=user&from=0&size=10` + ); + const data = (await response.json()) as { + hits?: { total?: { value?: number } }; + }; + + return data.hits?.total?.value ?? 0; + }, + { timeout: 90_000 } + ) + .toBeGreaterThan(0); + + await page.goto('/metrics/add-metric'); + await fillRequiredMetricFields(page, metricName); + await page + .getByRole('textbox', { name: 'Description' }) + .fill(`Metric ${metricName}`); + const reviewerPicker = page.getByRole('group', { name: 'Reviewers' }); + await reviewerPicker.getByRole('textbox').fill(reviewerName); + const reviewerCheckbox = reviewerPicker.getByRole('checkbox', { + name: reviewer.responseData.displayName ?? reviewerName, + }); + await reviewerCheckbox.focus(); + await reviewerCheckbox.press('Space'); + await expect(reviewerCheckbox).toBeChecked(); + + const createResponse = page.waitForResponse( + (response) => + response.request().method() === 'POST' && + new URL(response.url()).pathname.endsWith('/api/v1/metrics') + ); + await page.getByTestId('create-button').click(); + const response = await createResponse; + const createdMetric = (await response.json()) as MetricResponse; + metric = createdMetric; + expect(createdMetric.reviewers?.map(({ id }) => id)).toContain( + reviewer.responseData.id + ); + + await expect + .poll( + async () => { + const response = await apiContext.get( + `/api/v1/metrics/${createdMetric.id}` + ); + if (!response.ok()) { + return undefined; + } + + return ((await response.json()) as MetricResponse).entityStatus; + }, + { + intervals: [1_000, 2_000, 5_000], + timeout: 120_000, + } + ) + .toBe('In Review'); + + await expect(page.getByTestId('metric-details-page')).toBeVisible({ + timeout: 60_000, + }); + await page.reload({ waitUntil: 'domcontentloaded' }); + await expect(page.getByTestId('metric-status-pill')).toContainText( + 'In Review', + { timeout: 60_000 } + ); + } finally { + if (metric) { + await apiContext.delete( + `/api/v1/metrics/${metric.id}?hardDelete=true&recursive=true` + ); + } + await reviewer.delete(apiContext); + await afterAction(); + } + }); + + test('refuses to delete a parent without recursive, then succeeds with it', async ({ + browser, + }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + const suffix = uuid(); + const parentName = `pw-metric-del-${suffix}`; + const childName = `pw-metric-delkid-${suffix}`; + + try { + const parent = await createMetric(apiContext, parentName); + await createMetric(apiContext, childName, parentName); + + const blocked = await apiContext.delete( + `/api/v1/metrics/${parent.id}?hardDelete=true` + ); + + expect(blocked.status()).toBe(400); + + const allowed = await apiContext.delete( + `/api/v1/metrics/${parent.id}?hardDelete=true&recursive=true` + ); + + expect(allowed.ok()).toBeTruthy(); + } finally { + await afterAction(); + } + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/MetricListSearch.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/MetricListSearch.spec.ts index 2070f1edcd7b..0c345284f2cc 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/MetricListSearch.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/MetricListSearch.spec.ts @@ -13,12 +13,7 @@ import test, { expect, Page } from '@playwright/test'; import { SidebarItem } from '../../constant/sidebar'; import { MetricClass } from '../../support/entity/MetricClass'; -import { - createNewPage, - redirectToHomePage, - uuid, - waitForMetricsSearchResponse, -} from '../../utils/common'; +import { createNewPage, redirectToHomePage, uuid } from '../../utils/common'; import { waitForAllLoadersToDisappear } from '../../utils/entity'; import { sidebarClick } from '../../utils/sidebar'; @@ -55,10 +50,21 @@ const waitForMetricIndexed = async ( }).toPass({ timeout: 90_000, intervals: [2_000] }); }; +const waitForMetricHierarchyResponse = (page: Page, query?: string) => + page.waitForResponse((response) => { + const url = new URL(response.url()); + + return ( + response.request().method() === 'GET' && + url.pathname.endsWith('/api/v1/metrics/hierarchy') && + (query === undefined || url.searchParams.get('q') === query) + ); + }); + const goToMetricList = async (page: Page) => { await redirectToHomePage(page); - const listResponse = waitForMetricsSearchResponse(page); + const listResponse = waitForMetricHierarchyResponse(page); await sidebarClick(page, SidebarItem.METRICS); await listResponse; @@ -107,16 +113,7 @@ test.describe('Metric List Page - Search', { tag: ['@Discovery'] }, () => { // The debounced search must actually reach the API. Regression #29538 // cancelled this request on the re-render that typing triggered, so the // list never filtered — this waitForResponse would then time out. - const searchResponse = page.waitForResponse((response) => { - const url = new URL(response.url()); - - return ( - response.request().method() === 'GET' && - url.pathname.endsWith('/api/v1/search/query') && - url.searchParams.get('index') === 'metric' && - url.searchParams.get('q') === matchName - ); - }); + const searchResponse = waitForMetricHierarchyResponse(page, matchName); await searchInput.fill(matchName); @@ -138,7 +135,7 @@ test.describe('Metric List Page - Search', { tag: ['@Discovery'] }, () => { }); await test.step('clearing the search restores the full list', async () => { - const clearResponse = waitForMetricsSearchResponse(page); + const clearResponse = waitForMetricHierarchyResponse(page); await searchInput.fill(''); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts index 022a8444a852..25e8d1895315 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Entity.spec.ts @@ -293,39 +293,65 @@ Object.entries(entities).forEach(([key, EntityClass]) => { ) .toBeTruthy(); - await addMultiOwner({ - page, - ownerNames: [OWNER2.getUserDisplayName()], - activatorBtnDataTestId: 'edit-owner', - resultTestId: 'data-assets-header', - endpoint: entity.endpoint, - type: 'Users', - }); + if (entity.type === 'Metric') { + const metric = entity as MetricClass; + const owner1Name = OWNER1.getUserDisplayName(); + const owner2Name = OWNER2.getUserDisplayName(); + await metric.updateOwnerSelection({ + added: [owner2Name], + included: [owner2Name], + page, + }); + await metric.updateOwnerSelection({ + added: [owner1Name], + included: [owner2Name, owner1Name], + page, + }); + await metric.updateOwnerSelection({ + included: [owner2Name], + page, + removed: [owner1Name], + }); + await metric.updateOwnerSelection({ + included: [], + page, + removed: [owner2Name], + }); + } else { + await addMultiOwner({ + page, + ownerNames: [OWNER2.getUserDisplayName()], + activatorBtnDataTestId: 'edit-owner', + resultTestId: 'data-assets-header', + endpoint: entity.endpoint, + type: 'Users', + }); - await addMultiOwner({ - page, - ownerNames: [OWNER1.getUserDisplayName()], - activatorBtnDataTestId: 'edit-owner', - resultTestId: 'data-assets-header', - endpoint: entity.endpoint, - type: 'Users', - clearAll: false, - }); + await addMultiOwner({ + page, + ownerNames: [OWNER1.getUserDisplayName()], + activatorBtnDataTestId: 'edit-owner', + resultTestId: 'data-assets-header', + endpoint: entity.endpoint, + type: 'Users', + clearAll: false, + }); - await removeOwnersFromList({ - page, - ownerNames: [OWNER1.getUserDisplayName()], - endpoint: entity.endpoint, - dataTestId: 'data-assets-header', - }); + await removeOwnersFromList({ + page, + ownerNames: [OWNER1.getUserDisplayName()], + endpoint: entity.endpoint, + dataTestId: 'data-assets-header', + }); - await removeOwner({ - page, - endpoint: entity.endpoint, - ownerName: OWNER2.getUserDisplayName(), - type: 'Users', - dataTestId: 'data-assets-header', - }); + await removeOwner({ + page, + endpoint: entity.endpoint, + ownerName: OWNER2.getUserDisplayName(), + type: 'Users', + dataTestId: 'data-assets-header', + }); + } await OWNER1.delete(apiContext); await OWNER2.delete(apiContext); @@ -2112,30 +2138,32 @@ Object.entries(entities).forEach(([key, EntityClass]) => { * Tests announcement lifecycle management * @description Tests creating an announcement on an entity, editing it, and deleting it */ - test(`Announcement create, edit & delete`, async ({ page }) => { - test.slow(); + if (entity.type !== 'Metric') { + test(`Announcement create, edit & delete`, async ({ page }) => { + test.slow(); - await entity.announcement(page); - }); + await entity.announcement(page); + }); - /** - * Tests inactive announcement management - * @description Tests creating an inactive announcement and then deleting it - */ - test(`Inactive Announcement create & delete`, async ({ page }) => { - // used slow as test contain page reload which might lead to timeout - test.slow(true); - await entity.inactiveAnnouncement(page); - }); + /** + * Tests inactive announcement management + * @description Tests creating an inactive announcement and then deleting it + */ + test(`Inactive Announcement create & delete`, async ({ page }) => { + // used slow as test contain page reload which might lead to timeout + test.slow(true); + await entity.inactiveAnnouncement(page); + }); - /** - * Tests entity voting functionality - * @description Tests upvoting an entity and downvoting it, verifying vote state changes - */ - test(`UpVote & DownVote entity`, async ({ page }) => { - await entity.upVote(page); - await entity.downVote(page); - }); + /** + * Tests entity voting functionality + * @description Tests upvoting an entity and downvoting it, verifying vote state changes + */ + test(`UpVote & DownVote entity`, async ({ page }) => { + await entity.upVote(page); + await entity.downVote(page); + }); + } /** * Tests entity following functionality @@ -2155,8 +2183,35 @@ Object.entries(entities).forEach(([key, EntityClass]) => { */ test(`Copy entity URL from header`, async ({ page }) => { const pageUrl = page.url(); - const copyButton = page.getByTestId('entity-header-copy-button'); - const clipboardText = await copyAndGetClipboardText(page, copyButton); + + if (entity.type === 'Metric') { + await page.evaluate(() => { + let clipboardText = ''; + + Object.defineProperty(navigator, 'clipboard', { + configurable: true, + value: { + readText: async () => clipboardText, + writeText: async (text: string) => { + clipboardText = text; + }, + }, + }); + }); + + await page.getByRole('button', { exact: true, name: 'Share' }).click(); + + await expect + .poll(() => page.evaluate(() => navigator.clipboard.readText())) + .toBe(pageUrl); + + return; + } + + const clipboardText = await copyAndGetClipboardText( + page, + page.getByTestId('entity-header-copy-button') + ); expect(clipboardText).toBe(pageUrl); }); @@ -2219,9 +2274,18 @@ Object.entries(entities).forEach(([key, EntityClass]) => { await entity.visitEntityPage(dataConsumerPage); - await expect( - dataConsumerPage.locator('[data-testid="edit-description"]') - ).not.toBeVisible(); + if (entity.type === 'Metric') { + await expect( + dataConsumerPage.getByTestId('metric-header-description') + ).toBeVisible(); + await expect( + dataConsumerPage.getByTestId('edit-description') + ).toHaveCount(0); + } else { + await expect( + dataConsumerPage.locator('[data-testid="edit-description"]') + ).not.toBeVisible(); + } }); }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/EntityHeaderBreadcrumb.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/EntityHeaderBreadcrumb.spec.ts index f9cc72bb83e5..a3568c671531 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/EntityHeaderBreadcrumb.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/EntityHeaderBreadcrumb.spec.ts @@ -111,7 +111,10 @@ Object.entries(entities).forEach(([label, EntityClass]) => { test('should render every breadcrumb crumb exactly once', async ({ page, }) => { - await expectBreadcrumbCrumbsUnique(page); + await expectBreadcrumbCrumbsUnique( + page, + label === 'Metric' ? 'metric-breadcrumbs' : undefined + ); }); } ); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts index 42dff396e9c9..e9a426d69f0b 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Glossary.spec.ts @@ -482,11 +482,21 @@ test.describe('Glossary tests', () => { page1.locator('.ant-popover:not(.ant-popover-hidden)') ).toHaveCount(0); - const taskResolve2 = page1.waitForResponse('/api/v1/tasks/*/resolve'); await page1 .getByTestId(`${glossary1.data.terms[1].data.name}-reject-btn`) .click(); - await taskResolve2; + await page1 + .getByTestId('glossary-term-reject-comment') + .getByRole('textbox') + .fill('Rejected by glossary reviewer'); + const taskResolve2 = page1.waitForResponse( + (response) => + response.url().includes('/api/v1/tasks/') && + response.url().endsWith('/resolve') && + response.request().method() === 'POST' + ); + await page1.getByTestId('confirm-reject-glossary-term').click(); + expect((await taskResolve2).ok()).toBe(true); await expect( page1.getByTestId(`${glossary1.data.terms[1].data.name}`) diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VersionPages/GlossaryVersionPage.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VersionPages/GlossaryVersionPage.spec.ts index f3472e65c9cc..8e50989943be 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VersionPages/GlossaryVersionPage.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VersionPages/GlossaryVersionPage.spec.ts @@ -239,11 +239,7 @@ test('GlossaryTerm', async ({ page }) => { .getByTestId(reviewer.getUserDisplayName()) ).toBeVisible(); - const versionPageResponse2 = page.waitForResponse( - `/api/v1/glossaryTerms/${term2.responseData.id}/versions/0.2` - ); await page.click('[data-testid="version-button"]'); - await versionPageResponse2; // Wait for the version dialog to be fully loaded await page.locator('[role="dialog"]').waitFor({ state: 'visible' }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-activity-desktop.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-activity-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..1c00cc4b6e838a412bdeeab2846cfb6bf019733c GIT binary patch literal 96063 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 z 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 VW5c(j7L$+!xI23zYn;Mv{2O9QcU}Mh literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-approval-desktop.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-approval-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..426f7db3a377059b05cd993038e47c257d188b7b GIT binary patch literal 114592 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


!f;5ESwERI_jyZFo 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%0DB91KGp!cmaRmLo%(6(`~S(C6aF8?`6O3 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 z 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 +94sr>Ur0gYNo<^e-%&54e!p( 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 literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-list-desktop.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-list-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..516fd50d1cab6e67fcb4b747a802de6f732c256a GIT binary patch literal 98957 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%0D6H9tJ7)9YKTz1qbM8BVX8|$Cp0#dkT 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�GG|&jBYF( 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 literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-list-narrow.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-list-narrow.png new file mode 100644 index 0000000000000000000000000000000000000000..201acef789b61903b9f60ff8284b7978a51bab44 GIT binary patch literal 60859 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 literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-observability-desktop.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-observability-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..ef7553d08b4730dc0b438d242e74a4321a2b3fef GIT binary patch literal 123998 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

    Bo&-cDqimU5_)v@nkrF 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 literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-observability-narrow.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-observability-narrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ca01d3f96f0aa657e83bc6a33ac9ae617b3ca000 GIT binary patch literal 64183 zcmcG$Ra6{L_$D0Of?I;i;O_1^xVwfR!QEXG2sS`)C%C&?aCdiicNunm-*^6dyEnTx zb>{Tc>FMh3s(S35Un)v6sK^A!pFVv;1)o+^0_%pMa8L z8lD+vnFylTK>R_P&<&qUMNv!*(VE8%pGQVZ5ueNZJH}02r4IE;$X6Wu*X>zv+T7*PgX_z#nD_df3n2DZ#Td%=tObb&DR4@nYe$=+JGzA*_?%v-t!}X`mIZuEqIRZ{?F(}*3 zUsztkP*n^n^Cv-I|F^?Ew)uG+`inj`U8>L0Y-=LjAh-m)=wXu8&+RUiEnyP61S}9GIXS~~BVj!u~K~7uag_?~KkA|`Y@WLT*93_i8%MpJnBGD34g0<$b%`y=C z9rhgcN z&aCKY_=GmO8yq6Jn6HMqL_8V0gpz$c2-IGjgB8*PIxHl+VkpBa?N|5oNT<_?-NPNq z;Ts_ir%xiSTwss05fXK}GQgEGb$7BBT>bbOHHS-vuK2IG_%~Dy;K@j`A`AlywjN1M zNFxd$6@Yi)#dTa@VyiiQskW&xk)M7=sQOeyAEi9cd-WQw&n)&GiQf>d6JOOv9`d6~ zrTb$C7RVmU^{9QXyb>te_p=EnF@U7%Wmo<*U~O2tAnJcz`G|s_!6*5803cAY`8&W5 zGhZDm?hBo-NMxzn`G#&qU#YHqU z6!U`Rd`VGazxLA%#I-_iIGbZUNmnztE2=VqTyI|_;4s6-La?PCWAMyzvN^*MJeGZYt;#PqE{yl#gcvy@(G*wh&$f<*y{^cIYF}=e;Mfg>o8Lklm-?-N1_jlR`IzMQkn~4QTR3|E$8@E8yl^DEYuI_ zs6*sL1eo?)I=XsyC(8{<9xlOiL}6iJNi?n`gs1X zal^H~j+&-qgnMqmo6)}vi};h-hK&bhO~T+HF@Yw#mt$cU=cp?_P^~BI!muY(6o!*4F|;zcN@2|(^jUfuw0}xWWII2v zL7vRxzlKQr_IL%9lIkBTx3$_hKxIfwOhi;u)WXV4m&jvF9kW?<;9FX4;dW=BE1x?q zWWewIxFYA~j`Eh_%W zXYn?-z@%TU(i*vKdH;%X zdSSu${lKs6kI^pgzdz+mS6xh}kP$WslWLbAtZYS~pViiK9wxIGw7NgVffJ~IGdC~} zg>QZ&gVF{9R;T{<)DK_5I09F5+JFdGo~b)?(h9kDgqvD75K5Pls` z=LpdQ@8MVbOo|lzaXBA2-{@#v?|2*%AuF!2kx)zLb2?#^yp}u0%x<*PV>aaUm?aG$ zdGeu&$19pJg8jfO$I5=pwqN(3>h3|qd$O@BXS82yEh--BP%fio$Zm6VJKFNcT|N(q zP_C$81a(sXL#-`8dc(oULE4qZ!%y~ARPuVg_;>a^+GJ<6yP!ke`F>Ilvf5N602{ON zM(JLQ8u*qt=iW=5M`*dkngpUaK7uK&zuI%Y#u zt$$btd#IEO@=Z5)>9_gHJ7mXs1BqHq*^j?Rz$M^c#b91g9P0|=8fg=T_zha^nRn+IPtH081 zy_8n!U_IMUcN@cCHZn6sq8g~+c(MLIA|PTEa(FJTgIP!trY>Cl*i%W zGo3sZqN0*}Wu3Yg8sd}OxKMhB*K4OkHc7!tkgv%17Z3YQ*^YA_&$EFBdAKUapLWU_ zf`oapbE_nN5h1Kjw@&*vch3xnbBzwGYR1Zk^QRvEP-6B;91db0U|~m2erhzvDl?i% zVm^2H3^5;{)%OpQF301S8i@c+!68kt-hY&_nY^!ujnOaAJqz{qzxhzKwdA>p-xyno zGCvj@gY2VX4pw74Qd>$}!V8^C8us7LIeL$~?}ZH!mb@Cduo>}xYXZM|d9~&S3E$5w z%#`OgYb8NZs}-Tyk;|>rNTiRIm(xrdMK(OgiMN=ynOXnHzv3#Zbp?o zUbm(>C@EnC^iL-;SLkSmHUq8_HPB??dN=zDsu;Ddmv6NNh0;WST0igb#Ua3IZw;Kk z7L*>(l&n|h!r(I-CS+zxBy}q~P2afvi$E(L_)XZfiiV2>+THN%X+CD_tCT{h3(@y8 z7E#z62!}mM)N6E_Nvo+%t(a{xP9gFj_(l2(;F6KHu#oCqZ3upQ^K}$|JX?bvUD4As z&mB?cJ3kQg?jvE!1;p}bdSk^@%(2Xm>AdL`(R=CuF4t|V zOC#so(gLLv{qH^}GsD=ywn@zV%-9mPxkCEginGz_bxQJtyBm->%%ZBP36~jcll~K? z7(^8Pa5~4QfM+vyl>0B@Gk_~7sFQ>UZS6!+@%L!S!|-C4esYW?J@3+LxQuU|H(7W^ zd3i=cg8qn82$A5XE<85U=f5|PNI`bo>3-lHF3)Qe<4*s@N=11Jy6x>X>0Ym>D0#9q zW=0WlLGRYqEq~An6fB}YpAEOIIa}20!|_H3!=q0L3Gl^XAi5R=>ttiv{OWt?f*|gY z74CAKZ_$=@kZ;jyb^OQO;D-qn(pepR$KU@(7R@;voX7|MkZvBBp;kB{hR1LUshULTv7(+_DBU`J<_0p zI&9~qF{u6FSb<-p#^B@^FpNC)_4QASf(m4mvqBad9WOrn505mY_ar6gfJB{`joZvk z?U923QgHSc=)G4;sApb^-$c9XCE6AWR*sfCusx{Z_&aVrZri=t?KkaY>7}HxAKoHB z$bMst$&Esc;Ef|v!g!l+CEQ*mW%*@SI-eZWIK2E<6e|yWoA|Lel;q_DZqE8su|FDd zJWu{=PueF}ttX0t0+B7M%95y14qeZ=iltnXb1y7?#dpeEqMGdW7_<<(K%dW68CYq* zi*{vIfA(sEM{5lJp=jJCYNr?-B*=2Mvrl-w(nuTN;E4Z5L$fda$&|Z&&x ztqaKX_w_)3+*9#4YELp(i+Xa;#RZAP-wQl8<9SE8SHPkOG&;a6@PCmj=nbq4`qB99 zzR(4~GPtYpbyD%oXp7;`L|tQ}PKW*IP>niFa4-ZjB00IzqNBwAj*K*~ZMNj%W`;6K zP1Oxu^h)uTFa2rlHDG7Wv$6b4LTkMy?r>2!P=M9m{(8T4U;-BIiCy(*Lyc$tas0LJ zkV&`Ql17h@qh$PD(82-H{En#;;g8aDeLesG^AAA6}H`wl45CV35vAHEOvk1iG# z7N8Nbt4K+GrC{N4*c_c0HslP@dbH2fYdm+qx-=BIUoXA-+LV`<2k9J3C^S~#^l$k# z`QN>AQb^30VYM^lyum%rZ*$KT=~@i5LnDb8aftGY@(64oe{LYbJBZ$4uG>I2rC7#wheja=QLzui540g9+e+|X@OMe&8XfJBfsO8xdT2$LePbA zt24~bDSi7j5?Q02tu3#o=w)X|8}^>Syam;@LHQ+L?MzJphff}5u(R}JW1am~wz0Gl z_32DkO>QS2VNCPvet^MAbp+|_o;wm5m-wrDg}%3sl(e*}!}b)Jg3f~lw4!TuT?j3i z*mo=^A3hD-_t%F&{O=1FLY}Z)N6f^l@0?v)=<(8B1+_8y7W52!F%5oVva3e$egkQA zWiwH_8H3s&hit`fxK7!RbaV%A+8`^}Ad*$CB^IEns_KyyKz3d&f=MPWx3lB#HLpCA z6#qL&PM^!PZfMKRt;#uqjes7yApT!ACT`T%f1--+TL`%qS0!&v$}{ z+x@OR{L%+*meBV66O)uaI1+23cM4jGrt)zoxq9V*SLqW{H5b@H@kli06*iH9wsiL* za&LO;t+3&DOGZGX+Gr?jz)+V5H4|T!uJswfM|+tdt&Tl#RLg*IU!I;&`NPI z6$gYYI;At~$QY`VJSd+ayYfeC{%$f@hW5AFR}f>Qq0u%_%ac_Bm4;a#C&Ttda7@nhqOrPEym>=kJw z1E7Gad5H9;bdrb?c9G<$$`T7t<_-FVzOoMk4d|T&9RsrIuXx|FvL#J~qZCgiAg^Rx*l2 zj&u{G8?~tGF`v@VR#E9DlS2K3m5@HDrmbH5WH4gFfXg1))1H)E#30K32K!S@4=hU{{tF6_?Xi?V!$qE;SUb(sHW z;X?LB!(eP1h=g#{l`@x%sRH_r>9`{&$LqM`5)+qg;;-Y)NtsfE_%Yq32oGVsDLmExYb}liAkAtZm*Sz ziF3cO2kNhGwvvkq3+>)FFGBkYR4F6w&KANn&=LWV6HjTE8%Pz%D%h@tE3O_nJC|uQ zI=fcm8~iOST&c7x3-0Y@&~~7vrfz9#85xylX1H#H7T%eYQ6iq~&Ek zBWC&g6q__`F;H8n9cnRo%Vj~nm&D=W8$V}T~v@rc9a1&^ff4(ompxk$02 zp{|C2Gbgzw9;(DrvcIn;g;54UpMv_4L=Xa2T%G0U?;CUFLypx41O$L|PHet+dx>-P z2U&_db~-&Quy9{_ZGDxL>{q!rY_u2wNz_7=E<-EG`cy0gf$Ta0A|DIEA78W`>-A?a+$;DO_OglRXN|_yNm5Nd3Q5JTa?cT?|n-HK$ zNi*TZThOUGM*r}QEamzOX`ST3Xbap;?s^n*ny|FQ>c^NmR{w&3>cP1H6+2+#URUv{*)QFIK15 z^nivE-RyqbXjxZya$+s10B~GmHfk}q{x(JWu5RF!Mwax!#((5_rs(lp0J+O`~OC5aYrtdm3*; ze9viWh7Nu4`ROZtS^O0>Qxf(TX{G{V%Xc!g0~ z&&mwY(Mw^VqwB5cAL)I2SdXBlmPUJMguu5@e&y^gVXu>584eFk+$0a-Y-WQ_|J{R* z-(!p}9O_h57eRqxZZBv1kckB$<0J-50{S-Ahj}A#kO$eCkU;rlKjqIlRop8fqtt^r zd+h4xxBg(KF9!4%>$xZNn9OK<1Lw13pqf!i=%DPI>p$H+m+jI_cKM&0S(!LqUH$s` zlNO>ms963x_?SL+jzM#u({ilFfDv+jI~&!$yt{KnrS~0(tCjsHCnqm2;&#y6JpE6g z-a-AkV#~eBs)rH9L^2uY33@X=zIH=%}%wUm~NE;21?b@7{*4T^wEPx2ztYhDX&8nbqCC zecPQhYR^hdwKF$Y>gaHOSJLx_4;AUQ6LfsSsbV`5`XKUpc~g|IlvxZ{T697xBIOeU-tIyKg={GvjEpb_M=dG^gL})$YAJ+iA$~7 zcuau!7gJKL0J9S{>IphvwZTrYuSl^B4*?A*0U|?3?DBzu@yoU8c?+`fQTfO+BDuK2 ztDKJxIJ-eXbay!WW@`TeP6&vtB+hxucMzpahQHE}cu~&kAmR8HXG2NT>n3&H1a>fP zmPrihKyA0Xm@e>He0a+g;Htjd2zy;<^O`mEK^K#+=j3X0wYD*}C@m>L+sC*;NBad? z<@GiE6j4!o4#Ws24BNBP(-9WT`Np5<67fRl>FDYBmvobj`6v@k8G>qV&+VkCX>l6L z^YiV@?2u5x!{L40?WqL`ug;zsvPcxcOG8`=-md4(Cc|ljO_v@QQ{2Mj$H_JS24e`2 z_hYj=Ki!62VWEkSj;g5{%v8unFs*(B`-D_P&qKJME+bx_UpHeOefMf^$SWV0W6l|4 z@$oGfJHW*sg@dE6a=m%A)%@124FBIMjk0m&t6y8OnYMKtY>CBL|g#g|9d9kdAXYY*jsjhmqMws*ceamdB;oq zNe^X=B;G}yi%A9~QC#m9hXO*+Qj@WMUn}lWfvO~(if?|B^i)j`e1{H8#7jx}g6v;h zGu_lwSh!{uI*P7@|3!eU1_=X!?i>62n+S^Z=E%b2_&B~T3GH;K(?3&kZswW{3k}#I zqv?L9pl2EkXnvDXmC?86+SNxqcvydC#_xBh>(Sn;^+2<$7(ZWO)U!nt0C?{h#YBqR zZs%lrj=0^VIH#n9yuO{$k;7`Sa6e}KwZ}Ar&8_!6LYaWel^dsdHn3-@Oa{LzFlV=D z0v``27**5Yjq=|=2U9B@z#B1pG0Q#PS$U=p8V2T7Q|$qrgS$Jo7(j{u1S_JJmJv#l zmqEmH)l&jSD|g-iXayakDKLXH^9dfJ(`g3Uy+1t)Ft)L zV&hgXoNrwDj9axqzhLDa)v=LSxet)d$2>+66>vR!#Iu9)pXt2(%|u1Ft12s*16+g* z4NDzoUvRf(pM9TP?_cbmr2jBJRj3a(?k6V0O?>%6hfX3y$eF|Asd;;-fNg+sFv-$2 z5&TC-H%(t(cST1xxM|#Y)PWoqgzqXY@5YD``f*#xT@~>hM-ThD?hE6;&#Z*jbSdQQ zi;+oqOm(qsh!zSB%dl$-Z@SM=t^_6Xw{w?}b z2#=YavsDeD!J6`iYPqNS9;8TeYPuub=qD1U=4m~Plp}txbZG=9ife{dMqRU2%IN+a z8v$2vxw*aF!757XCMvAFxuGM_pwc_ zAzZ=N62QzUtO|0o?)g%K!%m`Z{(#~^msZv4+b~Pu9LAQ6V?cR?a>#U+u?pgHy-)xt zR5~>D*cLUXyIYIvy}K&r;{g(or@AQ3hdY=1?#}V?9tHW0Xl2I-NmevJTq&-1baLXJ@=@5$~3 zfJma8T4VCjV-}|vV#OI6!NfS$>T0cBO5L2XbwvUZe|CDv*a*4bk(e$Qiv(zoSrROW zh204_5q%YYem^~RnOD?kpOVB`X@O3yjl2MMFyG_iAq~rPu5|a3tFg zIKH{3wy!Lpo|>P};xL=(FKYrnKf-E4^V}ktMX2^9Zil>HJRcs-Xr`O!iWz|+3*A$u zM0jTL}ZPq5tBWzdAcRW7Im?n<)1|G4Besfdg%x#-16jg0b)|2T^U3 z|6svI;>sT~8Na`txalJ*t3kvfV5*XtG#a1R!A=W`wwIli;9(P;3gV%bl^37u`3(4K zdKP1eS#x7%75gTz?SUu|-C6Q;-l zfx{SSK}209d~11>U45e8(4faOn9F^0z{$lrtVHxWT{tyPNG1Y-0jfQpIOYYL!Q{AP zU&Knka{$O_Xn5%P@szfdU+pA11-Y1r3&dCt;8a_dnmuKF1h}{~dq(m``r(v@4!2l& z$xXyZe#JP8+gHY^77Rz_|4SA&Ibw@8)YXPwt2CdGNOX@G)t@8Ne z5B3*gan|ruNMfNdxi$A?$rzHYvJ#+rE-vyeX+ZEvSzdmHA_i;;f^0r^AQMZ%&BeP6 zg)jyc7dJb7z}_cVv6Igb5=>}QhG#^A02Vqq#UEmsTUZzwA7#+w5THT8l77p$evR$q zv0o?Vu>SHNQ6u|Hz6PN#kEDV-x7!I>S!f?(Bh62+R8&;{;pzX#AvSkhKoAi(EY9w3 z%cSKyyM<)(1o6+OEzu@KHNyClVvv{^IjQjTz(Bvc!|ly&U2W}izO<+rC)b=9i0rU5 zr+90vd%CTqs95GU02x9+=cKKjX9}$0AY-(qTtfOJhVc~|^7;SV0ulRdvErp_BW2MN zaFXJzrG6=K;{IyHa+)H)%btAxN#;g$Mz5RpWU!Mho#Fbc6yCx&*k86I%HSbpTHpsccLV?*L-~ioR~p!Cz_)TGMnLK;;rdV;z2 zLmYGi6ekgj^G1=I;UV*f1?xc$hb6N;CyFoe@{p?;iveHY`|1cadSq`k1M8TPs*XY( z5Y-k%A&2)CIdOh5=2Q;ZDeQZF^gOyaeknnYgow`BZNA4Ni zUphii!C%?h)Pfs;9~@MP92^7~Bv)-D{>c(Mq0;mh#?1ZySnUbLjqCN?gA4qRVwvwy zUVQdu^gB`(=7#`3#RKJ5ltl$2qt5VFJxAH4#VWd$6+Jw>1A@(>Xl6RP=d0n5^EUM5 zRRJLhaAUX!DD+f2Xbbsi-=^Vh)>r8k(AasdYn;D^WAI?}vH1mxiYL zmWtoP`}=7Gy&fWU`xu$&ERw5}l9EcOaq*L@m(Q+#vRu*4-Nj9TEhmlt>4RbI#8>I+ zs~L?G)W3Wlct!VjJX_}DbJ*}_<>APkJvNX1$?u-4h&BJDc8HD4#W|PV;Ymz_33sR> z1s4%fMW6!e#Qa0YPyBrDVbp7_bjZF)EPMkGqM4aVxNyuKvTSt!1w%MZdAThZ zCpIEB)9Y@pC9AS>GD7*%SGe)VJTx){v#;hFGFVsNLKe1%lMN{`G5_-cJI9V5F8A#j zH$Ok29|RxE zbq>zCF33esf zi;ErY-Oo^NpvLZK*5q@PR#BmOpccG8TF^ss<}qRX=d%vOsOkCnnz}l8{Tw%WmS*T4 z>8l%CVs& zgA?cX1tFGL>Vn?y-@hAmy4!qYotroX-n02Fd@ChN+dIW?{+PP9OV?I+u`4S48{&Aj z*`}CeX*_1!{_^f)%rZ$WzN*_Z00VJ}WKc;tz2AO^-CFeZ^@;euh|ggr*{ShGv-k*` zwrIyrX#F{;7W}ay$ooMJF(ykmX@L!d)lS{cP{3dx&vdQveJhG=;PGP7;6&F$8<+ju z()?eu*M&UhAFOyQ4R%P$evY!9R-UlU&XPnB$QW!X<0Wd+w!HFYx#Ms(VYR8B5*G(+ zlyu?|fbhGjIaD$Zkb7QkvI_+V2lrG~T-+_C8l-7p0LFYT0`7BnGEVthi>XTxD{usB zzZJ4K>@G#-WHroAvPP-Cc;B^_72n=u_{+mVj?oKzrg@RUKkmX%UglG)xjEX zKj}9-3tmKlrR#xQTkE|r6zq-;hnw|b?B)l-M@LJA7nNo*sG1sTuw6*VJ>PS%R!K#k zB??LLx?`qhXV2&JQJMh|hg?zt5>Yujw~NW*CB*pR`|y@DHfF2J1&Qd8<2@X#Bk08Z ziheyhy_}v?)DQ^6(~65ERqZE?)gV1;)`ZGzIs(WuP{KO<9f^k6cJ?KwL{X40s+*TSWHx{j46q(K7VakbNo6h}{2&&t}Fw9;nh z!256`KTLj6oE{lk6N6-<=>svenA>g{cs?bv#nG@mCFU2_XgS=g`*?7IK%3;xXDAKAbFUnE&9MnS!t>7jCK3u{m_n+V()<`W8Z zAItFQ=;Zh){^xP=t1lU1)r=#ti@}eaUXZi^XkY$7RMzSs<8J~@jFX2AtkTpQRoS*0 z4;SWh23m78g!1FzS^VvlFkjUzRXHl+ajeIGp~DrVK>QIk?^(bPS*OGM=&Qlr+ZQrx z8w+*(bQMR2T$$>n%Af*KJ-rvw)sM)?n6Rn)0;K%aMtd=9^oG`JH<-i%2ibCH#RUtR z?@p9`7Ay72Weu{LDrJy;j2GOUoyPk@M<6|&H|r3}KR zU^q`g4C5VZBQ7t9a2k=51mM&5vR}!u*c{;ex|G=FIFFA?1shLP59-VR$ZFTd{1{e! zaQUDHzNgb(_-nY%CsQrqnmmbk#ftmSIs9M=Fo#zX4<@4!V<=H`wJYxSm^JBcCvKvLzp>vcmnw3Ru?h_% zK18)6yMhwSE@?_jBiNOWwVGZFnbYg`2$@U&6ItKUI5$^c!g0{yeXCTB;Yw-*fm~pl z%OFz;1ZG3t!J*=q$#ZNBjJ;D*S{>($-lU{a{K(SDZO4am5ghzvGM%MLMFxrlNHj&& zThdeg$HCsgwdH;}p{yndvd3O@Ao#vR|Bn6*e}8FaZvMmkM~&qsln$5QN($P_~ zz$59!M%%~zs>f`Rf|^=sMa<;87lCAJXqeP*5|O`iZkmyGhs^6;A4f;Iek9|4DQOjG zj@Kji=JE&AQVI=s5aM$)nXWLs)L@#vurX=e9=^XVfiTY|L@|?CaCbL0uI~Y$rn*0w zcH6t^dAk9>H{U+cG0<^2x&~@TpxI4iwfP=yglO9EFd6acYs;jQiBKNf+;p3oLDt_V zD((d>#Wg~Gos^zvPC>z&T^f;6K}rsrz7*i2gK=YHE#Myh$~0RzV7|tWFxLhW?*v+- zlaJvR)acAwOzfUw4ozk22RO{vwwPq%vurB7+W8YWROYs~znL>EWb^w6 z&be**OD81cPmKK?T@01O$}c`ziC&$nwV_N7?4Fc72-;GWzdR_2p`Ze;+%JllkX9Jg z6bDb+6v3m_StuAaIh}R}fHQe4;l(6f-VZXH+Lxz3F)@u3CQp93u^`1Na4W;pX3jWT zuyGW2NXr>i&JM{RjCBt=6jx*|$uqdbI<*_VkyVxb^>rlN<0t$NS#4lEq8A%+J74K0KH`;2dPhgOWz!5?Z)kwzCo?k%zM!B? zYQB~KNla|_y~m6BauQ;xgCbT+3rW0 z9G6p+593pb`;7WS7F1zrqB*xue4# zg`n%qit(d(2{4~ysJG8$j~N)<^=Jrbt{nvNGgjJsR`-rwNCkbxE1;RSv|(^x{YF1X z1bs)c(f{QAz;0@(D|EY<>pY7P-*I>zxp&y;V9`XwjN6yT7u6~Q-G|-!fsNu~A<0BF zkcNtiwc(YtMe~^gaTR z6f1JpJR}?Iu+*-|ngYkPTy5c%y|Mo66ZoDj;MRPWC05jpz@m@l^_zIrf3wwZaT6h? zJLs0dljrfxW>M>FHoP1`M-wEuYGGl0GrKvfpN&4MT>_P=-r28IZ71Xv(@@&tr_BY+kEe(OOPEONCds*m>$m- zQq{F0I$<8?&v27TRw?#VVFkBPoW(ZT~xISR|^wBe|knxhKH-~v#~jKDWz&Yy=$3%|Gt!KNT{fI4csF$nlLI(rz>2d4zeyc`~rD3 zzRhU&j&FRoU90!oG+qUUP13_YX;nUF8l(Qsk2zoM)%ANi`ubGCVZpN3q-a1^mvK{Pv{TV9E*a|$~-a9JTwb9(~)?G)BZ=QyU_ zalf0Z-T&OVc~3*b|Mzvh_d9hb2`b5w$7o^0oE|Gf42ejGYd^pB{0y$mYJ<(+u~RE} z{F8{-P7S`Fy~_y^#pW1k*Spg0$HJd%k$;}~zU?Uke>dMVKy#v3T3@9<;SK&RTReQ@ zjy4X;wt=a+y0P*;9zo50g~CR zdpy$RGfy_}k2Emg5?9JIMNDK}+i` zQ-gtD4iF3ctO<;U8J|)uwK50)h5mwA7r2#dXh8AZolg<<9*8~ghv~y?R`2Hv(w{&N zmrJmj_1B%{0Q*;B`>r{Cg6N0QrTD7~!~OocZp!A5EvIawbyEo9i0+C|yS1{h`C-WG zq5;$eveGl!zav8rqMhqDIt$%D?EJOy1tO!w?nRk2F%yfS$t~ID3IugK%67LoR=$%= z&8*6+xI&iC9N00QUKB$rYU-pBGWA5EvN(!QmqB{)bvBRL0av?^j^4@4X|Le-BDD^q z{%<{NsgMYoy~FqZud~!beqhkaI4nCc30TTP07IhHSQBU}UQ0{*X&aL;m}4dMwiz!JiXD7P{dZ4!bOuS(U_vB&Pn?W*6THvJN|X zJzXPkM63+rom6jIXUw4ZC?u#n!m1fU)D1fp(`sZ)xy37+gZ{2R{ z7x%e5GoYh=3)_z%QdYPW!g%AnX9t%~fvjLep)y}C*l<)574B?AJ(e0kkV>$dZs}Bi z3ltSF)CWeE3NmBlL4p}JddCj@q;#;5wPCwmrM_Z zU#Q=tgu9F$nzw_EZp>os$)!}nVOGSd3A&)Ki z2Me)j31NpbHYS!YMa2$JE5Y9tDx|mXPbl^rn}eOM``+R^ix3zF@wLGVnXha$P8gIa z!d}63>LIo1GLp^#Jb2K$pcA_aYTwMg0sNf;c}|=b(}NQA8V=FY44)DVs@h{wV2$p+!!V;K7* z$6VcV%nvZN9DG&j$g>!pm8D1y?)LaeACuR;*k^)RQwMtqdmm|?Tp-Q7#)9m4CUD$ zLzvjy{!KP`^-BTtN|TM>;f6%7dPdozJsL5)sD?Rf{L^S~P5KQR`L1AHX#U~_- z5lIN_kCv-AU-?VfF3Kq(-rJ3b_8B>RP9O;G7H%~RYc@KfslkT znTrgQgaYc!^S(oy-=MLtkaKlYCab?f)rH|xkD2VAJQ?r>`oW^T`b^QlK(HiPqieVD z@A1Wf_hnB4+GaLuuY>T}}W44r?7Gds|j2=QcymNAM#@-WnxtuMmK= z^fdUv?`F+%ckD==(BLx}+wPps%>?Xs#7DGV>wFZgKE&*=5D<|jfXFj7Q<;I8&>}D= z#}UWsG!I7{fTZMaA$MLHuD>%Y6sb->5+R~C24#dk<+i)RHJoDJNRQ-8iOlXTSl@hT zBvZhzKw~GiCl2sP;YsNKcGeFG*~@FvnkUYa7EJrJIb2@UI5}zL;aIKLKF6GQ#eNk! zEAn=I8S96H_2*Qee$u|&pY{igFj7&u%`F)}bEA+By-uWdC4SHn>6EXxY0>7OKn!Co z&3paBpDu?i$=<9D)zugv@3*G6xtT#_|5cB(uN?lRZI-K5!ym`NRug6!qbm{vpDo!;+Sj!d$L z5cnqBAxQw5>z?lEaH3@GD(O~%LqbLAa(b<_tfS`cZPlgl?ao=M@x%Vmx;!LZs*&G> z`5*}~=DQD0@9EApdyZ8X9p7B6DsR4o@#gg2!>~^Mw>_595GW!_&}U^irZ;qHJX>DU zRy5eO!3=?;%MV@a=p@2GC8cM(2@0_!h#rOefecHTb|TI2-v|V^(q95IrI-SbHR6qv zgTOqb=Pr)4p{vjP5M8eBfce+Y-xNDAB#*_I5>E~Rshqo)FcBq}D8WY|5wW8a6Xf?; zboW|WZ0C#fr`+dj?>vmW?`J(uWB|^yDnA7BWIneW&)~PuD!z!Hl|SsDaIxSS%;r}% zr8JG2ynnPc?x3bNd-k09Jd&#C4+i^9=Rca*Fvvsd-l|ic4F8Y;yUt_X-W0oEo_sz` z<#a{u)0$4!TFiW~v3HfT-;7XFa9u1E)ipHYaynsk^wMq-MDo8(b%{$XH`=X&tYH8Q z2%o=le}idiit^1)dk23f&)Gr&$mjKj!dLy7!cHoVzMtc0s_~z^VW%0MTzhDadsbg8FSFlzM7KaN9CnwR z2ypl27v(?H1Bh94{f04!lnB)l-e2y@hqStW6A$wgcC!bwK7Y7hbbM^F9mUrr_;H`B4245@|?13*7`-R}%T zGzvAC>#Lx?*}Ia2i;dQ~R?R52^gy8V`Ai90es~gUlK}rpHg9XdbntRg2@4eDvbP5N z$*PJpYryu9Iu%Q05@?aAE~f40uHAv(&ED4<=FTh-cVdwxd%4w%c&Wni36f9_=6HJo z-!FG5Qr+Vc*tBL&NpPErw1#DJIm%i7g155 zZyi~pObh}7OiYxNl!qS}N6vj*Xow5<5$q4jh!Z;RQlqgEShr3gJO1g1`4nX@VM3ec z>V;vOYju77(C{!4YP2U9;-23rVKAm0hUS3P<{KCmdfwNMUlz0~WNq5Ll-I>#Gl>ia%$ z_%36N7Li|C`pv?6$I4+b2U;ld6hI4vl)Gbm*^vG}6uO5Fq5c0||97i~%sq^{!`g+V zMQ>^z2ZB~x%`L-%Gt4s)Rp+E8KsA43V~6-4__VZ)-&rH&ASv2B%Z6k{D^7w;C2cJ= z&`rAz#g^j@rR)oFo|UBf93`^%8bfNOoV7qsX}N2hHX27JtNKrWkF-+a3?GVw9KgK2 zXb8j$->%BbgEm;j8f($1t6sKMQKOE6TPY~XRZU2cbdlrz;ep5yedL}ueR}ruG6N(I zx{jmOQ!Y~ZA1&a^%v~F18lw^Ae+I|J96x7Tsa!=@X!le|mtGn!!RNMYhS%eazSj$)0uI399GzD>+d@tOjLSDI- zjQx}*ZAMYm1ME`%J~=yh<<1nYs!>p0AbWzmB&AoC3EgF~^Sa>`D?C3F-oYt`Y#TW$Ahzg?p9DsEw2dPjs)ac`6=Oml|bSB8a zFt{?3_h#+L*iVI}RB4FB3o9-g{vKAzKu3S4D-dHiHdDQ)q?&y7L}92q?{d$UR-KYL znZ|}nQ>D$-K)nw=ANh5SF)Ok&^~Y*wxY16uXf{6nwf+2%)@mi)@z(^oywzU?MwEE7 z=Ja#Xkc)td2qB$RnjFgDHIK=x;7S;VObk6%4{s%V5>0W<{}LP+VcJ!G;FZU!U%xO7 zJ|M}daI^~qf#rw84M=eXgdXFX?>Cg;nOm4AuduRRpF*@Yw9CyO*4FKZmlBF=29Sb= ztTxYch>>}GoT?(DtX$NhU6&iu%wfP{*n$bR*Xzny@qLZ)bGk;7i0jHWZeJ$nY_ev|HV#cYJS=s5|l8tA2G(o{JMYJvp6xZGFpeUt&~7~fR8a(q^<3? zA(?c@V#veBZo6LEa`k=yk0m9Mdu=ptqPHRsRtzrCNk+Pr})X zEHfRr2Zwnt{olVxlnQh=biBtlRDUXU`q);VLiGPdR`I`Rd&{UQ!}je{x}>|iOQpLz zq(K_#MpC*F1*D`q1UB8>Al=;!f^HEeqF^D9mqqJW*2$8#z=#aS$1 z!wu{?b;txO(KVB^j8tNbL|KaoTcgVbs=;W!;JUx z@w9T?XYQo1Y6qc_xmjAKHGIZRu&|-7Cku&8DLj^`9+wv4%z7VE`}^pBJdRX(9bQiM z^sMHkJfwM$Zjq6%PKVYws*(Vt{BD2%$xB@9*K0QwjR} zXwA%=l(=Dh+uZG29oL!>%G&%cGgBa+T*eEiZU*Fc|B5h4xHpQV{mQ*6!YMeu4`kZy zLn7}Zw<`(1^baL_k(i$qpy$86juUgr{fhVv<>Gc&n3!%y5-!DqNH;y}(&k)L`E7*L zLe`6cM45R$EgZRSMXBw`DsU?2azl}G9PPND@T1Y+PDooJu~dJM%0e&K)WGM)EXWnU zc|Cx|Am{dFrZzHiy7@e4mGC@ufJ)OmI^S(<;$PgcXN?tYx|HOg=G-gx+J_mI=^ zNkLo$&pf~Jxqi0M96iZszWT$6>x;JZXv;g7YGYiDaR1M16D1L?_t9UqLmhHY*XTqT zQ)5$Oa8F9Cx7A`u)b(T1_8!DnR}4QNA$`wCkTyedUHOAn%rq25+$5Uazc{EWCPtR4 zAa0Nkk9zd*_fMZi&CQFq&uxq!SnaHgDG7@AP*EPk(TejNO|;Jf#DQXDlqA=yzesO0 zMoL+_qfRAz^fWbbRcJq>pk7|1!15sH%Es|I1Px4D(b0tgcU|S{hY*J3!Y?gRb-OY~ z{zF?Z5)ilHJz$`O#zsn4SFIXEfxC1iI;L#Y&zM~Av1 zyI{~F;bbuecTX=F>*e~|z#wVQU83>C($L3D)q-h0f2(U~oKaCJ;3?UI4EbaJYPNOv zHVRuuIrhre38ftzoUS@W&zB+wW~Bxb7js|iiM*>rBLeO z#TK3~pIq%)ZK;1NBssdD4n^^TDRH}A5*mfvPwv2M4%kdeDhF!^JVM-Qjow0^+x_*S zWtT~x6Rvvm2cxt4Q0*F^JntDJZfVwU`J`=Rl%#C#)mtT<$l(`rfCDWOOyvX#H^ zp@VHm5o(%|hZ{B$GBPe4W$B2$hNA_qIze9z%kSVuD2C6t?;;DS1BP$HgOqHdu&{e| zOSW`A%dh3-XbCA;btb2o23-r733xE?hYr1G!VX*7e9@OIZEd;C`??3Ge_v*OWbV+! zrDSCldV5e3oPpZgEiOR~RPB_Mh?75asVro5U^Tzo^J>m!3FQy?D`C*g3p&9ENH?M~Rwi1+`ZejGv5ne(vCAjXD9^6N%@vwQE5F(|7L zV$S6vfXe*4GJbhP0G;w>R!cRFz{`CM@vlifJw%V6ps_*8^CdYY9%9W*6)>u}oeA{; zx-6eRC=)!J1uT{(=XTdtn7Es>+{D87gzs5J#hExbO2P*@x!2f=4wLoC{y>m6k40C|}`toVs2{S;}c{ zaQZC{H?`R#C~MB~gcik&FICAe!DIB5h4TGigPTw?WcRB82stly@GKU(;kY7)22U&5ISBG4E$!W^`=XPO*`XZWu$=2 zTklOHDuwxpgEBH1_&dyLr9jK9Mh`ZS8=ir8fIM&$7&r2pGk7hR$xH^`T;{ebDACsx zaUF1Q=y&-i?cb|cQC7pstFacuK;b}2W}l&aKkxj;XJBN6$i6UsJTV2kmGpNvCNo|z z^!@lN+^L2n8^FS;%g(EyNtpilbJLT_kHFJS>bK!f55p87v&4 z-s{WTp3f%R%0S`Qdp*y~ax#EWjU&Dl{9VuB)$5;Bw^X*jMH?<$o2#qiuKH;(;lHS3 z$W5JMNx`JHvfY?OG;>VY!|yy$cJz(jA6{oemVlmcs=!bVOYLW++?u5_CKsuwmq7}e zXtV%nK-^nZkFJAPHt_%Pb{T8S!HSt7g3tfg$CUVd^sL9VHt(!4;s^x=^_marH;HS8 zu%N{Xw3AZkU{yg^jN~k+y zW>tOfQ#Vh^7a*nrK@_q=qI5K01-5#(Ehpbr0T(q1TFw=siiXMrP*n~MQX&S;pqq)u zeb3@2CLytL>`&YJt~Gp5K8!=6j5LT&B{di_c(~VJ&O9zX0C5s{U?jqzrCxI-x~0&_ zkfNhuq~Wy#JOH5O11QZ;&6 zPFpNV3xO#NvNlua{1>ibpeV)u6svao7|;Gs}h^0 zc)mY$L^r^K+1vGSgdGV9)fWI_S`i&}s|KydW8@9)cTS zI*5`~8Z_FL=8cvAnglJ4c%1v_Jx!2-#_jH(u927EZY8;vxvJn#!Yj}2@fClk~G31+uKX0{uP3X6Xspst(RCf!j z?t=bSEbMAUkC^-P<3z22)@M&@HGf}Und!d8i5k=HJV%!vX@lo4ww9}c=_e1l8s_#g zJPT!>zfBx!8h)(_i#4j_CE(!WPVF?3`MM`Nb{a+a&P7GE`L@o4HBDwwj~(yf)P&TE zibdmWDwUj2pvnbdaK-<^VKI4=eBr!4)nH>&Oe#>TSJiBDJow*PfGbohoe}{|>=3)^ zOQ?eB# zXan`SD!gVz4!bMj>cdUMw|0o+uZX-RcS4oW;c`b5DP;}B zh`#G#^UN>bknQd5sBRwj_U11v@Pd7ujlH7&;{$rTGAfCyTWv-LNmNwizfE-qD^7EZ zX$K9a6TK^b+;^6*zG{EUCQ{Z&WJY}XI>y^D^^^K*4g4j>m4j>@uQ!punMY50Md@Lw zW@V)%oZJ)-b_-n;6WJ7S8^2AdJ%E{_E6grBo{*gFE!KD{eIsI_C5;q+ez(r`SHd4# zU-L%-8o&9ZIRR{fD=}A+wic@i-XtO`{kvCyij&*MpZfz-G9^Jdra6d{#`<<5@O@U> z>xjsm%BHc@;%`H@Rn#r6C!%FPGs{pB5p95CrFFI4{0VH8v9aQf7Y7C^LHP^|AzO1y z&p%x&xC`SLNx$ms&<=x4(*gusrxyFOg9|MP4ET+1j)|zV z)h@Hv;UdBJ;PDPlOc)Os$9|xcS~DvP`sy!0Y|E;IsxvV&MI+1Sgc=fAt!_2Jx|}4b zkME=BuCApl-Mp?aKHJ}!t2)J1P0T5@b0!@_!yS=Ac%?jEh8r6{UF%YJ{9@aC*CDAe zCABKOHdCEx8^NCR61d7__3cQ;V%0l6tPW*Adpz~i*mhD{~tYb*W7XM4kua)& z%Uo+HwSyzSmDTfZwKYn7_@_C~&yu3)1kGt-p}e?r>-O;kR7Hp;Ik%DnuUp%PFJd91 z%6<=`yWXCR$XI#Krai4ZMltI5bG9rTSEk+Z%yYi<0V85#-@`>4R8dIrqt7@5^yyv@ zoy7#1_x57L;^za!%$CZHKvUfCQc6O~#G~i6@vAkHA2n6nN`K%a`5?xf23*y2GyvX% zh328#yRo4%kyn)$rl;#9u{6jCK|mwDyhgveu#%6dW+04jHKyDxmPXF-VEEC(SR_6D z>p?u)5eg>1@eO+QZB&6{?ob-50EUm1Z!e$2%!kuZHWKQehdINw{V{J>5C?B2Y+1ROidej7> zkfVj1#clVNyzpYyMH6R6FIBZ?XZ3I&#!9ulYUqx_>gao*{fs()hH&&v_*Gjtnb! zO;W9K?$u(yuwtcFv&y{v5r6o8+Dh>cVLFLXu9>)cJ)JD6czySBd6Yg5&Q4OPj;+~%Z#S^u z;J^EnnK_C`g-jGxFrN|c6&1fNGmSIdTQur)U6daHzekA%qXLQxq{a?9`t{~ZigWLd z{1XEKIqqV!r__Kn^={JKkQ8xO0ZqDc4d#u$=uRW`cLfJ-zbIG!kiDaq)0BFOqhTXa z7Ngnxo{>LJT%e2oJXaRzFx_)QVqYjg_gUMtPZG(A)12z=N7+GM`hlp z?>g}UC(TQ0B+SDw?Bi*uEa{JY-ErWql!;7vXSHxkSd(-`_{M83R}%=4^SLpwi95WW z@Mxu^u)(-vrS;`_BCT{#>^$Dr9cFR`F6 zRDp-hplR`^xhfn?`?8 z6@8!Xh$KfnPj5y>MkGIm_`z1shpuyV{POiyK>j#Bwqw|RvbL21oC9j;we|<6lkPeo zHUa7=Zl~HjZhW`=jSxIs+=IhI2m^CcM-$}hdCLuXG>Hf{0SN(0u$8^&UudU{T6gM#)#&H&$0* z5=9WcI4oD;Lvu#yr*E+8b2HD|g+=5yX-}8TpN^$Ay!KlU5rFGC1uo?PqmFOi-f18r zMPX<%ARawNm$gXrPzktOZIhpQZvEh!(a^?y)VHLU`9l;y-uCk+U!A7A7TOP68!G}r z0@0?{NB`2>tu5fe(=u#yElX&yJWL#Y5q7!)Fszy43q8HDFkHc0bxZa#!wyXYrP=Ac z!2_41mxcP4bZQ{J3`OVn*!B`_UTZf!1$LLaE?(6v23fccd`8f?vC;wOoSy`qMZxaO!D8DbaQquX*<|v% znaqtCwRjvOIxg2)^Lag9fr)di{V^#XS(Ev+&5%++36bLK#+V_z#MLGUoME(Ad_K|bOVf@7E6Z0DAWGIrm*#&m6KI|?oTePzh(6}Zvysp zEG!c1>$UjOcy4UC-LF*E{F)!RJ*;(gy&xQ~Waw+p;ow5Ey}**|crr?W-m0eHq(kwZ zThHL%qDg0*fxv5TEEO7sTPsmRPSVU(%iaBVPZQ8>2f;akr4R-bY-`AU;OV1&Y4-r#l`}v$D{WQZ8;L;9ot%Jvx~{9R$ywKCVi9T^*aO;$o4%1?2^O#)v5`W$EL%Nso^~Na_~DlRHcG4mkzo zdwWY~3L3BLiXZ0^YfPlRBXWO{z$l$7vBXC}(7ULi-u3t5OPg*-my`+h;!XcX29`iU z9YN|O7om+*sO8g$P8?Rg~_0iPE}}_+cKk6&TemE zQywWL^!EMYar>=I6$3CSgCCsb|Ln20047M4&pAm>=+D1|q}cQ2qYb-7`vla~!PQYL zzg>RqjxOK8-Gy2zpJ=P^eoyqg-M4P9{;|H~%w0Nw`QaQb$0&=;tC@e7v*IXLTB={% zsv;;Y!h5Dt?-sal6s5AeqJyt&O|_Gdxf_u?l8WKL5GBo8-EUBKT)+MP22fils-P*S zJW;g8SD>~Sf7<-nw+dDQ*b%YYXy|k2pt>*6jbkuI%1mABz?>GO{ttHX?>OOnwi0Z(wai&`yx(Sq%JX5ZCnLlfcSV1O5M%ap5zNV-#AAQp zNx*A=a_exMo>1AYxIdtmKWmdksExDXi78sEvAqOJ0XE&{M5e&cT}zq~^1HpH6sEym^ z*7%=qjF|C{i_}{?*%!|UEw>}?v(EOH#YNrA;WTb*Ai_vPif_8KO(7um^yEfGLj7VM z{*bt?t4gf(7>+lZ#pi$ir;C~n%P`q`CD{Z65#K8xC8<2;I}VfGS|xOQ_BThitA97} zpAnYi!p`>1}V~ zT4tW~>+)NAt<4)XO~7=*5;y3yU;Z55EM6v%3mkvU3`6XOZ%XnTZ^zpDWxi)EKK(u& zQ~sXM9sHe`ijr*%wYK(fMzXi=B-~>3@p_<&12A2nIS_oBl@62U-G!*EXaOurJv-q) zWy}8*FaOVv=szelMRC8UlLAA`TgH?b=VJFGo0ov`4~vWWegSbI8c;#hmfCTENV3v& z6EkDMB;xJ{scO(JUp+c~Ntr>P_#{#M3JeyW2Nq>_`+<=%FM4|cT=~_eA`wKNKFlOf zh|6r#Q~XaVm{o8>vyBBcepzq#gzpbLf2D>Dn<*KKTKtOaym;+466a>y?GDd)#s zP&ZLk5}LVFEz`R$0UjfO*{pPzd{A++f=I`GL#;Gu5$!K?SGPH`RHbH%Ai~z2v0B-E z{fEW1(dxo?$4)08BF3wUR{$Os{<8lPf42S!A=-ZBu`saRPy(O+wzRPk_G|PEB(SGP zW_)W48=?fj3NV4TIwvW22b&lU`H>HHHex1}kj~^e^Zs%?w>SmT*bTA()i}rh&H{$M z3;SJ+NcmAGu^1UWGnUO}Z)+W5l01Ca4fUJ8RrTS{ zl-qIPN<;=>8Gwv`OxMGs{RO+_EFN!N^fg%_ve6YFlvCKEw%^)Y>YRMu+_vn9Bt+Yd z&J;#K(o$7r^Jn>Ufi4sCEz;V+=Ez1>LSKD*@FH3kBPTDq!FpD_GInqfV%+;w`?d}f zl%VMT|9NdnAjL?e*!(Py5fhV1lxS2oDwf}}(C|_9o4qcNTcW@GJ>D}b<|s>CdK^3y3x*_O<7ZD!$^^2fW~wY^FYHbFlyJENX{_(CQ4rkh1Pu=i zuB~^sR^t63cwG0+e8K$MAxB5)3AWro&R!^WX(3{-=OZ3xOl-_YM@I&&BbiGLM_^!{c@G~VM4xGApCzW@my&m zHcOS?SQHT-sAmfG{e z)M|?>U~<8kofn;sJzc;Ta4g&IqcybDQhEJm zrhiw^EThL-h1;s;MQcCO%oy7EAvQ?Jyaxbt9K6nT?zh}QX)tbCM=Ox0+p4(nh7XQk zoUpmJoIOp&lL&pA9>p?BTJ1$Ys=eb)Ml~SP7+fpP_rpCYybo(EFAk0)wNZM9va~-}6 z42&dSE_3P;A6DD;P*ZsvFQO~2{K1U~zXis~u;hhX>i#iNmajxJo&ZHGB$NsO2!1w- zaiB+V*<1MuxE9Mgdgmy4rXS1Tylf=>zUtPwPY-McdtdL%_rm^%Gr)zn*8b`81Xw;8 zgqRpu1l=D;mOV~W06mCZ*U5YOyNar6eNElLdf{)-UI1J-EMOCGO(Riovk9|{ba-o@ zTp|Ot3A2{{BMH`2hf&2RQ<=Y~%h=s+%vz2kLtAJV({&2{z%mB5JO6eD*%ma6yu6Cq zGQ`y)fEhikRc4C)_Z#gcxsa#d)dHk{+^|%)sxjH1)#-pqg_)IA$&IV7H-zTD-^$OO z=oPttwTNO2EB0F8Eh8M36Y%W52lM#5)Q@JyDk>_UH!n1cOzrHFQxm2C;UEA=kC2#9 zZB-EgeIK-TnTeUo*ROazHjy7^IVO~pK)+)Phgq2MQN@vS-k)^wZd@&L7yX>N4HNll_tl?q@?yb-bp;KYhrUkObMtp zLpQ7@G^&4>?GzuTT?ZK?@4>0ad&UW#>N_O z*i>e_yQzU;Y`sciSuNOnz;Y5+3VC=QhlzlK{P%c@7{;WA(~*7A-~PGP z9FtfuU=Fl(292T9lX?l$yLYaOli7C?>JdaO&FPaZ3Ux*rJwtqWT@rf@k~4uCPIiux z(lN!`?hhw06GS?)3QFFYscV2_2$mMBEid~sizuMO1*E;O2YcX3f)CEgrg#}n#snO2 zih=Q>f$*6S9=bu$nISo@{DN@cXYzTNKc`#ck`p!`Sxxv1eK$bWa=Od&K%pu&*(Fg} zq%4sl4F@t~T=He&Sh#$8Igb+&!A}?Iu~q-3h8$BI+GWc)WMoL54dn*>^|s6WEG$%< zf>iwcePy4h>17bWb}f=z6C78vsKdw0e#8oT%F5*cx(2qxw3?jY$(rPJg)sVGIf#XD zmp+;@F27MlxbP)8M~*s<8h}=dqX{P@75RkcP>3PBRP8&T>)Fx7?do@V;%lea8leEA zLawciKaY(5^BdyN$F5|63GZvrQa62*EZI9SkqswF0-n&*^kfSh=H#1m_(VK6ia79t zXDFs(@`1%u)IEzR?$||kf9|-&a#RmmB#E)(y9cJ_09(G#5P2jYKV7*&n&YtQm* zZ;ZTOLbG|r%)Z(*#Kn1fCT6b7;6u4EzS+Ml1*tsV+|;s~>SM+uJzr3DKpV2NqajNg zNhG{5e7PKBhf6}(9F!+^3Ax>0%_X8c>72?%%TKRrTfggKRPL9k0X%kj&k>U1X}pK*c~orp;|ypnOQiiBa{L(^;}a!P=+ zDWrVMVM^zg4y(rO4!&y=j6rn}UZ|m&#ykxV3lZd< zu(z(Rc8O~*ARyXjWMu08#mLSsG|R@u1}_GnF6wI2N>QkFwM_gBZn*Uywzw%|69VF{ z$id1N%s=ip3g#%P&cCJtPlT?nNZAKp`*Ps@&o34oenc>~9SA3bO57`GYPy@qy(rPN zO=DgFzfv3^Q=qB{&V0=zqZzW_B7HUDBl%v0tY&rjemQ_b^B=utYKnsbPr~fAm70xL zSW(@SwacBoXiPC2?E!IUB-PKCv1b+(peT5YOqe?-UpTtk03}w82S5j+sYuS6l6@+w zTF|SQbz1!PY#pe%uZ-B)gpmyQFDX9;KE<`Gs;N!uQM z5=F_*z^jIY`g^`ilH;`su8yB5#tVt;(a)Wmzey-rWP8Sj4Ym=-g}y zz`Gco>x$nOSa02E;5K?PD)W|x&Qs`Ck`z9ES8I28$0Fn6$kcHG8} z17jmj9uBS2=7Aq=8Ez(&Fp=y!6o_gjfRG#z&}nSbHU8pK7DID3FB(n6yWqv?65Iel zF`+Wj5;=i>3A?9239?*!L4`;~2N)tOpU%HJy#-A#KTqWsxJuse5q15MC{$~!B6UYD zF0RJV(&oiza)<#aPCs?eRJ&$C%t($TaRkmzX-36ts$ zs*d}Z7gk62CwhjLL2e5Zi|Bk){Z*Y};q>M^__Tr9*%YQvE^drq_%b*Mxatq7>EgIv z+%7Jzm9%Q~7YZX^-al(7qox-B{27}T-_OJb?|E_M#KHL{JUo)g%;`b2n1NZ_Gc$9& z@YMq?_}j}0zk_|c@$5_-gaR{XELa@Xw(o!8o<*eC6oE+g;gm0k(u?{fv3E+F$pwpNTndY}421+hf5KAT8`tj>+ zk&o}!z(C9lcXdtEpqsskgu42+rltAs;*yfs)Sj_9BDIH@gTlc2MSZrb?a0cf45cY4PcgV=bo>gnA|Hy z?@jP|3Nr3mEz1dQg4EaJRfvCYN_h)W6%8xuQ(<6Y3OeC*s(m<{6gjX(mdqw@<_#jo z$H777hpRecI!fKKa?HyuRV*A%Nu4>96Sctyzv@S{`bgqhucW4wg%;W-p98RjD=9s2 z?{C%MJEC5>r8ROINWZA#ZdYon&-!{+IzKAgemNd6pbBG?SF< z=j)9{2v1U5d!^_!y0S`S?d#7!(&DLZxvv)x``=jry>}%qfEc9?pT)f5=hp?^1(Qu9 zz*FmzlvkA3($bon>>G@YNtN-6o2mV}oRdfI=H}Y$c09nYs3`v}N=a7XJ>_2Aa^ zX2X5wa0!xk&H&@W!9ms22u5xtc6_j{%MI6b)lsdjK408fpB{sYemg2DMy7JQ=Sdn`?@AQ>D2KiT6LZ(n^4kOEP#h zF9Bcc$2SC=sU+7UZ-PLz6-9e}Fq@&v>%TdaaM(b^<(w&G`YoysSCfE%z~`zr1ujBc zDU-L}V0limIUq_!U!TRc$5G-|->~*v?T$OR~>PbLv8Fl&xJ!}#P+?_K;m)go$X2Sv_Y+}+1I zp?q&?frsrwt!tfeMj(tAurm26DbuM*8olSC<;oZ!7=&0)yiv9N`MSA-b7MR!@h3zP=9 zYR7T;C3&b0L?N>Fc8#%i-g;>YNfls~rfLuaA|EM#y|5cUxiZbjt< zdq*n)vY7VvN~t8E)NKUGNcnw~I@F^iBs=vRlDN2UK^4-;4avsSuur44g$dHY<&=)C zEgT|zIUHFNYC*jxQ-;=dSRA?rCf5w!sJBu5Z#9#XmwSih-%Gr;GzZ%GyDZU~1 z1@R;A?Dk*Dmw~shUud6S(#ccajYOK9M@mD?^xw} z*MJa2!4+O>Dpxpes3B^Uz%++lIHp9vGqkjH0aC~SnPq6Ms-fm!zCm04rVp4- zz#tAwBq#z*XzMT`@>3w!2PJ|4aPODFJK%km&vJu3b;ViMEq{KLVVhrJSy`RUowyp` ze-QUnvypn>om><;F>!`B+C~v+Q2!k)WMj7rk%B0$<5CGDdb-yB0))?}^K*=;z5YtD z`J2_yq(J?>RFtTM8bBedsS0C2%XqTpeYL+>bKCeLm}PEaz1BNhr$l@@^xih`JMlmM zqFrybgMk2E)wlBem2?5yX2FcHkGL;YzLx#I_BAq2okGIi7MdTwBJ4StfDZILyAHSzr~pBJ!)G02HCu(4UZOZg>;=tw0k3SvR# z3N*xHni0Yp6yme8#y?hBfqM^nH?cGRh7)hLd~tCx5Ng`M&>o1GSy)URxT?-!5GVou zBtQQY0V0XmA9^kh!#KOR%uMAwD?obwcb6~vH}xQU!+U{xHjj)<2)OQeELV1WbG>Dh zEc)&4JY1}+B`IkwdJ-x>gMxyp$@G21r-tWGsi<;USVvj~)4=waS}pJwlVRnK2=*qJ zBlgeqex97FOXDtea*a{r7^=R>>d7&|jMy9B8IRTcG&MEFW4~Bu)ujj=q8GN(eqYPa zsilfBYU3IMWTbyZf853bVh9jsSCmwrNLM;KIQVcjNKSKb>}}LtlTftLutC;M-Cnxd zsH7^EqnGrzxp~R|Sm1VRSC0ypm&9Gvxbpk=dcEzi83iMw@sXL&q8)~KdtBTP>V}5T z3APP2H7=(jpXGbMsP;bY;H!*XZ9Tz9w|T$3Wtq8+rP4&vmD3mfcw6&{cVV&C;efGm zj(vmU(SEu3ZWZBuO|^??VfH(_ZjW<{i#8Bp1Ln_wMUyQLCJihfs-R{z60y?;V-)&Nmj2ZTLZ!^n6`NC1V^NyF9OR`>1l=4RbfGK1RBREPrpS398#N^xSq3dOEdp%zI44|+i!lZM^Wk}wQzBiK~3&J?;HQ`KBYGhiM zv1ks!I|3?W&zGxt7LJCgcuV$cS2wTgeV^<5W1~K_-wnko+6EqBeZ z*%>=>f?f5kl+?&SXr%VW;z$O+npN^d0X#h1di%p0A?j%mzF0~5w7YZ0%`&|)-vg(Z z>FfsqBVVOR)QpTqmovXBRGL<63%D|x#>5L0WZlnCpGDCfmH@QM?^z53L&PQX@O6+K zslcbdTM20)zij|;7@keAF)n*&CnW;aARQ?GwM!RYe-$dKv_32^+Fw9B*6W#V{5VR7 zSS&FL)?Ha`PPiJ1Vw=Bt;*Qc+unXDD%y(5#K=#<^*qGR}!OD;Uw zwYE2t5|P$$yyvJ^O!tFbxBg@$lo><|0H$Dk;W#^snds)$?jbl29X{H@&c9sDcDQ^V z#oOu1v&|UCWG>)-f_FEqR`Yh`}gmc zCes#R$d-~4@j-6v1bZHZQ7`xtJ)oZfhO+vXlsNb#1B?2)I$GW^xX{op%1z_FPC9+P zut5?IXGBTG)-)bs4igJ!XXHk~4<8mwl3WU-Y)%$k?@NCH(5x|=SheF^q)`_Sju+yW z@0snNcj4<=T^{<>Z2bv2N`E%s*IJ&PAwfZP0n6O+LVefL5OnG5N^@g9Rj#hbbM#xE z=NT~r1JcUKPBj>B8Wuq;jlGpY7!}01q3q3VqYmHo>R;&7@3^=~>xte~RwVrVCusOb zOK;|k$$tB4K}q0c>E-I~kS${=aHQ+2&DI_=`@}hSnI1p`go(WHuDlxJ=8EEJSS=-t zPtPEci6$s5E*8gFgr|jYQqb{-dFuaQB-1x+IoFCv`a zvKYo2r)&~74v!mYV6h9fYvSemb9f-WLjQ)L_wpfm%bAl1w<~m9OR9;pwXxMFc zX;cHQvV$TLE)JGU>HyQ&-d=T#WTl{$dTMemhz|E{3I&8RXA@AO9#hky|H2t`inC~9 zM{>m|+d#X5qwXxsc++}>8N~j6w49+k!up%U{x&Gi^#zm14+n>Yh=?qwyx{)!KmkL& zomBU{?-dYlXYkj;@!-)MZ01?6wtOXNk+xFj;^ItgY#B>#gRT81PMI<4?~h%`aP2W;u=I*5O97?aeh@-G5q=ZqfESU;TU zO&2&guC=dM9g?eZX=-XXJG(5}anmw@88?QEwyIX3bYk7FTS2eKm4ShP)Dx(Y_q@bs zjK+j=a|DR8fdv6Sg7+WW{hD-?LU--c=0z2R{g4|!9j-M;Ee~09Q=u5Md_~zudHgY) zNbjozHM~CD<9iVjJ2MRExa<^-`5~+fa>lJ!$FuhHnJ_9@XOE2{9xu}~ZEqRyTd%G5 z(1?CyW+IId!M2Lr!-JPWE4rwU(_sgC2(BKBB{-?U^hTtT6`}_Ip`u;^NGc?!-2HGY z*xAO*lPj>~9!N<-h}BUD1wVe2wSvV7;_^7{!sfNkPAHkT|N8ywwj*>m)E_~|IgQ3! z2tKcp2f1Ku<6Ddpc!Vq2sQDR@hGv36`f%DX{ub$ULF9Vn-Fti1vZA77fC$_NfowDKSP`J&5dTxG zej_$vQ7P8xgsq9aRB1O!67vht??<7j1OcVjj{y*kDY`x9g zOq9`7lj(8?IteZ<0pCVsE`1$x%QZ6o_Y!QiIw8-@TNM?s_VjAJ#;+B@N$nD-*o0jXh_<|4>1xxgv z(ctj)nTbloM$Lug#UIC|0Ruo%Br-5E0swOi9qY*9Xpj4Kb#+KoxSd|Bck_Y3r~(2r zq4x;H{_q11^=4u8YA%^v3RoUp;#Y|ALNpcFgJxh<;^bk-NM=)7W;SSE(L_5rVZlPQ zRN_JcBpNAYl>+CJF^0%NhF$P~`(XaBo|ylSJ`Ycg&94|7L?;)HcrUM^ty$Ml zb2wKABA#F&v4IZ0!an~HQ7k%oANF>3%*-qnmvq?m1S_a&ZZy(|Ub{w6$SP6V%YliH zexqw$q2)Bt?m~)-MCBxRl0fW}!`9m8E%rRQSykG&A4y5*{do zww+Z6jFmbbvN*wX`vppVbYSy#|B)Eo;S-oEz>1S&+&pZ2A!V3JU( zOO3`zP8WfTiAjogPAk&!YOS~g!q2;~wETgYi2);Dnc80N+t;sPsKuaZWoIY(*<}!< z)WoG0G&a(lxyU-nhO`Q<{&Rvm`8)-KqZ_E@iJCYA#Dg^G!Lb+^Ncr{?lG9;zO%<40 zQLo$vI=TFJ7I0ug4Feqv!aVdoBsXz8Pfe)M%aTgTe_sZSKaUgPk)bhV1qI8RMRR5+ zUP)k6GJ4Ed^HtbQ*Id=Lv{USz>zrg%d`!=fgqItj)x z8D+R)#ZiYmr!KrCh46ptxwV3LUNve;O8*K8k)GJy@wz!ujN$*rS(^Xe531$)zCSO; z8?aK@jXGGFKDyhjOIM0}N%w)O$$+>CL>pyvIE5Ohy{q&mr*aFD=ms|?AZ5Bfngg+` zp+@D|*%P&2ZDC|u=*JB^Ja1w(^^ba6+)%1bF0-Vhq$-WGE9N^V+rdr;Fbk07WEFK= zK0SaCaaT9LcdKj>nytozHeGRDFb}{Q&92+*J{^V&LWU&6pqL>_%wY z5)yDg5UY`U$-Lt_5CvyzY(_$`!4!q*^OXE2KpO)3{v@XKvtd~`F0QZdsTY>KpM_yX z%D9;Euq0u@J_juOKrHoG1{Y~!iXxraB0TDC^j5&Z4j|%mIHId#$3H$k_P@`Z52yM0 z(-P~1WMxs9{4tg56KY)a6ruc`68{42zel$%Qx%YSBDUsLtC z^Ky4z_MrUzZxj)qn2D(9o6q)VH7670w4dF@*^xTC*7}B~a;r)dI)qn22jlj4CE=54 z80OkaQ*>tQ*)>WnXkAwz83ked0BZ`ERimk#?EnLy4)Y~*RbaLKVL;@pCa>+d^SQ0) zLkGvZnvHt$teBm}kv4z`iy|sKppt2953F;Dd&nTZZ-+`&l`}YWjl}-;Q5{)l`(@F_FO}WZ| ze1-;LhrYlSYVnx6eU_>{vjITDG7x2)mX>nnvA?&3VOY8Gn;aIJ(_}^VVtpD>#^7%Z zgacl=bGM`cSdL*&=>5NJV#exmmmwqGf{ubTC|vrxh6qsZg9JO=Qag+8rw?YAN0^Kf zd7q353i{fbJwjSO+Ua*Uq0DdMCdJGQE$3O@e0Pe-`||@`|CR59tM|)fv{#Gg@(Iu+ zOXQQ}?kOZzd_jTno5W`~034_GLYa7A)d6mNMj;`Xkd4V{d~|XVdciz9pxiiXurI-L ziVAENqx2{l=4ofuZ}Pkt`4z^dyn#}xQgKqGIGDbP(P9Ec8V=2K`o_Cy>Od z6d5I2oLKRkp&m#l2lXrm!)?C`$M^%ZDPXYM&BxBh7+41as}XvJCRDP%5kKQRThnx- zrRcWU99x8s_S~>EZWdt%6F2c}Nd3yIG2Zw79s`*i0mROQ5WNgbAtz z>E2POBcnEbla*D~mGzuoHZWNl91oQqAZSnc;rcs!dzcQbg8cma?f`FL>{@F-?Yx^h z3ev#NFRY;Fd-9E>#dO5v|jbaqNuF=cGH{{j?eY#>KF4m_eztmDWnd_tLCPbnK_ufLBC)OUvF~&7gbwd z9g~zaKRp|0FEtCR*9r24@6-`CxnV4zbqI~$g@nq$`=SYXT)e^&FLjzYJI7eDUhD>9 z0-b)aK~uFwA$(2yb>ue)LjaA7la@(SljZb54ITnqXh0KeSHTAkzl3Z@D4qA_=qb+o z6k)R~C4^!$xl6Q+^aA+LHsRdc>gv;DnH`V!WziFL#s(f%%NC+9hH7WqpLzb0PrCiHam51gz2qWuL#mXxz-O1W5+ zJ{PFj_c~ot3MmRW8&H}w1JF4W@s@0zqwYibRbpK^AU;yAw@`xx;zL36GT$ztfcH38 z3nA{ka6h`2(NG$o0qpD`6*Z{Tkr5UkP{B2i(b}!9PlgRpZ1p}}E;3PGOy=~#3uy-F zMU-1GqcwF^x^;H##*`s`;rWO{W>#ckOfq%-an7Id^9vFO+U-G1WD(pO>5Y1c_-(^W ze5yYr2*r2*=v|{)o}7QpJSM+uv4XbOunIU_Rr@-2uuXwevMEc`8T>rMBJW# z4L1ZM{0)oii_(v4r&Is*GkJkG>n7{}pzW=qs)`zRVWnFdDd{ey8)-J(Ac%CgbayJX z>F)0C4haG2kQNY7y8BGu_y4ZW7-yVw@!xO(i?#M%G1r_=>Ztb=C@Cm~y=Fm(9!?G&`!~6ULuU1-W*UCl zXqn*7Os?>$`rq~?ig@0yzvh{9TRbyQ$^ z-lJzVt4#E63M>r(PE!xo1`fn~bNNo%+65(PfczfA9}kf8oLmpf0rAH;r5)JKC)NMp zD9R3HJ3e9K+n&r)pY|lTBO#BIJ;`=%7W!-g=JDdm^`61?Tw6IxtP@H3bavnVU6I^J z6_t1WVHo}b%BB?s_P;l~!!lxTG}Iq0yID}szvLtdxDqe+O!=-KvA{8iH(sxSkV<|N z8pSuOY-N3aJ>-bEoe8e2d<(xC53l5N1U}gF#UZ88L*SSM#94?eeq7` z1|tnXwe{B;xS!@W>ey84+JE00muOcnm-XNw|Nqk-z@VGt8lW zrh;uj!AWf7WL895zzAv}rRdAnWk<)$WdyNV1%dQ*L(+-}lk|FsHTsG>`vE53xCPtN z)^rW1aT~E?R>jcp1|%yKdMM+geFhLe`+-~~CT&7*9xs7()sUPGjXAE5pi<*2m&~Eh z89LlL;a5#isL9tlIz*TgVo(Sz%SU-dm|OCs_~I6n3-4eYiRKRu40Jtjpt@G)8t&75 zR#TfM?`L_$MOeJ8><}Ub)8}1FNb>@j*vo)H+M_5N4<+0!EoHwFR|sIDL>%FGNrsD` zTCLeGF{W)j`P&?fnHdcI9`6z(qZiaQHR`-Mz^8gW$5W;URiB&N!X6#}I&A?u;zPAn zl^tXNRo8IQ@OR}Sx{HggLS>Nx5%Jz15U8CF__h`^H{=fA7TB@S2neP?H9BvotB zrSvK$yK`cA*kye{n8hB_-T(e;^J9!-8HwJ0Dc;m8Eo`nT-Km8|YUeDz*+QHntUk;#6aH#6d@I;dq!NAbl0UC@M)_B}2zw~b~B zAD?xFfehe+wnO{%L z4zP&14briR_&pvB8VIlW-AJfY#dp#6BL+k){981zD3p!YG|Oq(p%eZ1x$?ar17FP0 zkmA=`5M6KXrZSR3Ae<>+B$VOGNaY)xq4n!sLw5Z&@a35{qDhuoj%uRar z^;T8mREQRZH{eg!|D1hn`usIb_3f7wFzsExpENY5Lu`>vu6ht+VIds_3n>sG5{Cb2 zJWJ3E-t#3GM{eabZTv0v9lQSr3+T4hZG3^w?{$QN3&^H;t=O>gWiWYepPScnxOK5u zC#tByv*s3M*4nFrdznh_r2PDnU4w4&qs`tHF0hFjjhng4HQxRWDL=_IfSy>R*izJh zg@l&9w~mKbAhOfmp5+N8EtEMUoygk)=j$I$gS@sAU#h>T9 z!?3Z1qn^QEK#HL?cx`3$;%WilxxmuX&mL?BTD<;M9-+niJuRcy|7^Ct{FzZ$Bdej{ za(M=CRy0&okyG+Qg`zK!+ABPQck!o~JCop+oTeuCY`__)tS+9^A;HCkS@^W17crI+ zCl0vb@${(Fw;X(Y@T{LL&Oz7?;}Z`FRYS-R#uNNfga*sGt$6zvn^$?^(b3VXwYIR@ zpKO0Nd~7v42jUTaHyfswX4T&&-}iF8uE|0>dwYd_@30fp6%M8O$u8hC*sX3WCyOU3 zHrI88jmR?s41@01JWjSBcG6Ga10EM!#hGgU!aZ6P;0Hi2&`E9W)L{biFa{lK<4^tQDD?oS5&y(}naJ05}N8&ZPK7mC3M)_(Mpyt?!#=rCot+C2&iofX3Ja zh_NW#vygY)taQ&C@|G^ECGTFbla$e;vNX(PG2SF#$RI->o-9sFOHcpC7L0<)fxV)! zTRG`%#IE5l&Ui=QVJY;Fp|=K95~Jo&W^0q|7wu$fQhryDE6$PA-9I5Z^g(}!w# z3}(H+dhtU~14m4Ead8el`fe)zckqHaB{g%P6=TM?>kj_d{d13JWHG(ME6sz99`=^t zB>Y{>{=goOQabndP&g{j!1v?DY-|2bq*#RL)d1Y>b)H_B>0NYXf$wf2r93*JHleq`Ik)KZn>H<_QhAKkYH zKx%r)yBhshG*vW_nSZTm7QOC8aNnhZ(c*=^|MmNb(%jrP?ZKHzSy;r$NK=?6@bAfS z@g%Q$jq9{ePa{C<#@V_t6CYn|e9?rE+kt_$JN0lz&NIwy-N}hei{>rCE1Ng?_{cAH zdWY>8di-v&@nEx}Q%fOy?PavVO_<)CUCC`AIa{XFRosG>JmY=L5~jex2u;?L5)D5YTyx&8~mz$4m>fzm;~9N&kv>6gwgk<2lpr| z=HFa3(Hp450lh=yF6&2R(FTy~xZZKUaSqZFSpGB&B0rz=xt%TpJQWP3RD0(r(9~4q zTWOWfm-O$OdIo3a=V@gQ;b?<8$n+T zofq$(Ty1rd4)H!%_Wrtvv*NAqqQ8KYoh(Px;AtB+1 ze))fX`HG~k5+g{TLiIj}6Et9AJ$%A~i=zOO$p6Dnt50C*ny)Q0ze6Az%P*xMt12qG zSz1r<=6tAe??=~o$)>ovdcr@+Nea=Q&c~;qaOX<<9$Nw$Ldot{*|=m*v~k?_g0b=zcRWmcP$tENyj4+h2MS3wB^>ciRTgy9RwaUICsBkhgdemO-MYr@$plVR@f)`S5x4 zs!mqQD+&L>8ZmTTJE^LCZlF29lshKJ*-ItC_2@uXDzJP=&GRy z&N8lb+?P~TY_GLYlnQ~W5D#wa&(}}+z_IHuDv_ArU|z@Ohhk0Scctzlw7Q)z3%Xyh z_F*7BdwaavZ+Un$DtSnGInHEv|HgD*Gq@?s9qxCc%_i)ep)3v3WJo`?{(Abl|EsXo zv?DdzQ*vBsQP-J$W=ZUWr)|C!pm7#ZXo?<_UsY>J#10N8){J8*6EeDE0Zwe*vtY zif#h95vy}@44&8dhRcGJtJe_`LJ~wSIxlWr+%oLdH?Jbhj{8uq)*;;|?0<@s6vKuN z#=?lacuT}0^wl?C9B033^1J)68%$c8K0%l54Q>77d9WJ8XUEMr#J@69^ch8NnFTpU z(GbH@?>q>&^->0$=O6rVRO`QdbDbS$HSiio1~H&<(C-o!2w!O zQb(k^IH8Dv?RJ54Er$7E2*kY^?e3jGE+j!xaQZ$Xr1b-kM}mwE`P7Rqt*QHcH0654 zd@-a#A1!u_=_cS1;H$OU$SK}gPEF5^cM2NdP`U^Mvf1s0)NxqM(<*;6mBx7cbvE$4 zdbu9Um>|T)Aa=ES6@RelO!zpkWs_|(Ut1g6MY}-D?<^v&8})RJ_N6yHZ$fyIXue30 ztM!W8>nH%u#gwmx>iw|Y?Y2K1@5yzEH1T02n)SGI%)C_OEAGWV)}zV#z6XH%zk&8j zNnD+rzske+eiYHwNx_Q1{Lj|{c8TxVLLuQ01>s*wDG9h(gyVkJ_U5)$lsM-t0B;uS z2a6$~8(HhTj#84@n%qcA$~pye(t!dKAPTc)I&Z4f86KG$WuRNJEENZn8g@WSm`^pi zpw{@tWOl>?Q)#*Dq0nq!d1-Q(7hk$ul%E~YkW@SEdK7h#94_+<$bR)-pJ&~xZO=;SNLi&O3t{~E|-LwJ*M|f zBTHLieOoT*fVt-Tf=Jkf%+hkrV7~LVN&zwbeaO_$JW<3=r`}Ee2l8Kf+QRPnt7%qE z)&;D40ZF!KHti3*ycT8F(nP3latv-0y0`k=3H^PEyS`eK$7ktM-t33SV|cekRQ2hr zjYAYRh)-I@+mlGRzb%NA*jKYkc#pPX`hzJj(AsQ_{*#E=Y~~geXdi?fg3{R2(aH}q zbeN7M5XjjpB!1sBlIO#eseTg)=*C2kSv~3BirzoL_AnKi2k8d2k=GACa9wn6%~B_q zH;CR76QiKzHNE6>-(jrFGg$sQ#81us01+rBuaL6te^wU?S7nSBN{M0#2$ovNOY7An zKJkovou!pzBk#gX)igJ@aD{7m0bFWn-;3$O&~2JSMkKZ5gaobf-#C%jSd53~`^ zei#;s(Z^07CAl_lC=A$2u9mNI;u-X|u(n0`!r|~Mx#9u(#M1DXhg#h|2KjDKxyb-S zznqnBNlv)&D0DH_`NVoZ!S99ixf7jb_&duj^rJ~tHBv4Uom1hZIm$%maGu2G+P9CG zrAZS9u|g!BLI{0Q<9{`}&FYGdBK~X_Iere%;ET$2ttwDnek9PqXwjw@7r4#FI64^H zc;I_PlTmo_Nf#_{!eLgZvjqJ}iId3#a;Xo*$k+WA$;F4HLV1n_y|2y=`&wsYZ9nyy zNq-x_dRMyH3ju<`>*JrusNIU03MQdSz8}9d0~lXOj}*zKSD{G%*p8FP4P)?c#>W$W zX|zMc^$Q?ibatHK6TjjoRv*v~8g|2;2Lk9NAFoL^vE#J124aLWwV%PD|!N6{E z^uUl&6wVVja{T_=thsQAq3_DRNgfs1>;AnCN~52JCdvUV>Sn5Dj%-TfB7R&!Y0_`Z zQua^#l;Houy3Odemt^YMz)IniAV@g9C%otWJyD9tP0G{FAa3+d zs1i4B^id9Mpg=>^RSHHMtnO!?{U%0iXY}C4jGAn=r6Nve`)O8Lo$qyL?5BdM?V}YhdG{Fn{&gTO z1Q;irh|28lbnsaWJp@MFzZ-3k?t$-ruz(ATB8D4$gD(@w(~R6~4r&4#u`jg!)d?2W z$f!_7-QG8CKtuiSGGLK6v|a3rAagJOgnmGSydr{YMVibB>b4gRGV|~xW_TVNGCFngM_MJx8~Glcb4vxemcJ!+CAsieYK%gzZ+(DM*Jf*jLj>IxP1gOS^H*z>3vS8 zED(g_^yaldh$M-xX|D1CCW#g`kax*Av*T!UCP@oKvm;6EPF@~&=haSYJUjSEf9@r1BERgmlev%-u@WCN^@y!T2z8=m%HuV zT(~rD%C5-xZ*TU;CP;O}OJpost5~l+9c;H}i|Ke;kly8kRAQ=rvR?R6tt|&$@UZUs zyOzm*b`bH~PUa~o9o>!B#7-oiJRjl*l|$dvP@#4qw-BawXx2XaC31v7leMsL8IN8x#AF#@|?-{D>Q zUWH(8+87lvMzr*rgrhsT7}}$ByG<(=36y5VxA(Xo-1mGRnvg|qMeVaK=B;hF zHxyLBr0uAQ@s*Dg#m1pQ8TISEaVF;dZVD?KX}w{m-Z_ER_AJ57^edR!lh5jzGn1Gd zWwSO(MP(!dQ|SU_Vw>I9(+Vzlh9c5rMe8Rcw_c%=URs--0SL|0pSD zlM5mG8LOtAU{Rc+-7snETNpEjbFa?4lJN*MR6bn)0TA50g-Ht#qf4sqfQEf0^py7cQh z#;<6h`sx%Wf4ao|02K2&9Zkmt zdFA%CM9fH|k(Up~NCn;E$RzaDPS)8pl-VYSty=f1rAzNV`y{ZQ9eq4NZ^7iWD zVl~CUd@!>K-GHSL66Dn7RAw=9>_LUqIy$pHN}f}g=~)j#Me-pfUOVkFk~HKu+cJp8mk&Z5C@a!T#` zsVvAP-SxebCTpg6Su|h-Kmwqq=B`FcK^Y*mHjZX~v&F}&Wp}z4mY2iwJb%5A$1v=N zfje9}fmhWh4jZ1@%qC%zl$@EH10uPv-7?g)ncnh)Hj#qvPnFt_S!Wb$Vx84E+hTo3~OC5$9< z$Z*WDCDp{v=K32>OU>}^3FYu-v`tALOlIxwyq4E_edqF|Ub@IIk2FO=~yTyo-icc<{+1WeE?&#Wf7!#=5R-Yo2j^!6ePS<-N#V=1`RRZlvl!@X*^{e=}xOebyv_1-oPiYxh zsSsW`*3TfMR!fVZ7$N$>DqCDE2quUsFYi4PQqCxw)w`mu>r??!_A&e zW8jbqo`3gtR=?K0tE=k`7GeYq@&!E|kCL34nu=N|o;`DsevS%>+N57cVYa0Aswre>RMgdj-D^!2Y%XP0 zv4Vcm!o$ZAwB`qqZju5iL{tesO5{hiXq92|Ib=3B<-k)LxKeCR&RIFxjWTQjU)9cN z;`GPtXu*Hc8@^l2jel2HoOUnt4MpYT>K`(PPn~h1qt)qX1_wWXh881Z!ZE-PKmncG zyMbxVRC*=H&cW^IYWLoq6od5d;mytt(@Q+6e2w~#{@Vei5TM?r+z5pBKw}Ri_YMwV z*eK)u<4OxYE`9oh6nLT%n{3XGiiCAsC)U0}JV-->0wTy{=6dU)vf(K*my~E|XkDLw z;qSBn5NWy6TAGr>ftSP^#O;@1w&ci4#xn(~183%2dS2cH9faEi28fsm+zl2%G7wbV z=TCHe%M=-kWAe>lvuqgV)X}6+QQIz|pH{~WuM?F15Lc8dA>UxJ+xB^P`SWg@vz%UA z&^y=Nl0?vRFNHz2GSKp2Z_`=sSR!Q@y1J5J3n1#l@g@-(R@~4 z&LXOZj~KD1R%Bz`vOl~PdJBQtKg$ty@M=9oZo(onICE|{)D*h8YTEp+_C}uh&CRXht+}_-^fJ?vmrx64enJf4;qb! zl#})J)Q2@q{Vp%#2fY#eIVK2r1E27)@pS*&kD!wi=q&?TqM}w5Hr&L{;VN)q1K4gq zbEub}k~OlO=ox7zDK`civ(#~4>t$F{>C(G650RzFD<9TU!@@r9rD*GSzi{Kxq7)|c zdHjWgt)L)}q+0$$prj@iq!0w2V8$hIkd>|KvYEtLKV?`yp*h(O$*|p3AI>$XzdhB7 zSHIt&270@v-#v!8V6tnUvZ9E2sEq=l)IL4rFz*5_uu3UAnx;{;x#H*dmSVZv z>)E&WkyMdQ)S(hsxVWG9_C|mPE?2qi4`DdOA)4~E-mqCR7v~StDq|( zpR=ZY75ctcL-R*mz46sTi1Mrh^{cN`P8@2eP8?KJ;s8-4_s@(^PmfF0_{eR z5!*z{3wY}2gc`AAKM-;S8Z z&MkaNw;%Q-{A5buU4Xj?4~rGF(joYkj^?$am=Uc{5g-!+EJ!3{ynV#N@scz9xF z>AOxFm|ixpS*~blQp91Y;|_;Dp&0APvI{8ttLS8Qdowmg*9jG6n}wY3jkB z$;vi)FZX+5SN{H#jEh#nm7+Z-T&-uj>ov2YaL^-7B{gL$wO}G?qO1`|1n2%#Y?FCI zQ5!pkrV3F)0U5~o$O3_LK$4BT+lfV>OehJwo{~4kFBsKnV5i^)>S4B0s;R!{`)m$q zbc>~0#`piySY;VZkIJ72f?mKT6v(Qo4}6~}T|=sZLMgQ(K*tdY<=n_Z1(aY@afDNcx({m#yhR%2pb6y=wW zaZftPT=}+=xq#)QYXdp0WXQ(e!CH-HQ2EHyW8GdTn=L^Z8Vmo`)$z0VZGn1isVcPlU-WVD9 zP2NMWlR?K;UmxS26A-^pQB|e+ht~1t+-@!V)fYky&XV5Xq|fPL7En+5O79``ICzwn zU+*=e-i(Zm{Q;_fi;{&Qi0Q7YnqR$oe!ART!^01zt1AJnmBEI2Fd1_=x8A6WlZ7RM zlLc0Ey;aDg)u4Kq?}Jt)M||RV17zp+m)&XUf(BuF`8kN7bxV=gOx(WjRhwCu(I{nd z(sgmx^zD@Q(ynKGo4lK0yn0$4U=C}|Ko7Yj`tjtU0Rg7q=tPqDFxGIX=!uM|Xuzy7`2L^n6%^XBjbr8cdWXM% zyG;%bf~t29PmILz7N8s2=#i4j)W&%#89NQ?*3W@{6v22)50lY%&g=iSi+SM}HInf5 zm4b_K-pncDIl32B$QTDFbyH$iu;Y`**U2=bmwtwq@Wa&*!2_g&IOV@l+mni#alBO* z_lH{r%ztr|iAaz)h+TZCUpOp*v__Tv26HUVZa5v}bnQKdWdR34W*+$}8NgJ)Gu7$N8FlHF*vQU#g z%>(wz9&0RoE&3Jr^0LPs6;rJ2eDYcgasKX17ZHN(DR3KoPSa>dn>GON=jxK0c|G_i z95;3JQ3$Z?V-q&kjnTQ|8i+iJCiLx{ugY!gQgqNkgguQ=jL%u7J60qNeq4P1Tsehw zS&&Gm#laUpl$cIaV~GfG%Nkw@O%OCsrsneNig$J?32Az8CRmnx$r+g)d4%I2f-O`~ zQZn+Z2Yt1Bdu0?M$a+nT2HH+@MM)ALqdQm`Dz1$;^Qh+(Fa$>?@w-vi3Ytv0TQHfyn)o^a4QnVb>p<2>xH1DOC-7MGNjd?XBXYX6a3Rx_Ad3BE%zPP*uT^O) zd%H&ZMg(gM*5b%CrB!hm;}|m3TkHf11qYkWibm22S<=w2o-4#Jz#kp=gBFF3zBgC~ z37woSTlK1k2}?X=#S{1(9G|=Z)rL{&FO5W!-R9oR0@f4p1;N5optlu409;VmylG{Oh4om%^l!V=JwDmp&KFCsk8x~AMzyCQgn`#{;e zONzUQ!G+i|^9O%ns~mJ?!gM73A+Mkz+VKIl%D1c-78aagQgDWgH@75JJ1Z>t%bLO%cOFaUAK5*kOajUQ4cE8aKn-Ns~?)Rvu^}e0$YOs7@mDuWZtYV~E2b6qlF|<}z zB1VQl-e<}V1RXvJ#bZC0bwrWFS3xJF)A`xm#eta_PhvrP>SmKq;g#mxK7e0^XE{-eo)kPpdHT$q~YcRGsP2=(!DgUz(soNI6? z-;IFi=bBs$Q)G>=fQ$uNh4kxNCkr5jQFUtg?C$_|*Pm%;``YBnYru(X%#gvDfoaD5p3tu5^By^BMEYn2@vZUI{EHDJG!FqzHGFIELv zD-8Gh8SsD(I?)2ozYiZGMzD23&8-?~TOw=32&QrTLL74fb%7>!Ed8gI+|rp8o|H`FfSUFS;71CQ~aYM1A0(B^B}T-5ZAdqMPLA;Rs0h5awEmf`S_M zHG|Xa0Zo^Zq-#r3cs6q9|XM77Ed%Lpk-Yd3k}rLZ<P~q2h9&OtGtAzPbwn28{rlP;J?X~z5B{Fm_Tjzc#sB$MuK6ybE!y8RrI_9^0i0uY?baK zGH~RVj-)&wkR21xkp{Vvx?nyoOjGqxQ~@FgVJz7U3n>I|06lUoc_xTBAx$X=-@~1e z?K|OC{WFZ~6sQXumFBnta+)-5t2`NC2>3)DX9&96v zkp3*-$6SyYuQu1j7XEb=rSteTy(LDW@S#+pAiCObBafyW21W!GpOK#af%|cxwZ2%b zzX|#5u5uE(W8L3J35ROQx%_>4aYCB^;w9nRtzUE^z7cA$-w@qcXZD{V_Fxbc z=hE-?2kE^^BqE`+n2lTaW!Tj2L+I!?ZT?9qL3ic^vhCNT+We1*Q3V$=8XAos)ZCbu zP_@l!wV!{sx~&9T79M~)71x2i2yY<}E|k;fHJsGH`FE|}Z*_>J@IV9v8(+xi>DkUj zN~UvH&Cg9?AfvZCp4*jL3AjC@d(MLRROIfjv|JLJ0q%7A?V;v2vE2W;G{r36&1D24 zVB6FN(nSl5@3}>NtL;DXo$ua0{tA08sz{Mm$`bKAP17fo&q}oREj|c(zP#v-3UjMQ z@b+wVTt%sY<~Tg}=7Ut(!24n|n*F)_KMf-|zJwe`KYF@Ou9m)N1-b~|-r29$BAQs= zC!x>!S_KQfQ|hu3^4v~B1(*K)LwKorCH32owJt9umgm+(H`79Ujx?8}S>J&g(b+SB z>{kzWAfF~XNZhb@ZDO}NQ z_e7JG7a%l~ zMrwPQv^Ks8PeI)~N^XT2pO-{IMAK5nWq%Ih*+9fC(v~a%oBnS+Pc>@__RH&l{+v)< zo@y$ts1`l4xxp-&X4fE1RXzXTEfJ^U$#scv%qcwQASns+O&Xuq=0zzEDe2$WlHbn> zs+1`Tgge{3JULm+&w)1>_=mFuow7dfnaQWm4s_NUz%RnWL4iz+$8O8HtiU=sS{&gr zCdwIbfqfsF8Nq2FqH^pxXHZ|E3SMG*xeslNNm z^@r!%z(7DZtuxbpdQ8Q;vNl&fP@BBK9fW@%2`s%BR z7xaP=k*1W@!1~2I(Rb=ncd&R9sofWSh1N9&rl#+F|I&l_D`1ez27Nl2yyrLjPRiwS zzoU~QNmRhD-j}r3#GdZ1-UB<9q~y1i&g(r;yP?IJ;b3)wgEuxhktL8_E)lz%FSc59 zo8^P3-+em5Mt@>=#J8EOvLoTfGI#(XPeQ^+p9Ku236+dl(5T`|KJv^(l3R zPHn7ut%GUqRSxcNz;HVLsmjlPtfM(Eh5q5O3wi^Uf$dA=o z^gG%65%+5o-cGOd&gSaXeN|0OY&iM8_1P#FF-6DY@A;^QtW>Nxm6K)=fujwsQZyEgQ9_5ZZviw3GyjLPJ&gT=I-z%O49X-!x`K(?V331QQ z&$3rLU0J(>D4_Qsfv20@;>Yr3da0=%sV(eO3}jNbh9skXiKCd?c58@@nPGSI<@4<) z{%R+)cXDMhnfF8C*B`s(9@E!Qj3F*?);>BGk*`G~ljAC$#tSaq|1OCWe_HcH6614p zL6c4sSad9Yfao|?+= zWu(pJTKHLXWvN>M=h9I+COcFjUH6xilerQBGYC-(?FLi>`6J>x<^w_lApWJ4{3I1# z?9c6aY4@N+lCe$P=;?rMFjl!@dp$VJDnJ-#E?2;_4Idmiq?m$`OOk8-E&5HDWj|x@ zsZ`Gh5uYoz4D`p{OtJjOR`1*&8v1#8?N=n~AHTPG{W1zdzz8fi$hH-@g2Sm$u(k(| zukr;u(al!1uuYaY{QqETc;co>&dJ#e3YoJy4i3;eIVP{uz#NJZY9S?051yJ2St4y* z_E*kc0>r+#k#(P|-{?(d3!i;Eww8_ZgPY3|ZmD(OwCQzD0ij#nT|(8L1ZiYr$fw~_ z+rgkEiE5TSO=XpRe|_kG!`~8|BMm~-i04_8i{6-S*AGrp}a_sxQ8 zz6PGSOPh+@v|pyLsra-y-b0&x9uKG?KxN@}(nR28l8Gv8q}UuRGs;I+ODAGwSuKC? zZxV%wZkm?Nh4qEWciQ)N%FX)`)AS3By={CkuKFfdwDb z!A$DT7_UxT>VyLRA#$Z!4vXLG3-wFt)`6(UgV9Uq7CMu(a(5VD(I=**F!58WL!k=M z0b2L=QZuS&zmt?YYhivqYp-N(#u^7KNvE{DgZzF!dIzc#|2&TL@w{)FQ>%^wqnQvw z`19LC1~ONjH$$!E@VvF(*1~=45Zz0lcPQZH4(r{_Z4?a!b&;9ZXGp5(5697qbWNF5 zJRY(KOyFz9zEl|GzTZ^Lii-(V#e=1tK5gDgm$~FxkOC(Jk#JR2K}n%Q0p)|qi~?su zS;~6#?}&T#_9{lgeU{y1t!99HrOVsUT>Vm!)~|mwI=zK5_KReBY-KLePFLF=+{d4Q zW5h?;&Qb5(3tZcPnCEc5;z8lmlSBnO{b~j3K&ZObluA7Dvix5*p0{x%J^`dKW&S~v zXPYLGV=_vucO;8N;28Dt$AEtHSXI!}d^yz01TWFZvzlbm6!IbSPkV#}SarW`LO2s5 zj`SHDH;pCy=7g+@T=Zsq1n;@Gw=2rBi2u^jzd#k7EPy&DZu6DiQ)Iv@{qTv8^@%yl zlEg$#SuK2WjlqQjZ>V2prHe}t=;FXxc|{J~zQTp3`AL*%RTt}s!IjX*@N$pNqv!$f zDvPf7s0rST(8t&zFi3vkIBe=LM3(f{wAC;cLDU@_$&vYT+wTuKB$$#GHc)m6uJo;1 z^e%NckMwt*UDqPHw;`T-@HC}I9Nq1qT@v*;YiQdK$E>dVRhYVVJHkj<_HfuJ#tIYD zpDZXJ0U~jfUnVnuo#+tSH|`dx)H$Slt>mvpJ+Iy$SaGaRhPcRzm{8!^ORl8xN)Gvc zW1R1sC+^pv&B*O&5m-g6xbUK+0{wVTe$N7WaH>#$hRS9czwt{sWgz<2j~A$fd%o}s z`sXs*aFM4Du)LS>1RNntq%>c1@#}_b9z(E3T%4+0BLZ;Pz5N0PI2I?5#oX8j2mCC- zzOcsbEjZ(6ea0B6gRXZZsg2DG?Sp+x(O1&bnMy-uSJIe|B2;WC!1-Xiicwog;LJ!% zQMmg%aUJt*O?H5%sAQq)p_&i-pgo$A?=8lq42Y4wL`BuRJHj$jiX5X8%D!05d}i6ZN%*O>Z67(VFP z3|F(yFLP10Djt>gNfO*>WJ>^c>wORP_3`%QQ+0mO==@XN@C;dNP)n@C%#0cVAS@gf zSPKd5oWQvxj+%PyW}CC{#)}^y!ppN?T3khzCyw&PmBR%r-iIcj;qsm<uW<>N{u+g=rV+<3J-4h1+)w0C2sA$Z|gVjE8OlFc1!%~esNHH zPsnkPd^dl!luWa9BVBmoR01Q+t11evgn+SbY1M%q{Mx`HrsAJ*K0l!fDk?-0kF0eo zwTYRxs-O-_`L#xOu^A3(0(J2BzXhyIDYAw122=B^^mfxtpjA zdnq<;BecIZb|B>6VtgN)FU_6f*~HA0m}oElZv6RZ*S1T|v>TCBgMB_-xUn-WtF2=F zmK^2kcjv=7+0xfCuTXo4+pWjyf!C-A4VQwnu3UuzaF+!@B^)0#o*vFMZfz>-U|C`pn1nuj_Y0$~ZCYb!+0`FJSnZ073=(u4!b+fi38;|WXpvtFzcilPPnsx#(iqV$ z)YYnOz6F)_(nYrJD2gV+)xfJj>B7D-8Fys^Gx0xW<|XUG<~{1?azkba9{lub2=}a9 zX;IdBW)QeEJwUX`UkBheaXz1|NTd5>Nu{8Y{3X{u^5&a2gX9@ zN2Aw9RcdQJ8uj~Q0tsURQz!ctHSpS4zr-Q@K0^aY`QPkEz##pHgPQ$#RnX5@oiF2( zUn-xbJEOBSBV>!0sen71ST2PqszDZpD}=$~fiq~Re!l2bc{u!}&v|Jo9Lr{^3Kf{{L{*gjt%mmR>p2pfIHBODmR6FQ3UwLEXDeAw4VtthlIeD7Tmzocr3jCg-&Cw%;2l zQYsJZB6_JdWym2G=9D7EsZrDCgF2a+1t!k3_@0~vy_TXvWxxao_`lOkHMNE&G!vCJ#_i?Vn*nUvpXXBSzmTk=|jbeT>au6X8cspv#Gn&R5KezKqpAysj zxQB$zHw}Dxb2jKT;!VN--N7BWs~?U(J+)r{?b8uf;Gv$CavvQ($}M`NMgRBvII2w$w4jtXHg?(Z41aF_p+<%xx>JPuv zoTmn3BzYc|0HtUKZrt%oh%}vtfcULlRf)tL(tqeb6Z~iQ-JeMFf7k}ADftLhGoaH` zu`?^7YlD)tnf2_#_*A6-yj zN0re*Nd&kqe(g{F80j$oe_=IbJC*X`DBO`P(oNgB~Jdx)J-}pg1Iy zXCR|COJ&8nV*R>myX~a~6BDUKQaqV_UDotP8;*v6n8WLp19%$bxYyithZu%M(`ffN zt!=#AR2EDf3D1*j9{yaFjgEq*L4Rpr>IPp@q99R@x*S)wG%ti`bslv#w_LC3s=)Cu zvP*=Lm)J?8}7gMoKr?ZeT)lPDvW{Fs#YZf|my3Spo`R~9RtcKVHKGbz?O*-puOb-K)kzQIL<3*%rVoER~odfWbmbkrQhvL=mHo+B~>*>9bEw_9(%QiWQyms3Bzgj!%n7G2W zPeY+F&;moT;tqutcXt`wDKf>~y?BuVrO0&f;_g!1y;zGBcP|X?ZhQKE`z4!fHrZtN zpTi^*PUbx4kz0S)Qp|$=G(`PCFX2$-PkL;zqr@lmSKaj9nZ|}`+xO~|`RT-zE8j<# z9NFDv&k2$yy+#L4k9&UAZ1hBjJ(i!%M8x*%=0EQ+t$`1XulLF&y$EEml0o}}X{1s& zq8epVltMuK@|l(3p^?Y0iXRQwG8rqFpIwJNu+UWFH2xS@Z$(!B9z{m=E#gDB2H#|2 zNFxCyc8luTw{e2YMycJCoTEQ~5|yu_;2kIItk3;eyG1D&u-#>DIGkLpSM^kSqgSyw zl+$*`%A<&`ydX-FPF7>q1Dd`+4=k~s)tM-;8Y=ZQhjc$^PV(>l`5cAQ{t{q?3U%6g z_{JVo4bbllYVR^=>BJ}DtM~Sr2r_Q<^yj_}saI0=as6!4)mn+`(h#eaz~ya+DI-}| zvdI_(LIO@>#i4N!gaNL#)sj!sm+(d@1V^b;w?MJ9wobv%mH1X}%vZtx$}qniOV5$p zw!JozLFtoxK3cmLPYwP1xb?p!Q~7~kD?-}u8sp&Eiv@AXd9~HW`SxdtWr@sezZn^s z6(ZLi$<0vic>X&Uz)<4*O~RmHu*7cf@^$+CIw6ZWZIKT?aidH1cRi~})Ed5Y`C`p0 z6dEMj?q_76k`qziRbQ zY_@3lkQCfP?yVF5m>#8L{nB00o&TDjkDBxGkVD5#-ur+#KkxSEh57HPHq%!cU=CdS z!I&G^$)MQoIO~*WeV-ZO*eKkgqSWN?wPiqT)x%fn&vXp*Qp(G^I;{p9bd_dh-Mku7 zr~sI!n|{nLM7)@A-6!zJjeNM6Q#>0TQ&r&%G!eJAifLSs# z@6l`V_ov0Cxb#5f4yB(tckSTLm5|j;uTVllF>*%rQv#RTwFosEQ=e%Us~YjH)hT9z zCoj_nEoexLfrU3y*E4N5p#;zAAAC6DM3SO=XM-O2k*`su=VN*zxv1!IR(i9mr*^qc zu3~0X5@*!Dt1RI}AaxqP>L$l$DlZ9^XW-i$;7Qu|hdn4(O7IAl3*-7*;Gk0dmAT=x z)!#bvg8$XA8|ei3FFM#7(-h|83IE_FU+GaOGDwulp| z^M$rQ=J*Xj89BCi~w#a_256y*>&*;mP3+$(fFYaY>52 z0$ewF|17X813tg{8EsK)Hleh}QO~R?;!^)R z*8hKBdqL7LEp2T;6v`iRtw06pMt)6?5viI<3&kco2_%Y7O_ftCKf-VEsxfM^|Mue> zHBblq;>}O`zrC3euRjav4gw`$%2*!3s^aF{&a<<@!Ot*1k5@SC0W4pmj`1u*W#x;D zvv898J8D#1i-7$6(l>6~QeVmWf}AhA3C3tAbozpvjC@4>kEsV1E=CA=v=e{=cssr$ zFetbRNyzaTwWuiafC(Q3Dtw_ zoPPTmQ_RM;k8DQ_ zeCoUc!gaOqBS5nB`gU7;JHwjb``{oTnhSp?@NqLVGV=7oz$-V`Y|U;ue18mQ4Jg=D zBplw(e#~VYO)59U!DFfYUdlV;_t1wfN~Kzw$W~B}mA4BuX7{VxHMg;tayhByVSk|B zr$rFm;58hHe&P+e&Y__8Lk5P?&nZ~ z@Fj*Hm&fVH>*j^Ou%LinNJgWD6kb9e`$+VBPD>l*qLTn9PVa~PpF5<=88!;Xg;qjL z)%12XeSKL2gX_Wwx58Ly|Cgbi!@aXGLlpZL0u2CFYxsdfDT;z8N*oOMT6Ey7j;)(b zQTK0J+VKy|XogLmc9-`*)9uNemOSYj%{L>mv7rZ4FufXA3_q54@6x#JzGq}OqQ7uU z{sgBK)ATOw@b1~=%b<8-O+$ZBxK_A)Bf&Sp#c6F960ivHLX8{2@bhC2rMmM)uQPx# z8T=)wvdu(TT|y#Y7KV%(d>n$7m={Y)8= zL-S2no#9ogy_DgNjg4kk73hZb9cTU~HYV8g0GOFh8VTWsMJeJkUMm0qS;FKoU8UR} zGjz5!z^vbhfAp(n_Q2LBtTIq}+(}fZK$+I^5TDEY{1iP>gi)D6TbaYc^r%rQ%_E2^ zaG%>m&~Lq@e@ULo+SM5$skUOAp_mx)RkNSa)y>Vu!}aVGWP)657vWB|>AfESL@3i2 zX4sU-j(P`!b4$WETU#HNuUlD|S$Q2S>=))D#lfP~!VpXhEQ31FvlTZYfFT|9?k4ec zX`u5{8ZYOV>fX7pz!M?|)M^V#zS%XSkFQ!4Vq-D1lT#S?w@=%;V<^ZGDlQtqmwsl5h_Y^45Yj|ByfB!aHN zfNEl;k>%n$DmXvfxRZ_B6cE3n?}sSJVc zZ+K$j;nc**+5;(|cx#?6fpW{L$4yzym8HAn(Z%Sf`i_HBjR(f zq~?rRPB-8;O!RcJdTMXWk^*-7C-69zqZgD?66}86>Bt0uU=sy7E)DUdQf*_>$T+L^ zh;GQD&@l-zsL0Cp4X7C@MGZbj>g%AP$&HSF`JKm37DSF3T-yf#6JfXf@^0rcnL);2aIB!~&eODPgU zelR=DA0-vXk^LRd^m1U<@jV-*?-CymqGbg7IDqcQ0u_ptxn?}Q$7!+S*})*B#>zz{<^QRsyeOe#&66iTH`OyLR%j)nus z5^PGb{K^^E$zy6uO9zCN_g&j(_4-GDTX-(}?$i7)blG7WxVedm=Q`psBEs6}$&09R z5i$8kLs|K=ICwKwwrb}9z%TkCTNc^>G;k}H$D zswk;20IflsiKxL;fr7yY zjS`k5a5=e{^e`NADaI&LsXf1x20J%K&fD`QMStI`H*A&1eme;%DN{+TCV=JObT31fzI+^zEcjcDU>c)Sh%Mv_0Z<_DhDC!_$P_Y zf-v5k%)1-6$w|n@?d1-H3N&sG&bYd)A*$rzChh^lsL|+iOw6s1&u>Z(ms*D874bm9 z+*qOK;uv|MaCjUMTk@|Pnh`fE3rh&RA~@ z7lwr@e7zjBD^#FX78aHIEdm``NCif|H`wHhVuHM^w6wp5N>GBRP+i;4FmDOhYrN{wpXeK^B;n2{4b6v#o_`*`Nr;XV>vxrE~Y;T0SvaN+F zzJUW9#{K<`VvEd+@~vT$+svDqH7Q^K&%wJ3j?_BiSuI!nKU#X)QRLV@G*PqAU+hMY z7U4>PfQRLkbWJdqQLM<2W zQo-p3B`(A%@E%|9!-tBZtWJ}MYc?ZIjez^xgp9;QmMJRN6_Dj`JYjAweNr$NS_#R|&p#!5PtcR)rsZyEVUZs!tXMhe6?6n> zqF+78l@Nb5h}e0;YZO7G@g*1?!{4$*+v#SX?M&bK`%<0#I%rwo;D% z9wf!37GB)7ltT=$$-MlJ5z(UtY)1_^6rwla$0p@Hok+}6K$U2Z@93G0-OP0SjuVSf zot{x;enkaumx%p5&|dfB>3C4ns4pEkSNm_;3D2e^oU(KCed!QehAlVI24YE zi2Tv8_l{L1{rRh{R%>lb%jvnVGlHJhsx2yxEB@dSSv<2I!PNMals5YdhFP52*r4`| z_6$~PA2MNAK>&~5re|IDZ?#s*HNlErlUvltrW+nLEwR7=uXSGdy3(5|;Q%*r>>1ijV zrMX_*E|m*iW%9QgNJu;$M!SU?8&71+INj&un5vS^<(A~6#l^MQKGa)fdV6P?xK(Q-10V-V%F#(|E~0@u&6$BzX=ZBIh`|>wE-uy2 zu++F;TanLZp71bsl%&@+PWBWZU%n9eM= zVX5Wz+85yV8$fF0l{DHJJkuRx(a_Rzu4*_ipUW_ryK{^+ITRbIdHq3MTVH4EqL1yo zM-Cz3?u8gXV?)RM+}$qn1+oHk!9yn8>FH%O@iuyUN!UcJ$7`9)28E!&u@Uw1e6^R> zN@815GMJg3TLN zFtwDC2sUs2A?=}BbGd9*r?}?&>iiMq_kpnqnyG^Cu#&N}wYV{0!+2L_khSGL7d!$G z2@VdnWVpmVCD>#Up`m#Is1g+X?)O48F;Dyy!`LGpf@oV;lay?&?NduJ@;6Bt@6Y+4 zQvmVPl?5a)Lv?Gy7hJk$lT(ub^oE7H>koa9aGROwIyDgrUW;MObsN^c{gS$@zEA8g zTrmFakZNX!&+4Oj+5`wqgt@Y4w$Y;DE_a)EIn9t{u_LGarOc!=} z*>gwrX(QZ|?anLUKsk&+a%k}3#0~Un^g|;W@ta`cD%F?_e)O*A2zhh!-*5ub!2A23 zmS%bfA_bqbvd3b>$WkoO&+c$C$wa&}40{sxys*hd$_om{=O;HecNA9w@9B1*txJ#5 zUV5yGBM`NpCP~Ra$;LGpwNI!de)hH@A?om~p6;wv+4AAs%h=0L>!1-i5pmu z|5`ITdH#tC?QA8opaP$h7`xq!tQ0g_2ZRiAN13VAlf0~1%_I;Mog~KJMGuIdpIN9? zkV`!&|GRE#3N+O6@J{MhjO=d`;fMKwD21zV?k+zyigOXNLQ#Hbn65VfxE}sluYyV> z5g|lnm%w6&>geH;?T2TWVlJDVF_m8iH5sA+I!M#TE;fD4QlqcT8&vD@aShnppn+$u zkULK&OF_E%)+Pp2FZQ)n;|AAZLcS|Tx2KFDTeFlyV1S%4T-*YiuQLVG9g40B+^g7) znqAFQ<>@+yd zt*~C6BU&QI(D=WZZnU?4{Oe$2qoOD;fnL=nz!QzxeZK#5FT}T@`?aC?>RnkH8UJ?b z%*FhnIxSjHcv@JT8$hK4w7b&;z3mUaUwZO5v4mGtlq)kLfX1ZvI=+>j)Dc<%5)yvh zy4SG1q=bZ^407o**lEL&##!z>OYJ#oocs3u$1Z;T9^QnGEIJI-0h%u2Mz1FheGJsi zEY0H%jqU2%^Go>Oz3j7Y_D1Zo_v`z2ykk$$u^zcmAO=uw@W3Vzb|FBcP?4N$I z?%Px_DIlpEVxXZh6ac*Xw)xM_RlOy6eB1z{20Po-#)de4!uKNv;*b1DEYYO>Y{BWj zFvsc!5fbC^r}n4O`C#E7m5VL@pP(nDI7UH0dD(g(E8slWL;7M#1n^~6<1#W_uCMjv zIo|0X^Tn&C3Xjw#{2A9yJ#21{r5L<+$Ch@G`TUbH_8_6Oy#WCrN7CdqOeDVPoIS~L z1He`1XX3NZIM;4hajhxK9RMN7pFineeqCwwUja0F_tm8PdzDi*QB5YJ=DxN+$vfzY zxDVU*V!_p5$k{&)iHTD<$A3?ex$Z*k?FzCh3$wHP{^wI_GQV%a-Mo_+VSZa`eWlv{g$S1zdgo=rg+nQH*W@$Zulj9_ z`anG$TpYdqi!V!>9hZRo1ydnFSgDzNU*H>SL!Gvqm1o6j__;~?f;>vo>fwy*f(Y~` z4@SKnqR!60R=M10pm7>V9mXx(RJn_jy75yygfF4PIKDUVgYOM9^FR+jt3UP2b;tR7 zqQ{=qbuoMSCuM`HC<-yRl|yA%yG2b2&;s!e+Oz}h^i|`oMun%V{o=l0YQdhiHsrzqgznG({I%vgUR@KxE@a`e0F+IVyw zsb}XWZiGCMQ0g2P!?&8W?cv6cHw;k`08qCZv1}9r1+a6f24KwWUt7Xn&5MD2enOsm zuJ`9M^fJ$1tK=*tV$eD&@%e2YOE^F7&-#M}O*uI^d&1ZYrfgnP3OXnKTC1&n`I?oC z#}6z38u-sPh`8lg0@kBtCv_^16NWl@tza~TEbm>WHy03HHV5Nx0pTJ_ezAyn67Zm^#ZV0$PWm^FCA##_iTNf3X4^Ca6Tq(AR(FIas)zqOiW@x zkk_D&({g~e3cZ^c@uALULLoTS08CAfN~8@`!-tW+7|;XfA@+7$U8PVaL#6FWHSw_V zAe%$f2C6N;!h&pS2)nOIHuI>>xi~lg*hOiyMe|iMp`u801PbQ9|i92v&6tXeDVaR>J+m7fzoar?wb?allW-0c%bHzV7PSf=D0+>SNxs$@;C8K|t(~y_)@eKmZa`v7M9r-Rm;Uxu*Rk#Nv>b}f zxUl1<3lMWuJ)~0){jO(;zjKi>?t2Oh^-aO>fJj!iXaGZF=+xG6eZAn|C>y``7CiPy zC>T&#G^_r)JE4N?utE7!LBs5s3YXYZCv;(ka=F9*DT8G#lLjEJLV(h;6|YQD8C<{M z4!c~5X3dHH#9dYYd8RCf`;aa}xVZ7gcVVC2)x6F4tW`BEtc!0w=zl0o0UPfoKgp?~ z!gI6bt$S@9pyTy;8@-Z+?9YGiku#5cxf~)_mtGPCI2Xtg)Ie|h!SI5hXAPr&L>7SM zy1>N7xI5vh)8lHIXI&CD5aqhKw`}IUQf$F>1zg*jPxlTQScgGBGEK7Cz`cLtb?s{|+c!$*yMO!-`p5wyWOa3Q+DEz& zS+#P%czhdrW@ZH#fSdb5vt%bT`_v5V(DN!&Fj%wKirMrzM1-uRyNtDd`UPPnCddy5 z&s-?Ig!JWDi~G#PX-d~w3;gH&@8Nm&TI8xDQ>nf%@WgYpaQmgkSEgimcs-vLrzI)U z*KjB1g$!k6Qlt#*Miy+QD?A)fobb$~ZY}g~3uxW5=uRjvD+X(ckV#0??u-D=oby9v ztQ_a(R3ochEi84kUVP|&*`S{DLxc6oq0}s+2K?OJBl(dvkR?;EJUX5(j2BT`##gVm~?(JJSpv}4&E$vBAvv4=KTQUqyd=;&WNPWig^v`L^)O>`Grf>L} zrPK#2AwBP$i5^Hg1Gd7er?u(7`chKSQn8z!4ocJ*OLdCT9qaw0-(Y1X1HY=DJPK5% zSUfxsq~cl~81vn&F*Dp}GyiUfitNO@NoPMlIE0tJAgD~HsO~bXnpn7sO}FE5w+@G^&{hVKo8Iz~+*Mn;jv!D{l18)A&L_!n`CVoc zl$08&QA9kgHZFlt@S(bFH?6~+Jd6mGNAho)>Q)TW*$cyWf|9Kt(`>9pj6woU<)xHT zg{PY}(JKO$Y|g8I*WcMXH^J+$Amkm!rPT91i7lnFqCmd|`6aMg-iw}9@wWFIAg@=Y zD`B+~CtBz;(w*nFXB=idwqc;MELtBgbw{Ho*%eR>0_XDE@X*@!4D8g+H>pOWzkdCD zqqxfET1pl&77k~Yyv}wvzt85cvHy)j+5F%a#=E>=6(l5#Mu@b8mf&dnPBbpXyG1p) zt+*}(*z6F@U#R3a(C9HFz_`!;mun6(9e~2PwljToa@UjdDYB$m$IWjOUE({pWJ2C5 z495|NGVtbTjSB6%o$cXDOSCvR4}(@1BItFpTRO80(3SMqopju~7N3Pv$(zZ^wq7w2y++hGiaL8$HEax}lx6&Pv}$d!zf@%e+E|ghWO^I# zf_XaJ`|~HDa9u9s;q2jCR!|}-XmvE}Ca8N=r-Y`OMBqgQU(*>qeovS43CIgM7Wmo6Tk887;6MkIa%y4qpwzABZBNcC2Y(iJx4hfWRTM{y9GX$T zz8(1GE9`xOC@wT>U@g0(zT;&li$DhwMW=2H7u5T4M`8hJXrE`_>nSKIazHV{!#~Bz zM)CvnWgs(U$P&CocaQ$4i4rXNxa+8D^oE|^VrFhgY*pkY!4g|}Quv5OktC$*By+1o zl<{yT_zbi?M3Gud&NCr-88hEmM|y=#CYoPX28h+awayq_Kq_crMB{QAX{((h1HEz_ zuAifPrb2SFP3_vCAnJdjp`ugKB1JnQXkl*I^;bo%@VS&guks%b7kfhUBe7v`f9$2o z=bN}H-Pt0%nnJcJ!X+uZIKdGDH4InxrKEGMGG(c9TxVNDim62}&~gt2`9dG4i)w%t z6Als{8b*kB(~WM$a!E;<^ZubYH^=Oqs@sQ5sVlo6pHMgJ*x{j=W|dgm>EY5Ji=lCp zf)ZulftyvtCV8e$+SCs}f}O|Z*JGtN>1=)%ndr^U6^=p^;faT)c2eAuR3>!Ptk_V3 zQ#c3%9}pdt&l2Ygf4~AS-m1<_Jm`y4tSxp={=5C|{P5eix%2yDnP+Jc@*-`u-V1`a zM%%s54W0WoX(HZ;Zt(hUO`cYt0vhG=3i91DVb=EIue$o0H!f1IR-b{aWTdrzr=00h z`&^yjqzO1kDw9Jnx$ROjao5}j$RI%Qkt|eUCej>atWPL*(=Ot9m7mc z(pWXI=G0@W{=a7+nf%^#eQuaEhGy)ppdLc_h57n@{+>Wn(?(xZQBm2dIa5VztsXgu zBrVxtV)Y&j8cuHQ!VUZ5V52v8t~YXKIqHnC?O&q-$e?FuIPV*cW6Glmy6|XB-BSS! ztuB}ULn468J`QYhnz4K>VbuX@c$~O!?;uQ*34uMhEwaq)^N&>v6JF4rjHY!1XawZ`;B04 zuGLomhrXj}Xv0COZUZL=4Ge8v^?146Z4~R=`tmo^#UI){8&131JYWO)?fC%>Kon;I z4sZ3sg8(oP-Nl1VG0kBN)}DB_mP(;x`^olx?^oW9e1 z{TMZ976N z>S-R>3$%THSWhr;&`*U~iUb>=N}z_T$t|K?9-(9cyOHJg=Hz8IK~m?M7^=-K_a{v2 zhOzO-(UmMqP41Qa^v_zQgSyAZt>4&u-=(ARMGR1~uC1#{!ix@?Gf2+~_^Z%TGR zPQ?r|0V@qn)ehUlEDWk@;D~DThFt;ho&oWVUqe9jkt<+dp3>+kJT?Q1RLQ@uF~0)4 zt&j&6pO#Zvs$9vW#F9CeY%((eyjT*)=1_m z@JC+re>bT9SL5pc{_}bu5)#tWld);HH1GlKpACnCRO(nv?i&0NP=rQ8g2<>yS4bKM F{|^U`5K{mE literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-dark-desktop.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-dark-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..093a6c9c158d20ccea9876c54f8683f313fef473 GIT binary patch literal 149719 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

    qwid;$kk}P9YK!66gT?{mI_Y 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

    *&S5@i>+M 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 literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-dark-narrow.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-dark-narrow.png new file mode 100644 index 0000000000000000000000000000000000000000..d3dff97c0491027f974b725087ce0f1d297f6227 GIT binary patch literal 69438 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%0A?(Zxs>yGwdi1`F_xCr4IUnQ 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 G`ab}1^>N?; literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-desktop.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..500e102bb8fa103282435ec9d4fac960302b2bad GIT binary patch literal 148003 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[rYS1c{FnmIV%PF~g41nmI0JoUrK-&l#;4<+5b>&SB^H5B z9k-SCK0pkeRJrJc_TIe?1H!i4>D_2Rw(nLmrOFo6> z^?0=g=D!x7u!ymSo?hCCM!S@%Sdsl?t%qOm9g@n{(6(R7Mm{X?$(w<|S)>%_c?@MJ z2wwJqryU>nPe`Mr+?d1Mpv@TB`2dOEkWrm3SLbcYAa_gexE)<*Jxxqq&__$$ZgPe_ zfloej2C{EbSYmQCNvF}1GFa7t)?}q%^&v!R9COF$Z`qHAXK{*}MtSCngFr}Ky`WF` z-HXr@l88VfvqpyS4k$Y*4w|4q1Qd!4%hZ^3AhQonL79=;aBJ?Z@NC)xJB`%GzkgQ) z!w%5r1w#dvU7ULS*TCl8#I~z2-&Yt~(shN$s>}4kM}&VF9OH z;*sm>P^nfyOcjphvI}NIv^}(B(6qwdSmI6T?I6(`eb>T8-Bv>2VA}E^6I(q=SxcTY zQk;nJ4My3v@P;xE#$PecIY56sL{!8FC8)#_kP$Kg(-rV!DO7Ab6hDT{3Om;H5?M#Zn3k2=f!K;~w{z9DmbuR|NIDzFGrMrW9l!(~O6P9dqsoiy z$yjv3H0nk2Q)_EO;|ZsX6x*iJPu=}(DBm>(+%rt^6Gu7<3DWRA@exi@!Cap}S>nAZ zHMY)a(<&vE$eg&n+}k}&MpG)(PptKW&}?vF)l__ni^Lto0ymu_RS<4aB1Pb{7??Gn zq@)ZLUfxixTZ;j0N#**z2~`Kqb5OcV0(uv-c(*%^&2Z=^rcZQ!({U5A>yY%xchYis zitdQ>Eopn#f!6lcRHLR!G!^wh3FxO);1>IXONR5`8#;^8=#x8)`xH+#e;jqh_F7!Z zoP*SXv>FW+lP>Vo-0;v3=&3>Ax{EUs6p z&c1v;YGe`!Azgyn&SqO?tjFDn=clJ(2JT!=PV5?K7V(I1S3qbeP%n#!#t0(B9%TW< z&oEtJQRzTXnapFyL-)>kXG5>hkiH;Ky+I<|H|O^wqXt+x<9n)9)iiFqGhQDOfc*jJ zjJhQPW5eCAz&gwJOjACQt%NK9V+DmiuNsQr)kJXrtb*Do-!TrI@k7p-^p9z_j=}#z zIf1HMeIgOw zsuS$(t*vJSM4upJxQ{ncN2lu|Feia|0I(%Obai&l88t1Gz%0D}@UML7L##%W_ejQk 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 Q2(*9$6P3*yrUy#N3J literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-narrow.png b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/metricDetails.spec.ts-snapshots/metric-overview-narrow.png new file mode 100644 index 0000000000000000000000000000000000000000..5e5d547da094ea165c48d66d0c1c32000786779f GIT binary patch literal 68388 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 DA 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 literal 0 HcmV?d00001 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/metricDetails.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/metricDetails.spec.ts new file mode 100644 index 000000000000..9e16bfc2cdfe --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/metricDetails.spec.ts @@ -0,0 +1,742 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import { expect, Page, Route, test } from '@playwright/test'; +import { + FIXED_DATE, + gotoForScreenshot, + SCREENSHOT_OPTS, +} from '../../utils/visualRegression'; + +const METRIC_ID = '11111111-1111-4111-8111-111111111111'; +const METRIC_FQN = 'visual_gross_margin'; +const GROUP_ID = '22222222-2222-4222-8222-222222222222'; +const TABLE_ID = '33333333-3333-4333-8333-333333333333'; +const ADMIN_ID = '44444444-4444-4444-8444-444444444444'; +const FIXED_TIMESTAMP = FIXED_DATE.getTime(); + +const permissions = { + permissions: [ + 'Create', + 'Delete', + 'EditAll', + 'EditCustomFields', + 'EditDataProfile', + 'EditDescription', + 'EditDisplayName', + 'EditEntityRelationship', + 'EditLineage', + 'EditOwners', + 'EditQueries', + 'EditReviewers', + 'EditSampleData', + 'EditStatus', + 'EditTags', + 'ViewAll', + 'ViewBasic', + 'ViewDataProfile', + 'ViewQueries', + 'ViewSampleData', + 'ViewTests', + 'ViewUsage', + ].map((operation) => ({ access: 'allow', operation })), + resource: 'metric', +}; + +const owner = { + displayName: 'Finance Analytics', + fullyQualifiedName: 'finance_analytics', + id: '55555555-5555-4555-8555-555555555555', + name: 'finance_analytics', + type: 'team', +}; + +const reviewer = { + displayName: 'Platform Admin', + fullyQualifiedName: 'admin', + id: ADMIN_ID, + name: 'admin', + type: 'user', +}; + +const domain = { + displayName: 'Finance', + fullyQualifiedName: 'Finance', + id: '66666666-6666-4666-8666-666666666666', + name: 'Finance', + type: 'domain', +}; + +const metric = { + childrenCount: 2, + description: + 'Gross profit as a percentage of recognized revenue for the reporting period.', + displayName: 'Gross Margin', + domains: [domain], + entityStatus: 'In Review', + experts: [reviewer], + extension: { + businessCriticality: 'Board reporting', + targetRange: '70–90%', + }, + fullyQualifiedName: METRIC_FQN, + granularity: 'DAY', + id: METRIC_ID, + metricExpression: { + code: '(SUM(revenue) - SUM(cost_of_goods)) / SUM(revenue) * 100', + language: 'SQL', + }, + metricGroup: { + displayName: 'Profitability', + fullyQualifiedName: 'profitability', + id: GROUP_ID, + name: 'profitability', + type: 'metricGroup', + }, + metricType: 'PERCENTAGE', + name: METRIC_FQN, + owners: [owner], + relatedMetrics: [ + { + displayName: 'Net Revenue', + fullyQualifiedName: 'net_revenue', + id: '77777777-7777-4777-8777-777777777777', + name: 'net_revenue', + type: 'metric', + }, + ], + reviewers: [reviewer], + tags: [ + { + displayName: 'Tier 1', + labelType: 'Manual', + source: 'Classification', + state: 'Confirmed', + tagFQN: 'Tier.Tier1', + }, + { + displayName: 'Financial Reporting', + labelType: 'Manual', + source: 'Glossary', + state: 'Confirmed', + tagFQN: 'Financial Reporting', + }, + ], + unitOfMeasurement: 'PERCENTAGE', + updatedAt: FIXED_TIMESTAMP - 3_600_000, + updatedBy: 'finance.steward', + version: 1.4, +}; + +const groupedMetric = { + ...metric, + childrenCount: 1, + description: 'Primary profitability KPI reviewed by the finance team.', + entityStatus: 'Approved', + reviewers: [], +}; + +const standaloneMetric = { + childrenCount: 0, + description: 'Daily active customers with a settled transaction.', + displayName: 'Active Customers', + entityStatus: 'Approved', + fullyQualifiedName: 'active_customers', + granularity: 'DAY', + id: '88888888-8888-4888-8888-888888888888', + metricType: 'COUNT', + name: 'active_customers', + owners: [owner], + unitOfMeasurement: 'COUNT', + updatedAt: FIXED_TIMESTAMP - 7_200_000, +}; + +const table = { + columns: [ + { + dataType: 'NUMBER', + displayName: 'Revenue', + fullyQualifiedName: 'warehouse.finance.fact_orders.revenue', + name: 'revenue', + }, + { + dataType: 'NUMBER', + displayName: 'Cost of goods', + fullyQualifiedName: 'warehouse.finance.fact_orders.cost_of_goods', + name: 'cost_of_goods', + }, + ], + database: { + displayName: 'Analytics Warehouse', + id: 'database-id', + name: 'analytics_warehouse', + type: 'database', + }, + databaseSchema: { + displayName: 'Finance', + id: 'schema-id', + name: 'finance', + type: 'databaseSchema', + }, + description: 'Certified order facts used for finance reporting.', + displayName: 'Finance Orders', + domains: [domain], + fullyQualifiedName: 'warehouse.finance.fact_orders', + id: TABLE_ID, + name: 'fact_orders', + owners: [owner], + service: { + displayName: 'Warehouse', + id: 'service-id', + name: 'warehouse', + type: 'databaseService', + }, + tags: metric.tags, + tier: { + displayName: 'Tier 1', + tagFQN: 'Tier.Tier1', + }, + type: 'table', + usageSummary: { dailyStats: { count: 1284 } }, +}; + +const assetRelation = { + affectsHealth: true, + asset: { + displayName: table.displayName, + fullyQualifiedName: table.fullyQualifiedName, + id: TABLE_ID, + name: table.name, + type: 'table', + }, + direction: 'upstream', +}; + +const observability = { + assets: [ + { + asset: assetRelation.asset, + failed: 1, + health: 'AtRisk', + latestRunTime: FIXED_TIMESTAMP - 1_800_000, + passed: 5, + score: 83, + total: 6, + }, + ], + dimensions: [ + { + dimension: 'Completeness', + failed: 0, + passed: 3, + score: 100, + total: 3, + }, + { + dimension: 'Accuracy', + failed: 1, + passed: 2, + score: 67, + total: 3, + }, + ], + evaluatedAssetCount: 1, + evaluatedAt: FIXED_TIMESTAMP - 900_000, + health: 'AtRisk', + incidents: [ + { + asset: assetRelation.asset, + id: 'incident-1', + severity: 'Major', + status: 'Open', + testCase: { + displayName: 'Revenue within expected range', + id: 'test-accuracy', + name: 'revenue_expected_range', + type: 'testCase', + }, + timestamp: FIXED_TIMESTAMP - 1_800_000, + }, + ], + latestRunTime: FIXED_TIMESTAMP - 1_800_000, + linkedAssets: [assetRelation], + metric: { + displayName: metric.displayName, + fullyQualifiedName: METRIC_FQN, + id: METRIC_ID, + name: METRIC_FQN, + type: 'metric', + }, + partial: false, + reasonCode: 'AtRisk', + score: 83, + sourceCoverage: { + coveragePercent: 100, + partial: false, + restrictedTables: 0, + testedTables: 1, + upstreamTables: 1, + visibleTables: 1, + }, + statusCounts: { + aborted: 0, + failed: 1, + missing: 0, + passed: 5, + queued: 0, + terminal: 6, + }, + tests: [ + { + asset: assetRelation.asset, + dimension: 'Completeness', + status: 'Success', + testCase: { + displayName: 'Revenue is complete', + id: 'test-completeness', + name: 'revenue_not_null', + type: 'testCase', + }, + timestamp: FIXED_TIMESTAMP - 1_800_000, + }, + { + asset: assetRelation.asset, + dimension: 'Accuracy', + status: 'Failed', + testCase: { + displayName: 'Revenue within expected range', + id: 'test-accuracy', + name: 'revenue_expected_range', + type: 'testCase', + }, + timestamp: FIXED_TIMESTAMP - 1_800_000, + }, + ], + upstreamAssetCount: 1, +}; + +const approvalTask = { + about: `<#E::metric::${METRIC_FQN}>`, + assignees: [reviewer], + availableTransitions: [ + { + displayName: 'Approve', + id: 'approve-transition', + name: 'approve', + resolutionType: 'Approved', + }, + { + displayName: 'Reject', + id: 'reject-transition', + name: 'reject', + resolutionType: 'Rejected', + }, + ], + category: 'Approval', + createdAt: FIXED_TIMESTAMP - 7_200_000, + createdBy: { + displayName: 'Finance Steward', + id: 'steward-id', + name: 'finance.steward', + type: 'user', + }, + displayName: 'Review Gross Margin', + id: 'approval-task-1', + name: 'review_gross_margin', + priority: 'High', + reviewers: [reviewer], + status: 'Open', + taskId: 41, + type: 'RequestApproval', + updatedAt: FIXED_TIMESTAMP - 3_600_000, +}; + +const fulfillJson = (route: Route, body: unknown, status = 200) => + route.fulfill({ + body: JSON.stringify(body), + contentType: 'application/json', + status, + }); + +const setupMetricRoutes = async (page: Page) => { + const storageState = (await page + .context() + .storageState({ indexedDB: true })) as unknown as { + origins: Array<{ + indexedDB?: Array<{ + stores: Array<{ + records: Array<{ key: string; value: string }>; + }>; + }>; + localStorage: Array<{ name: string; value: string }>; + }>; + }; + const authOrigin = storageState.origins.find( + ({ indexedDB }) => indexedDB?.length + ); + const authenticatedStorage = (authOrigin?.localStorage ?? []).filter( + ({ name }) => ['loggedInUsers', 'omAppModeHint'].includes(name) + ); + const appState = authOrigin?.indexedDB + ?.flatMap(({ stores }) => stores) + .flatMap(({ records }) => records) + .find(({ key }) => key === 'app_state')?.value; + + expect( + appState, + 'admin storage state must contain the auth token' + ).toBeTruthy(); + + // The isolated Vite port has a different origin from the persisted admin session. + await page.route('**/__metric-visual-auth', (route) => + route.fulfill({ body: 'Metric visual auth' }) + ); + await page.goto('/__metric-visual-auth'); + await page.evaluate( + async ({ entries, tokenState }) => { + entries.forEach(({ name, value }) => localStorage.setItem(name, value)); + localStorage.removeItem('user-preferences-store'); + await new Promise((resolve, reject) => { + const request = indexedDB.open('AppDataStore', 1); + + request.onupgradeneeded = () => { + if (!request.result.objectStoreNames.contains('keyValueStore')) { + request.result.createObjectStore('keyValueStore'); + } + }; + request.onerror = () => reject(request.error); + request.onsuccess = () => { + const database = request.result; + const transaction = database.transaction( + 'keyValueStore', + 'readwrite' + ); + + transaction.objectStore('keyValueStore').put(tokenState, 'app_state'); + transaction.onerror = () => reject(transaction.error); + transaction.oncomplete = () => { + database.close(); + resolve(); + }; + }; + }); + }, + { entries: authenticatedStorage, tokenState: appState } + ); + await page.unroute('**/__metric-visual-auth'); + await page.route('**/api/v1/**', async (route) => { + const request = route.request(); + const url = new URL(request.url()); + const path = url.pathname; + + if (path === '/api/v1/permissions/metric') { + return fulfillJson(route, permissions); + } + if (path === `/api/v1/permissions/metric/name/${METRIC_FQN}`) { + return fulfillJson(route, permissions); + } + if (path === '/api/v1/metrics/hierarchy') { + return fulfillJson(route, { + data: [ + { + group: { + description: 'Board-level profitability and margin metrics.', + displayName: 'Profitability', + entityStatus: 'Approved', + fullyQualifiedName: 'profitability', + id: GROUP_ID, + metricCount: 1, + name: 'profitability', + owners: [owner], + updatedAt: FIXED_TIMESTAMP - 3_600_000, + }, + kind: 'metricGroup', + }, + { kind: 'metric', metric: standaloneMetric }, + ], + paging: { limit: 20, offset: 0, total: 2 }, + }); + } + if (path === `/api/v1/metricGroups/${GROUP_ID}/metrics`) { + return fulfillJson(route, { + data: [groupedMetric], + paging: { limit: 25, offset: 0, total: 1 }, + }); + } + if (path === `/api/v1/metrics/name/${METRIC_FQN}`) { + return fulfillJson(route, metric); + } + if (path === `/api/v1/metrics/${METRIC_ID}/hierarchy`) { + return fulfillJson(route, { + ancestors: [ + { + description: 'All margin measures.', + displayName: 'Margin', + entityStatus: 'Approved', + fullyQualifiedName: 'margin', + id: 'ancestor-metric', + name: 'margin', + }, + ], + children: [ + { + displayName: 'Gross Margin — Americas', + entityStatus: 'Approved', + fullyQualifiedName: 'gross_margin_americas', + id: 'child-americas', + name: 'gross_margin_americas', + owners: [owner], + }, + { + displayName: 'Gross Margin — EMEA', + entityStatus: 'Draft', + fullyQualifiedName: 'gross_margin_emea', + id: 'child-emea', + name: 'gross_margin_emea', + owners: [owner], + }, + ], + childrenPaging: { limit: 25, offset: 0, total: 2 }, + current: metric, + group: { + description: 'Board-level profitability and margin metrics.', + displayName: 'Profitability', + fullyQualifiedName: 'profitability', + id: GROUP_ID, + metricCount: 4, + name: 'profitability', + }, + siblingPaging: { limit: 25, offset: 0, total: 2 }, + siblings: [ + metric, + { + displayName: 'Contribution Margin', + entityStatus: 'Approved', + fullyQualifiedName: 'contribution_margin', + id: 'sibling-metric', + name: 'contribution_margin', + owners: [owner], + }, + ], + }); + } + if (path === `/api/v1/metrics/${METRIC_ID}/assets`) { + return fulfillJson(route, { + data: [assetRelation], + paging: { limit: 10, offset: 0, total: 1 }, + }); + } + if (path.endsWith('/observability') && path.includes('/api/v1/metrics/')) { + return fulfillJson(route, observability); + } + if (path === `/api/v1/tables/name/${table.fullyQualifiedName}`) { + return fulfillJson(route, table); + } + if (path === '/api/v1/lineage/getLineage') { + return fulfillJson(route, { + downstreamEdges: [], + entity: { id: METRIC_ID, type: 'metric' }, + nodes: [], + upstreamEdges: [ + { + fromEntity: TABLE_ID, + lineageDetails: { + columnsLineage: [ + { + fromColumns: [ + `${table.fullyQualifiedName}.revenue`, + `${table.fullyQualifiedName}.cost_of_goods`, + ], + toColumn: `${METRIC_FQN}.gross_margin`, + }, + ], + }, + toEntity: METRIC_ID, + }, + ], + }); + } + if (path === '/api/v1/feed/count') { + return fulfillJson(route, { + data: [ + { + conversationCount: 0, + count: 0, + entityLink: `<#E::metric::${METRIC_FQN}>`, + mentionCount: 0, + }, + ], + }); + } + if (path === '/api/v1/feed') { + return fulfillJson(route, { data: [], paging: { total: 0 } }); + } + if (path === `/api/v1/activity/entity/metric/name/${METRIC_FQN}`) { + return fulfillJson(route, { data: [], paging: { total: 0 } }); + } + if (path === '/api/v1/tasks/count') { + return fulfillJson(route, { completed: 2, open: 1, total: 3 }); + } + if (path === '/api/v1/tasks') { + const isApproval = url.searchParams.get('type') === 'RequestApproval'; + + return fulfillJson(route, { + data: isApproval ? [approvalTask] : [], + paging: { limit: 100, total: isApproval ? 1 : 0 }, + }); + } + if (path === '/api/v1/governance/workflowInstances') { + return fulfillJson(route, { data: [], paging: { limit: 100, total: 0 } }); + } + if (path === '/api/v1/users/name/admin') { + return fulfillJson(route, { + displayName: 'Platform Admin', + email: 'admin@open-metadata.org', + fullyQualifiedName: 'admin', + id: ADMIN_ID, + isAdmin: true, + name: 'admin', + teams: [], + }); + } + + return route.continue(); + }); +}; + +const maskVolatileChrome = (page: Page) => [ + page.locator('.Toastify__toast-container'), + page.locator('[data-testid="global-search-suggestions"]'), +]; + +const expectMetricScreenshot = async ( + page: Page, + name: string, + viewport: 'desktop' | 'narrow' +) => { + await page.evaluate(() => window.scrollTo(0, 0)); + await expect.poll(() => page.evaluate(() => window.scrollY)).toBe(0); + await page.evaluate(async () => { + await document.fonts.ready; + }); + await expect(page).toHaveScreenshot(`metric-${name}-${viewport}.png`, { + ...SCREENSHOT_OPTS, + mask: maskVolatileChrome(page), + }); +}; + +const captureMetricScreens = async ( + page: Page, + viewport: 'desktop' | 'narrow' +) => { + await setupMetricRoutes(page); + + await gotoForScreenshot(page, '/metrics'); + await expect(page.getByTestId('metric-list-page')).toBeVisible(); + if (viewport === 'narrow') { + await page.getByTestId('sidebar-toggle').click(); + await expect(page.getByTestId('left-sidebar')).toHaveCSS('width', '72px'); + } + await page.getByRole('radio', { name: 'Card' }).click(); + const metricCardView = page.getByTestId('metric-card-view'); + + await expect(metricCardView).toBeVisible(); + await expect( + metricCardView.getByText('Gross Margin', { exact: true }) + ).toBeVisible(); + await expectMetricScreenshot(page, 'list', viewport); + + await gotoForScreenshot(page, `/metric/${METRIC_FQN}`); + await expect(page.getByTestId('metric-details-page')).toBeVisible(); + await expect(page.getByTestId('metric-hierarchy-card')).toBeVisible(); + if (viewport === 'narrow') { + await expect( + page + .getByTestId('metric-breadcrumbs') + .getByRole('link', { name: 'Profitability' }) + ).toBeHidden(); + } + await expectMetricScreenshot(page, 'overview', viewport); + + await page.getByRole('tab', { name: /^Assets/ }).click(); + await expect(page.getByTestId('metric-assets-tab')).toBeVisible(); + await expect(page.getByTestId(`metric-asset-card-${TABLE_ID}`)).toBeVisible(); + const assetActivator = page.getByTestId(`metric-asset-activate-${TABLE_ID}`); + + if (viewport === 'narrow') { + await assetActivator.evaluate((element: HTMLButtonElement) => + element.click() + ); + } else { + await assetActivator.click(); + } + await expect(page.getByTestId('metric-asset-summary')).toBeVisible(); + await expectMetricScreenshot(page, 'assets', viewport); + if (viewport === 'narrow') { + await page + .getByTestId('metric-asset-summary-drawer-header') + .getByRole('button', { name: 'Close' }) + .click(); + await expect(page.getByRole('dialog')).toBeHidden(); + } + + await page.getByRole('tab', { name: 'Observability' }).click(); + await expect(page.getByTestId('metric-observability-tab')).toBeVisible(); + await expect(page.getByTestId('metric-health-summary')).toContainText('83%'); + await expectMetricScreenshot(page, 'observability', viewport); + + await page.getByRole('tab', { name: /^Activity & Tasks/ }).click(); + await expect(page.getByTestId('metric-activity-tab')).toBeVisible(); + await expect(page.getByTestId('metric-activity-new-comment')).toBeVisible(); + await expectMetricScreenshot(page, 'activity', viewport); + + await page.getByRole('tab', { name: 'Approval Workflow' }).click(); + await expect(page.getByTestId('metric-approval-tab')).toBeVisible(); + await expect(page.getByTestId('metric-approval-history')).toBeVisible(); + await expectMetricScreenshot(page, 'approval', viewport); +}; + +const captureDarkMetricOverview = async ( + page: Page, + viewport: 'desktop' | 'narrow' +) => { + await page.addInitScript(() => localStorage.setItem('ui-theme', 'dark')); + await setupMetricRoutes(page); + await gotoForScreenshot(page, `/metric/${METRIC_FQN}`); + await expect(page.getByTestId('metric-details-page')).toBeVisible(); + if (viewport === 'narrow') { + await page.getByTestId('sidebar-toggle').click(); + await expect(page.getByTestId('left-sidebar')).toHaveCSS('width', '72px'); + } + await expect(page.getByTestId('metric-hierarchy-card')).toBeVisible(); + await expect(page.locator('html')).toHaveClass(/dark-mode/); + await expectMetricScreenshot(page, 'overview-dark', viewport); +}; + +test('Metric surfaces match desktop baselines', async ({ page }) => { + await page.setViewportSize({ height: 900, width: 1440 }); + await captureMetricScreens(page, 'desktop'); +}); + +test('Metric surfaces match narrow baselines', async ({ page }) => { + await page.setViewportSize({ height: 900, width: 390 }); + await captureMetricScreens(page, 'narrow'); +}); + +test('Metric overview matches dark desktop and narrow baselines', async ({ + page, +}) => { + await page.setViewportSize({ height: 900, width: 1440 }); + await captureDarkMetricOverview(page, 'desktop'); + await page.setViewportSize({ height: 900, width: 390 }); + await captureDarkMetricOverview(page, 'narrow'); +}); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MetricClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MetricClass.ts index 91a09e025194..8dda2c6fe9fe 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MetricClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MetricClass.ts @@ -10,18 +10,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { APIRequestContext, Page } from '@playwright/test'; +import { APIRequestContext, expect, Page } from '@playwright/test'; import { Operation } from 'fast-json-patch'; import { createOrFetch, okJson, withNotFoundRetry, } from '../../utils/apiResponse'; -import { uuid } from '../../utils/common'; +import { getApiContext, uuid } from '../../utils/common'; +import { + CustomProperty, + setMetricCustomPropertyValue, +} from '../../utils/customProperty'; import { visitEntityPageByFqn } from '../../utils/entity'; +import { + expectMetricMetadataSelections, + openMetricMetadataEditor, + saveMetricMetadata, + setMetricMetadataReferenceSelection, +} from '../../utils/metricMetadata'; +import { DataProduct } from '../domain/DataProduct'; +import { Domain } from '../domain/Domain'; +import { GlossaryTerm } from '../glossary/GlossaryTerm'; +import { TagClass } from '../tag/TagClass'; import { EntityTypeEndpoint, ResponseDataType } from './Entity.interface'; import { EntityClass } from './EntityClass'; +interface MetadataSelectionAction { + groupName: string; + isSelected: boolean; + referenceName: string; +} + +interface MetadataSelectionExpectation { + excluded?: string[]; + groupName: string; + included: string[]; +} + export class MetricClass extends EntityClass { private metricName: string; @@ -154,6 +180,484 @@ export class MetricClass extends EntityClass { }); } + async updateCustomProperty( + page: Page, + propertydetails: CustomProperty, + value: string + ) { + await setMetricCustomPropertyValue({ + page, + propertyName: propertydetails.name, + value, + }); + } + + private getMetricId() { + const metricId = this.entityResponseData.id; + if (!metricId) { + throw new Error('Metric must be created before editing its metadata'); + } + + return metricId; + } + + private async updateMetadataSelections( + page: Page, + actions: MetadataSelectionAction[], + expectations: MetadataSelectionExpectation[] + ) { + const dialog = await openMetricMetadataEditor(page); + + for (const action of actions) { + await setMetricMetadataReferenceSelection( + dialog, + action.groupName, + action.referenceName, + action.isSelected + ); + } + for (const expectation of expectations) { + const group = dialog.getByRole('group', { + exact: true, + name: expectation.groupName, + }); + await expectMetricMetadataSelections( + group, + expectation.included, + expectation.excluded + ); + } + + await saveMetricMetadata(page, dialog, this.getMetricId()); + } + + async updateOwnerSelection({ + page, + added = [], + removed = [], + included, + }: { + page: Page; + added?: string[]; + removed?: string[]; + included: string[]; + }) { + await this.updateMetadataSelections( + page, + [ + ...removed.map((referenceName) => ({ + groupName: 'Owners', + isSelected: false, + referenceName, + })), + ...added.map((referenceName) => ({ + groupName: 'Owners', + isSelected: true, + referenceName, + })), + ], + [ + { + excluded: removed, + groupName: 'Owners', + included, + }, + ] + ); + + const peopleCard = page.getByTestId('metric-metadata-people-card'); + for (const ownerName of included) { + await expect(peopleCard).toContainText(ownerName); + } + for (const ownerName of removed) { + await expect(peopleCard).not.toContainText(ownerName); + } + } + + async domain( + page: Page, + domain1: Domain['responseData'], + domain2: Domain['responseData'], + dataProduct1: DataProduct['responseData'], + dataProduct2: DataProduct['responseData'], + dataProduct3: DataProduct['responseData'] + ) { + const domain1Name = domain1.displayName; + const domain2Name = domain2.displayName; + const dataProduct1Name = dataProduct1.displayName; + const dataProduct2Name = dataProduct2.displayName; + const dataProduct3Name = dataProduct3.displayName; + const metadataRail = page.getByTestId('metric-metadata-rail'); + + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Domains', + isSelected: true, + referenceName: domain1Name, + }, + { + groupName: 'Data Products', + isSelected: true, + referenceName: dataProduct1Name, + }, + ], + [ + { groupName: 'Domains', included: [domain1Name] }, + { groupName: 'Data Products', included: [dataProduct1Name] }, + ] + ); + await expect(metadataRail).toContainText(domain1Name); + await expect(metadataRail).toContainText(dataProduct1Name); + + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Data Products', + isSelected: false, + referenceName: dataProduct1Name, + }, + { + groupName: 'Data Products', + isSelected: true, + referenceName: dataProduct2Name, + }, + ], + [ + { + excluded: [dataProduct1Name], + groupName: 'Data Products', + included: [dataProduct2Name], + }, + ] + ); + await expect(metadataRail).not.toContainText(dataProduct1Name); + await expect(metadataRail).toContainText(dataProduct2Name); + + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Data Products', + isSelected: false, + referenceName: dataProduct2Name, + }, + { + groupName: 'Domains', + isSelected: false, + referenceName: domain1Name, + }, + { + groupName: 'Domains', + isSelected: true, + referenceName: domain2Name, + }, + { + groupName: 'Data Products', + isSelected: true, + referenceName: dataProduct3Name, + }, + ], + [ + { + excluded: [domain1Name], + groupName: 'Domains', + included: [domain2Name], + }, + { + excluded: [dataProduct2Name], + groupName: 'Data Products', + included: [dataProduct3Name], + }, + ] + ); + await expect(metadataRail).not.toContainText(domain1Name); + await expect(metadataRail).toContainText(domain2Name); + await expect(metadataRail).not.toContainText(dataProduct2Name); + await expect(metadataRail).toContainText(dataProduct3Name); + + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Data Products', + isSelected: false, + referenceName: dataProduct3Name, + }, + { + groupName: 'Domains', + isSelected: false, + referenceName: domain2Name, + }, + ], + [ + { excluded: [domain2Name], groupName: 'Domains', included: [] }, + { + excluded: [dataProduct3Name], + groupName: 'Data Products', + included: [], + }, + ] + ); + await expect(metadataRail).not.toContainText(domain2Name); + await expect(metadataRail).not.toContainText(dataProduct3Name); + } + + async owner( + page: Page, + owner1: string[], + owner2: string[], + _type: 'Teams' | 'Users' = 'Users', + isEditPermission = true + ) { + await this.updateOwnerSelection({ + added: owner1, + included: owner1, + page, + }); + if (!isEditPermission) { + return; + } + + await this.updateOwnerSelection({ + added: owner2, + included: owner2, + page, + removed: owner1, + }); + await this.updateOwnerSelection({ + included: [], + page, + removed: owner2, + }); + } + + async tier(page: Page, tier1: string, tier2: string) { + const governanceCard = page.getByTestId('metric-metadata-governance-card'); + await this.updateMetadataSelections( + page, + [{ groupName: 'Tier', isSelected: true, referenceName: tier1 }], + [{ groupName: 'Tier', included: [tier1] }] + ); + await expect(governanceCard).toContainText(tier1); + + await this.updateMetadataSelections( + page, + [{ groupName: 'Tier', isSelected: true, referenceName: tier2 }], + [{ excluded: [tier1], groupName: 'Tier', included: [tier2] }] + ); + await expect(governanceCard).not.toContainText(tier1); + await expect(governanceCard).toContainText(tier2); + + await this.updateMetadataSelections( + page, + [{ groupName: 'Tier', isSelected: false, referenceName: tier2 }], + [{ excluded: [tier2], groupName: 'Tier', included: [] }] + ); + await expect(governanceCard).not.toContainText(tier2); + } + + async descriptionUpdate(page: Page) { + const description = `Updated metric description ${uuid()}`; + await this.patchFromPage(page, [ + { op: 'replace', path: '/description', value: description }, + ]); + await page.reload(); + await expect(page.getByTestId('metric-header-description')).toHaveText( + description + ); + await expect(page.getByTestId('edit-description')).toHaveCount(0); + } + + async tag( + page: Page, + tag1: string, + tag2: string, + _entity: EntityClass, + _tag2Fqn?: string + ) { + const tag1Name = tag1.split('.').at(-1) ?? tag1; + const taxonomyCard = page.getByTestId('metric-metadata-taxonomy-card'); + await this.updateMetadataSelections( + page, + [{ groupName: 'Tags', isSelected: true, referenceName: tag1Name }], + [{ groupName: 'Tags', included: [tag1Name] }] + ); + await expect(taxonomyCard).toContainText(tag1Name); + + await this.updateMetadataSelections( + page, + [{ groupName: 'Tags', isSelected: true, referenceName: tag2 }], + [{ groupName: 'Tags', included: [tag1Name, tag2] }] + ); + await expect(taxonomyCard).toContainText(tag1Name); + await expect(taxonomyCard).toContainText(tag2); + + await this.updateMetadataSelections( + page, + [ + { groupName: 'Tags', isSelected: false, referenceName: tag1Name }, + { groupName: 'Tags', isSelected: false, referenceName: tag2 }, + ], + [{ excluded: [tag1Name, tag2], groupName: 'Tags', included: [] }] + ); + await expect(taxonomyCard).not.toContainText(tag1Name); + await expect(taxonomyCard).not.toContainText(tag2); + } + + async glossaryTerm( + page: Page, + glossaryTerm1: GlossaryTerm['responseData'], + glossaryTerm2: GlossaryTerm['responseData'] + ) { + const glossaryTerm1Name = glossaryTerm1.displayName; + const glossaryTerm2Name = glossaryTerm2.displayName; + const taxonomyCard = page.getByTestId('metric-metadata-taxonomy-card'); + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Glossary Terms', + isSelected: true, + referenceName: glossaryTerm1Name, + }, + ], + [{ groupName: 'Glossary Terms', included: [glossaryTerm1Name] }] + ); + await expect(taxonomyCard).toContainText(glossaryTerm1Name); + + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Glossary Terms', + isSelected: true, + referenceName: glossaryTerm2Name, + }, + ], + [ + { + groupName: 'Glossary Terms', + included: [glossaryTerm1Name, glossaryTerm2Name], + }, + ] + ); + await expect(taxonomyCard).toContainText(glossaryTerm1Name); + await expect(taxonomyCard).toContainText(glossaryTerm2Name); + + await this.updateMetadataSelections( + page, + [ + { + groupName: 'Glossary Terms', + isSelected: false, + referenceName: glossaryTerm1Name, + }, + { + groupName: 'Glossary Terms', + isSelected: false, + referenceName: glossaryTerm2Name, + }, + ], + [ + { + excluded: [glossaryTerm1Name, glossaryTerm2Name], + groupName: 'Glossary Terms', + included: [], + }, + ] + ); + await expect(taxonomyCard).not.toContainText(glossaryTerm1Name); + await expect(taxonomyCard).not.toContainText(glossaryTerm2Name); + } + + async certification( + page: Page, + _certification1: TagClass, + _certification2: TagClass + ) { + const dialog = await openMetricMetadataEditor(page); + await expect( + dialog.getByRole('group', { exact: true, name: 'Certification' }) + ).toHaveCount(0); + await dialog.getByRole('button', { exact: true, name: 'Cancel' }).click(); + await expect(dialog).toBeHidden(); + } + + async followUnfollowEntity(page: Page, _entity: string) { + const metricPath = `/api/v1/metrics/${this.getMetricId()}/followers`; + const followButton = page.getByRole('button', { + exact: true, + name: 'Follow', + }); + const followingButton = page.getByRole('button', { + exact: true, + name: 'Following', + }); + + if (await followingButton.isVisible()) { + const resetResponse = page.waitForResponse( + (response) => + response.request().method() === 'DELETE' && + new URL(response.url()).pathname.startsWith(metricPath) + ); + await followingButton.click(); + expect((await resetResponse).ok()).toBeTruthy(); + await expect(followButton).toBeVisible(); + } + + const followResponse = page.waitForResponse( + (response) => + response.request().method() === 'PUT' && + new URL(response.url()).pathname === metricPath + ); + await followButton.click(); + expect((await followResponse).ok()).toBeTruthy(); + await expect(followingButton).toBeVisible(); + + const unfollowResponse = page.waitForResponse( + (response) => + response.request().method() === 'DELETE' && + new URL(response.url()).pathname.startsWith(metricPath) + ); + await followingButton.click(); + expect((await unfollowResponse).ok()).toBeTruthy(); + await expect(followButton).toBeVisible(); + } + + async renameEntity(page: Page, entityName: string) { + const displayName = `Playwright ${entityName} updated`; + await this.patchFromPage(page, [ + { op: 'replace', path: '/displayName', value: displayName }, + ]); + await page.reload(); + await expect( + page.getByRole('heading', { exact: true, name: displayName }) + ).toBeVisible(); + await expect(page.getByTestId('rename-button')).toHaveCount(0); + } + + private async patchFromPage(page: Page, patchData: Operation[]) { + const { afterAction, apiContext } = await getApiContext(page); + try { + const response = await apiContext.patch( + `/api/v1/metrics/${this.getMetricId()}`, + { + data: patchData, + headers: { + 'Content-Type': 'application/json-patch+json', + }, + } + ); + expect(response.ok()).toBeTruthy(); + this.entityResponseData = await response.json(); + } finally { + await afterAction(); + } + } + async delete(apiContext: APIRequestContext) { const entityResponse = await apiContext.delete( `/api/v1/metrics/${this.entityResponseData?.['id']}?recursive=true&hardDelete=true` diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts index c974dbf2b67b..e91a3a3e0f64 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/customProperty.ts @@ -72,6 +72,70 @@ export interface CustomProperty { }; } +const parseMetricExtension = (value: string): Record => { + const extension: unknown = JSON.parse(value); + + if ( + extension === null || + typeof extension !== 'object' || + Array.isArray(extension) + ) { + throw new Error('Metric extension must be a JSON object'); + } + + return extension as Record; +}; + +export const setMetricCustomPropertyValue = async ({ + page, + propertyName, + value, +}: { + page: Page; + propertyName: string; + value: string; +}) => { + await page.getByTestId('edit-metric-metadata').click(); + + const dialog = page.getByTestId('metric-metadata-edit-dialog'); + const extensionInput = dialog + .getByTestId('metric-extension-json') + .getByRole('textbox'); + + await expect(dialog).toBeVisible(); + await expect(extensionInput).toBeVisible(); + + const currentExtension = parseMetricExtension( + await extensionInput.inputValue() + ); + const updatedExtension = { + ...currentExtension, + [propertyName]: value, + }; + + await extensionInput.fill(JSON.stringify(updatedExtension, null, 2)); + + const patchRequest = page.waitForResponse( + (response) => + response.url().includes('/api/v1/metrics/') && + response.request().method() === 'PATCH' + ); + + await dialog.getByTestId('save-metric-metadata').click(); + + const patchResponse = await patchRequest; + const responseBody = await patchResponse.json(); + + expect(patchResponse.status()).toBe(200); + expect(responseBody).toMatchObject({ + extension: updatedExtension, + }); + await expect(dialog).toBeHidden(); + await expect( + page.getByTestId(`metric-custom-property-${propertyName}`) + ).toContainText(value); +}; + export const fillTableColumnInputDetails = async ( page: Page, text: string, diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts index 893019eb0096..ffa907853a4b 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts @@ -1983,6 +1983,25 @@ export const checkForEditActions = async ({ entityType: string; deleted?: boolean; }) => { + if (entityType === EntityTypeEndpoint.METRIC) { + await expect(page.getByTestId('manage-button')).toBeVisible(); + await expect(page.getByRole('button', { name: 'Share' })).toBeVisible(); + + if (deleted) { + await expect( + page.getByRole('button', { name: /Follow(?:ing)?/ }) + ).not.toBeVisible(); + await expect(page.getByTestId('edit-metric-metadata')).not.toBeVisible(); + } else { + await expect( + page.getByRole('button', { name: /Follow(?:ing)?/ }) + ).toBeEnabled(); + await expect(page.getByTestId('edit-metric-metadata')).toBeVisible(); + } + + return; + } + for (const { containerSelector, elementSelector, @@ -2130,6 +2149,20 @@ export const deletedEntityCommonChecks = async ({ await page.click('[data-testid="manage-button"]'); + if (endPoint === EntityTypeEndpoint.METRIC) { + await expect(page.getByTestId('delete-button')).toBeVisible(); + if (deleted) { + await expect(page.getByTestId('restore-button')).toBeVisible(); + await expect(page.getByTestId('version-button')).not.toBeVisible(); + } else { + await expect(page.getByTestId('restore-button')).not.toBeVisible(); + await expect(page.getByTestId('version-button')).toBeVisible(); + } + await clickOutside(page); + + return; + } + if (deleted) { // only two menu options (restore and delete) should be present await expect( diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/entityPermissionUtils.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/entityPermissionUtils.ts index 46e8a56cffed..e5ebb695a6dc 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/entityPermissionUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/entityPermissionUtils.ts @@ -202,21 +202,29 @@ export const testCommonOperations = async ( await entity.visitEntityPage(testUserPage); // Define test configurations with special handling - const testIdsConfigs = [ - { testId: 'edit-description', type: 'direct' }, - { - testId: 'add-tag', - type: 'multiple-containers', - containers: ['tags-container', 'glossary-container'], - }, - { testId: 'edit-tier', type: 'direct' }, - { testId: 'edit-owner', type: 'direct' }, - { testId: 'rename-button', type: 'with-manage-button' }, - { testId: 'delete-button', type: 'with-manage-button' }, - ]; + const isMetric = entity instanceof MetricClass; + const testIdsConfigs = isMetric + ? [ + { testId: 'edit-metric-metadata', type: 'direct' }, + { testId: 'delete-button', type: 'with-manage-button' }, + ] + : [ + { testId: 'edit-description', type: 'direct' }, + { + testId: 'add-tag', + type: 'multiple-containers', + containers: ['tags-container', 'glossary-container'], + }, + { testId: 'edit-tier', type: 'direct' }, + { testId: 'edit-owner', type: 'direct' }, + { testId: 'rename-button', type: 'with-manage-button' }, + { testId: 'delete-button', type: 'with-manage-button' }, + ]; await expect( - testUserPage.locator('[data-testid="entity-header-title"]') + isMetric + ? testUserPage.getByTestId('metric-details-page') + : testUserPage.locator('[data-testid="entity-header-title"]') ).toBeVisible(); for (const config of testIdsConfigs) { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts index 7edbd72eeacf..26f466a61cd9 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/glossary.ts @@ -462,12 +462,10 @@ export const verifyGlossaryDetails = async ( await checkName(page, glossaryDetails.name); - const viewerContainerText = await page.textContent( - '[data-testid="viewer-container"]' + await expect(page.getByTestId('viewer-container')).toContainText( + glossaryDetails.description ); - expect(viewerContainerText).toContain(glossaryDetails.description); - // Owner if (glossaryDetails.owners.length > 0) { for (const owner of glossaryDetails.owners) { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/headerBreadcrumbUtils.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/headerBreadcrumbUtils.ts index 9c69c8921d67..693a4702cc70 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/headerBreadcrumbUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/headerBreadcrumbUtils.ts @@ -12,8 +12,11 @@ */ import { expect, Page } from '@playwright/test'; -export const expectBreadcrumbCrumbsUnique = async (page: Page) => { - const breadcrumb = page.getByTestId('breadcrumb'); +export const expectBreadcrumbCrumbsUnique = async ( + page: Page, + breadcrumbTestId = 'breadcrumb' +) => { + const breadcrumb = page.getByTestId(breadcrumbTestId); await expect(breadcrumb).toBeVisible(); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/metricMetadata.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/metricMetadata.ts new file mode 100644 index 000000000000..29a4cafd04e9 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/metricMetadata.ts @@ -0,0 +1,176 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import { + expect, + type APIRequestContext, + type Locator, + type Page, + type Request, +} from '@playwright/test'; + +export interface MetricMetadataReference { + displayName?: string; + fullyQualifiedName?: string; + id: string; + name?: string; + type?: string; +} + +export interface MetricMetadataResponse { + dataProducts?: MetricMetadataReference[]; + domains?: MetricMetadataReference[]; + owners?: MetricMetadataReference[]; + tags?: Array<{ + source?: string; + tagFQN: string; + }>; +} + +export const openMetricMetadataEditor = async (page: Page) => { + await expect(page.getByTestId('edit-metric-metadata')).toBeVisible(); + await page.getByTestId('edit-metric-metadata').click(); + + const dialog = page.getByTestId('metric-metadata-edit-dialog'); + await expect(dialog).toBeVisible(); + + return dialog; +}; + +export const setMetricMetadataReferenceSelection = async ( + dialog: Locator, + groupName: string, + referenceName: string, + isSelected: boolean +) => { + const group = dialog.getByRole('group', { + exact: true, + name: groupName, + }); + await expect(group).toBeVisible(); + + const searchInput = group.getByRole('textbox', { + exact: true, + name: `Search ${groupName}`, + }); + await expect(searchInput).toBeEnabled({ timeout: 60_000 }); + + const checkbox = group.getByRole('checkbox', { + exact: true, + name: referenceName, + }); + // Changing the query forces a refetch while newly created fixtures propagate + // to the search index; repeatedly filling the same value does not. + const alternateSearch = + referenceName.length > 1 ? referenceName.slice(0, -1) : referenceName; + let searchWithExactName = true; + await expect(async () => { + await searchInput.fill( + searchWithExactName || !alternateSearch ? referenceName : alternateSearch + ); + searchWithExactName = !searchWithExactName; + await expect(checkbox).toBeVisible({ timeout: 5_000 }); + }).toPass({ intervals: [1_000, 2_000, 5_000], timeout: 60_000 }); + if ((await checkbox.isChecked()) !== isSelected) { + await checkbox.focus(); + await checkbox.press('Space'); + } + if (isSelected) { + await expect(checkbox).toBeChecked(); + } else { + await expect(checkbox).not.toBeChecked(); + } + + return group; +}; + +export const selectMetricMetadataReference = async ( + dialog: Locator, + groupName: string, + referenceName: string +) => { + return setMetricMetadataReferenceSelection( + dialog, + groupName, + referenceName, + true + ); +}; + +export const expectMetricMetadataSelections = async ( + group: Locator, + included: string[], + excluded: string[] = [] +) => { + const selected = group.getByLabel('selected', { exact: true }); + if (included.length === 0) { + await expect(selected).toHaveCount(0); + + return; + } + await expect(selected).toBeVisible(); + + for (const referenceName of included) { + await expect(selected).toContainText(referenceName); + } + for (const referenceName of excluded) { + await expect(selected).not.toContainText(referenceName); + } +}; + +export const saveMetricMetadata = async ( + page: Page, + dialog: Locator, + metricId: string +) => { + const metricPath = `/api/v1/metrics/${metricId}`; + let metricPatchCount = 0; + const countMetricPatch = (request: Request) => { + if ( + request.method() === 'PATCH' && + new URL(request.url()).pathname === metricPath + ) { + metricPatchCount += 1; + } + }; + page.on('request', countMetricPatch); + + try { + const patchResponse = page.waitForResponse( + (response) => + response.request().method() === 'PATCH' && + new URL(response.url()).pathname === metricPath + ); + await dialog.getByTestId('save-metric-metadata').click(); + + const response = await patchResponse; + expect(response.ok()).toBeTruthy(); + await expect(dialog).toBeHidden(); + expect(metricPatchCount).toBe(1); + + return response; + } finally { + page.off('request', countMetricPatch); + } +}; + +export const getPersistedMetricMetadata = async ( + apiContext: APIRequestContext, + metricId: string +) => { + const response = await apiContext.get( + `/api/v1/metrics/${metricId}?fields=owners,domains,dataProducts,tags` + ); + expect(response.ok()).toBeTruthy(); + + return (await response.json()) as MetricMetadataResponse; +}; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AlertBar/AlertBar.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/AlertBar/AlertBar.interface.ts index 59b0e3cd2e64..044dd7777dfd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AlertBar/AlertBar.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/AlertBar/AlertBar.interface.ts @@ -10,7 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { AlertProps } from 'antd'; +import type { AlertProps } from 'antd'; export interface AlertBarProps { type: AlertProps['type'] | 'grey-info'; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx index 57c458ff8b13..076b08ad12dc 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx @@ -10,12 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - Button, - Tooltip, - TooltipTrigger, - Typography, -} from '@openmetadata/ui-core-components'; +import { Button, Tooltip, Typography } from '@openmetadata/ui-core-components'; import { Copy01, File02, @@ -288,25 +283,23 @@ export const DataAssetsHeader = ({ return ( - - - - - + + + ); }, [dqFailureCount, isDqAlertSupported, dataAsset, entityType, t]); @@ -637,18 +630,16 @@ export const DataAssetsHeader = ({ disableRunAgentsButtonMessage ?? t('message.trigger-auto-pilot-application') }> - - - + ); }, [ @@ -671,20 +662,18 @@ export const DataAssetsHeader = ({ return ( - - - + ); }, [dataAsset, t]); @@ -865,19 +854,18 @@ export const DataAssetsHeader = ({ ? t('message.link-copy-to-clipboard') : t('label.copy-item', { item: t('label.url-uppercase') }) }> - - - ) : ( - - {label} - - ); - return ( - {interactive} + + {label} + ); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/StatItem.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/StatItem.test.tsx new file mode 100644 index 000000000000..752788066c04 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/StatItem.test.tsx @@ -0,0 +1,73 @@ +/* + * Copyright 2026 Collate. + * 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. + */ +import { fireEvent, render, screen } from '@testing-library/react'; +import { StatItem } from './StatItem.component'; + +describe('StatItem', () => { + it('uses one accessible trigger for the tooltip and action', () => { + const onClick = jest.fn(); + + render( + + ); + + const trigger = screen.getByRole('button', { name: 'Open metric tasks' }); + + expect(trigger.querySelectorAll('button')).toHaveLength(0); + + fireEvent.click(trigger); + + expect(onClick).toHaveBeenCalledTimes(1); + }); + + it('prevents actions while loading', () => { + const onClick = jest.fn(); + + render( + + ); + + const trigger = screen.getByRole('button', { name: 'Open metric tasks' }); + + expect(trigger).toBeDisabled(); + + fireEvent.click(trigger); + + expect(onClick).not.toHaveBeenCalled(); + }); + + it('does not expose an enabled action when no click handler exists', () => { + render( + + ); + + expect(screen.getByRole('button', { name: 'Metric tasks' })).toBeDisabled(); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts index 1431e7cf4492..4e859952c832 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts @@ -11,7 +11,7 @@ * limitations under the License. */ -import { DefaultOptionType } from 'antd/lib/select'; +import type { DefaultOptionType } from 'antd/lib/select'; import { HTMLAttributes } from 'react'; import { OperationPermission } from '../../../context/PermissionProvider/PermissionProvider.interface'; import { SORT_ORDER } from '../../../enums/common.enum'; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExplorePage.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExplorePage.interface.ts index de0a79adede2..df742825b9ab 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExplorePage.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExplorePage.interface.ts @@ -11,7 +11,7 @@ * limitations under the License. */ -import { ItemType } from 'antd/lib/menu/hooks/useItems'; +import type { ItemType } from 'antd/lib/menu/hooks/useItems'; import { SORT_ORDER } from '../../enums/common.enum'; import { SearchIndex } from '../../enums/search.enum'; import { Kpi } from '../../generated/dataInsight/kpi/kpi'; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx index d262828b0aa5..1a2bac7cce3c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx @@ -15,9 +15,13 @@ import { DownOutlined, WarningOutlined } from '@ant-design/icons'; import Icon from '@ant-design/icons/lib/components/Icon'; import { Button as CoreButton, + Dialog, EmptyPlaceholder, Input, + Modal as CoreModal, + ModalOverlay, TableCard, + TextArea, } from '@openmetadata/ui-core-components'; import { File02, Plus } from '@untitledui/icons'; import { @@ -141,6 +145,11 @@ const GLOSSARY_TERM_DRAG_TYPE = 'application/x-om-glossary-term'; const GLOSSARY_TABLE_SCROLL = { x: 'max-content', y: 'calc(100vh - 350px)' }; +interface PendingGlossaryTermRejection { + glossaryTermFqn: string; + taskId: string | number; +} + const renderGlossaryExpandIcon = ( { expanded, @@ -228,6 +237,10 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { const [termTaskThreads, setTermTaskThreads] = useState< Record >({}); + const [pendingRejection, setPendingRejection] = + useState(); + const [rejectionComment, setRejectionComment] = useState(''); + const [isRejecting, setIsRejecting] = useState(false); const glossaryTerms = useMemo(() => { // Deduplicate by FQN: the table keys rows on fullyQualifiedName, and @@ -676,7 +689,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { ) => { try { if (!taskId) { - return; + return false; } const resolutionType = @@ -685,6 +698,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { : TaskResolutionType.Rejected; const updatedTask = await resolveTaskAPI(taskId + '', { + comment: data.comment, resolutionType, newValue: data.newValue, }); @@ -709,7 +723,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { ); } - return; + return true; } const newStatus = @@ -745,8 +759,12 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { setTermTaskThreads(updatedThreads); } } + + return true; } catch (error) { showErrorToast(error as AxiosError); + + return false; } }, [expandedRowKeys, glossaryChildTerms, selectedStatus, termTaskThreads] @@ -762,12 +780,38 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { const handleRejectGlossaryTerm = useCallback( (taskId: string | number, glossaryTermFqn: string) => { - const data = { newValue: 'rejected' } as ResolveTask; - updateTaskData(data, taskId, glossaryTermFqn); + setPendingRejection({ glossaryTermFqn, taskId }); + setRejectionComment(''); }, - [updateTaskData] + [] ); + const handleRejectDialogClose = useCallback(() => { + if (!isRejecting) { + setPendingRejection(undefined); + setRejectionComment(''); + } + }, [isRejecting]); + + const handleRejectConfirm = useCallback(async () => { + const comment = rejectionComment.trim(); + if (!pendingRejection || !comment) { + return; + } + + setIsRejecting(true); + const didReject = await updateTaskData( + { comment, newValue: 'rejected' } as ResolveTask, + pendingRejection.taskId, + pendingRejection.glossaryTermFqn + ); + setIsRejecting(false); + if (didReject) { + setPendingRejection(undefined); + setRejectionComment(''); + } + }, [pendingRejection, rejectionComment, updateTaskData]); + const handleLoadMoreChildren = useCallback( (record: ModifiedGlossaryTerm) => { if (record.childrenPagingAfter) { @@ -1856,6 +1900,47 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => { )} + !isOpen && handleRejectDialogClose()}> + +

    + +