mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 02:16:18 +00:00
PW: migrate query entity spec to playwright (#17619)
* PW: migrate query entity spec to playwright * migrated to playwright * minor test fix * fixed api waiting issue * fixed the api issue * fixed API response await * fixed await issue
This commit is contained in:
parent
183da3f2b1
commit
3a5539eb1c
@ -1,354 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 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 {
|
|
||||||
descriptionBox,
|
|
||||||
interceptURL,
|
|
||||||
verifyResponseStatusCode,
|
|
||||||
} from '../../common/common';
|
|
||||||
import {
|
|
||||||
createEntityTable,
|
|
||||||
createQueryByTableName,
|
|
||||||
generateRandomTable,
|
|
||||||
hardDeleteService,
|
|
||||||
} from '../../common/EntityUtils';
|
|
||||||
import { visitEntityDetailsPage } from '../../common/Utils/Entity';
|
|
||||||
import { getToken } from '../../common/Utils/LocalStorage';
|
|
||||||
import { generateRandomUser } from '../../common/Utils/Owner';
|
|
||||||
import { EntityType } from '../../constants/Entity.interface';
|
|
||||||
import {
|
|
||||||
DATABASE_SERVICE,
|
|
||||||
DATABASE_SERVICE_DETAILS,
|
|
||||||
} from '../../constants/EntityConstant';
|
|
||||||
import { SERVICE_CATEGORIES } from '../../constants/service.constants';
|
|
||||||
|
|
||||||
const queryTable = {
|
|
||||||
term: DATABASE_SERVICE.entity.name,
|
|
||||||
displayName: DATABASE_SERVICE.entity.name,
|
|
||||||
entity: EntityType.Table,
|
|
||||||
serviceName: DATABASE_SERVICE.service.name,
|
|
||||||
entityType: 'Table',
|
|
||||||
};
|
|
||||||
const table1 = generateRandomTable();
|
|
||||||
const table2 = generateRandomTable();
|
|
||||||
const user1 = generateRandomUser();
|
|
||||||
const user2 = generateRandomUser();
|
|
||||||
const owner = `${user2.firstName}${user2.lastName}`;
|
|
||||||
const userIds: string[] = [];
|
|
||||||
|
|
||||||
const DATA = {
|
|
||||||
...queryTable,
|
|
||||||
query: `select * from table ${queryTable.term}`,
|
|
||||||
description: 'select all the field from table',
|
|
||||||
owner: 'Aaron Johnson',
|
|
||||||
tag: 'Personal',
|
|
||||||
queryUsedIn: {
|
|
||||||
table1: table1.name,
|
|
||||||
table2: table2.name,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryFilters = ({
|
|
||||||
key,
|
|
||||||
filter,
|
|
||||||
apiKey,
|
|
||||||
}: {
|
|
||||||
key: string;
|
|
||||||
filter: string;
|
|
||||||
apiKey: string;
|
|
||||||
}) => {
|
|
||||||
cy.get(`[data-testid="search-dropdown-${key}"]`).click();
|
|
||||||
cy.get('[data-testid="search-input"]').type(filter);
|
|
||||||
verifyResponseStatusCode(apiKey, 200);
|
|
||||||
cy.get(`[data-testid="search-dropdown-${key}"]`).trigger('mouseout');
|
|
||||||
cy.get(`[data-testid="drop-down-menu"] [title="${filter}"]`).click();
|
|
||||||
cy.get('[data-testid="update-btn"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Query Entity', { tags: 'DataAssets' }, () => {
|
|
||||||
before(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
|
|
||||||
createEntityTable({
|
|
||||||
token,
|
|
||||||
...DATABASE_SERVICE,
|
|
||||||
tables: [DATABASE_SERVICE.entity, table1, table2],
|
|
||||||
});
|
|
||||||
// get Table by name and create query in the table
|
|
||||||
createQueryByTableName(token, table1);
|
|
||||||
|
|
||||||
// Create a new user
|
|
||||||
cy.request({
|
|
||||||
method: 'POST',
|
|
||||||
url: `/api/v1/users/signup`,
|
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
|
||||||
body: user1,
|
|
||||||
}).then((response) => {
|
|
||||||
userIds.push(response.body.id);
|
|
||||||
});
|
|
||||||
cy.request({
|
|
||||||
method: 'POST',
|
|
||||||
url: `/api/v1/users/signup`,
|
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
|
||||||
body: user2,
|
|
||||||
}).then((response) => {
|
|
||||||
userIds.push(response.body.id);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
cy.login();
|
|
||||||
cy.getAllLocalStorage().then((data) => {
|
|
||||||
const token = getToken(data);
|
|
||||||
|
|
||||||
hardDeleteService({
|
|
||||||
token,
|
|
||||||
serviceFqn: DATABASE_SERVICE.service.name,
|
|
||||||
serviceType: SERVICE_CATEGORIES.DATABASE_SERVICES,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete created user
|
|
||||||
userIds.forEach((userId) => {
|
|
||||||
cy.request({
|
|
||||||
method: 'DELETE',
|
|
||||||
url: `/api/v1/users/${userId}?hardDelete=true&recursive=false`,
|
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.login();
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'/api/v1/search/query?q=*&index=query_search_index*',
|
|
||||||
'fetchQuery'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Create query', () => {
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'/api/v1/search/query?q=*&from=0&size=15&index=table_search_index',
|
|
||||||
'explorePageSearch'
|
|
||||||
);
|
|
||||||
interceptURL('POST', '/api/v1/queries', 'createQuery');
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: DATA.term,
|
|
||||||
serviceName: DATA.serviceName,
|
|
||||||
entity: DATA.entity,
|
|
||||||
});
|
|
||||||
cy.get('[data-testid="table_queries"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
|
|
||||||
cy.get('[data-testid="add-query-btn"]').click();
|
|
||||||
|
|
||||||
cy.get('[data-testid="code-mirror-container"]').type(DATA.query);
|
|
||||||
cy.get(descriptionBox).scrollIntoView().type(DATA.description);
|
|
||||||
cy.get('[data-testid="query-used-in"]').type(DATA.queryUsedIn.table1);
|
|
||||||
verifyResponseStatusCode('@explorePageSearch', 200);
|
|
||||||
cy.get(`[title="${DATA.queryUsedIn.table1}"]`).click();
|
|
||||||
cy.clickOutside();
|
|
||||||
|
|
||||||
cy.get('[data-testid="save-btn"]').click();
|
|
||||||
verifyResponseStatusCode('@createQuery', 201);
|
|
||||||
|
|
||||||
cy.get('[data-testid="query-card"]').should('have.length.above', 0);
|
|
||||||
cy.get('[data-testid="query-card"]')
|
|
||||||
.contains(DATA.query)
|
|
||||||
.scrollIntoView()
|
|
||||||
.should('be.visible');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Update owner, description and tag', () => {
|
|
||||||
interceptURL('GET', '/api/v1/users?*', 'getUsers');
|
|
||||||
interceptURL('PATCH', '/api/v1/queries/*', 'patchQuery');
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'/api/v1/search/query?q=*&from=0&size=15&index=table_search_index',
|
|
||||||
'explorePageSearch'
|
|
||||||
);
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: DATA.term,
|
|
||||||
serviceName: DATA.serviceName,
|
|
||||||
entity: DATA.entity,
|
|
||||||
});
|
|
||||||
cy.get('[data-testid="table_queries"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
|
|
||||||
cy.get('[data-testid="query-card"]').should('have.length.above', 0);
|
|
||||||
|
|
||||||
// Update owner
|
|
||||||
cy.get(':nth-child(2) > [data-testid="edit-owner"]').click();
|
|
||||||
verifyResponseStatusCode('@getUsers', 200);
|
|
||||||
cy.get('[data-testid="loader"]').should('not.exist');
|
|
||||||
interceptURL('GET', `api/v1/search/query?q=*`, 'searchOwner');
|
|
||||||
cy.get('[data-testid="owner-select-users-search-bar"]').type(owner);
|
|
||||||
verifyResponseStatusCode('@searchOwner', 200);
|
|
||||||
cy.get(`.ant-popover [title="${owner}"]`).click();
|
|
||||||
cy.get('[data-testid="selectable-list-update-btn"]').click();
|
|
||||||
verifyResponseStatusCode('@patchQuery', 200);
|
|
||||||
cy.get('[data-testid="owner-link"]').should('contain', owner);
|
|
||||||
|
|
||||||
// Update Description
|
|
||||||
cy.get('[data-testid="edit-description"]').filter(':visible').click();
|
|
||||||
cy.get(descriptionBox).clear().type('updated description');
|
|
||||||
cy.get('[data-testid="save"]').click();
|
|
||||||
verifyResponseStatusCode('@patchQuery', 200);
|
|
||||||
|
|
||||||
// Update Tags
|
|
||||||
cy.get('[data-testid="entity-tags"] .ant-tag').filter(':visible').click();
|
|
||||||
cy.get('[data-testid="tag-selector"]').type(DATA.tag);
|
|
||||||
cy.get('[data-testid="tag-PersonalData.Personal"]').click();
|
|
||||||
cy.get('[data-testid="saveAssociatedTag"]').scrollIntoView().click();
|
|
||||||
verifyResponseStatusCode('@patchQuery', 200);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Verify query filter', () => {
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: DATA.term,
|
|
||||||
serviceName: DATA.serviceName,
|
|
||||||
entity: DATA.entity,
|
|
||||||
});
|
|
||||||
cy.get('[data-testid="table_queries"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
const userName = `${user1.firstName}${user1.lastName}`;
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
`/api/v1/search/query?*${encodeURI(
|
|
||||||
userName
|
|
||||||
)}*index=user_search_index,team_search_index*`,
|
|
||||||
'searchUserName'
|
|
||||||
);
|
|
||||||
queryFilters({
|
|
||||||
filter: `${user1.firstName}${user1.lastName}`,
|
|
||||||
apiKey: '@searchUserName',
|
|
||||||
key: 'Owner',
|
|
||||||
});
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
`/api/v1/search/query?*${encodeURI(
|
|
||||||
owner
|
|
||||||
)}*index=user_search_index,team_search_index*`,
|
|
||||||
'searchOwner'
|
|
||||||
);
|
|
||||||
cy.get('[data-testid="no-data-placeholder"]').should('be.visible');
|
|
||||||
queryFilters({
|
|
||||||
filter: owner,
|
|
||||||
apiKey: '@searchOwner',
|
|
||||||
key: 'Owner',
|
|
||||||
});
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'/api/v1/search/query?*None*index=tag_search_index*',
|
|
||||||
'noneTagSearch'
|
|
||||||
);
|
|
||||||
cy.get('[data-testid="query-card"]').should('have.length.above', 0);
|
|
||||||
queryFilters({
|
|
||||||
filter: 'None',
|
|
||||||
apiKey: '@noneTagSearch',
|
|
||||||
key: 'Tag',
|
|
||||||
});
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
`/api/v1/search/query?*${DATA.tag}*index=tag_search_index*`,
|
|
||||||
'personalTagSearch'
|
|
||||||
);
|
|
||||||
cy.get('[data-testid="no-data-placeholder"]').should('be.visible');
|
|
||||||
queryFilters({
|
|
||||||
filter: DATA.tag,
|
|
||||||
apiKey: '@personalTagSearch',
|
|
||||||
key: 'Tag',
|
|
||||||
});
|
|
||||||
cy.get('[data-testid="query-card"]').should('have.length.above', 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Update query and QueryUsedIn', () => {
|
|
||||||
interceptURL('GET', '/api/v1/users?&isBot=false&limit=15', 'getUsers');
|
|
||||||
interceptURL('PATCH', '/api/v1/queries/*', 'patchQuery');
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'/api/v1/search/query?q=*&from=0&size=15&index=table_search_index',
|
|
||||||
'explorePageSearch'
|
|
||||||
);
|
|
||||||
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: DATA.term,
|
|
||||||
serviceName: DATA.serviceName,
|
|
||||||
entity: DATA.entity,
|
|
||||||
});
|
|
||||||
cy.get('[data-testid="table_queries"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
|
|
||||||
cy.get('[data-testid="query-btn"]').click();
|
|
||||||
cy.get('[data-menu-id*="edit-query"]').click();
|
|
||||||
cy.get('.CodeMirror-line')
|
|
||||||
.click()
|
|
||||||
.type(`{selectAll}{selectAll}${DATA.queryUsedIn.table1}`);
|
|
||||||
cy.get('[data-testid="edit-query-used-in"]').click();
|
|
||||||
cy.wait('@explorePageSearch');
|
|
||||||
cy.get('[data-testid="edit-query-used-in"]').type(DATA.queryUsedIn.table2);
|
|
||||||
verifyResponseStatusCode('@explorePageSearch', 200);
|
|
||||||
cy.get(`[title="${DATA.queryUsedIn.table2}"]`).click();
|
|
||||||
cy.clickOutside();
|
|
||||||
|
|
||||||
cy.get('[data-testid="save-query-btn"]').click();
|
|
||||||
verifyResponseStatusCode('@patchQuery', 200);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Visit full screen view of query', () => {
|
|
||||||
interceptURL('GET', '/api/v1/queries?*', 'fetchQuery');
|
|
||||||
interceptURL('GET', '/api/v1/users?&isBot=false&limit=15', 'getUsers');
|
|
||||||
interceptURL('GET', '/api/v1/queries/*', 'getQueryById');
|
|
||||||
interceptURL(
|
|
||||||
'GET',
|
|
||||||
'/api/v1/search/query?q=*&from=0&size=15&index=table_search_index',
|
|
||||||
'explorePageSearch'
|
|
||||||
);
|
|
||||||
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: DATA.term,
|
|
||||||
serviceName: DATA.serviceName,
|
|
||||||
entity: DATA.entity,
|
|
||||||
});
|
|
||||||
cy.get('[data-testid="table_queries"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
cy.get('[data-testid="query-entity-expand-button"]').click();
|
|
||||||
verifyResponseStatusCode('@getQueryById', 200);
|
|
||||||
|
|
||||||
cy.get('[data-testid="query-btn"]').click();
|
|
||||||
cy.get('.ant-dropdown').should('be.visible');
|
|
||||||
cy.get('[data-menu-id*="delete-query"]').click();
|
|
||||||
cy.get('[data-testid="save-button"]').click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Verify query duration', () => {
|
|
||||||
visitEntityDetailsPage({
|
|
||||||
term: table1.name,
|
|
||||||
serviceName: DATABASE_SERVICE_DETAILS.name,
|
|
||||||
entity: DATA.entity,
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('[data-testid="table_queries"]').click();
|
|
||||||
verifyResponseStatusCode('@fetchQuery', 200);
|
|
||||||
|
|
||||||
// Validate that the duration is in sec or not
|
|
||||||
cy.get('[data-testid="query-run-duration"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.should('contain', '6.199 sec');
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import test, { expect } from '@playwright/test';
|
||||||
|
import { TableClass } from '../../support/entity/TableClass';
|
||||||
|
import { UserClass } from '../../support/user/UserClass';
|
||||||
|
import {
|
||||||
|
clickOutside,
|
||||||
|
createNewPage,
|
||||||
|
descriptionBox,
|
||||||
|
redirectToHomePage,
|
||||||
|
} from '../../utils/common';
|
||||||
|
import { createQueryByTableName, queryFilters } from '../../utils/query';
|
||||||
|
|
||||||
|
// use the admin user to login
|
||||||
|
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||||
|
|
||||||
|
const table1 = new TableClass();
|
||||||
|
const table2 = new TableClass();
|
||||||
|
const table3 = new TableClass();
|
||||||
|
const user1 = new UserClass();
|
||||||
|
const user2 = new UserClass();
|
||||||
|
const entityData = [table1, table2, table3, user1, user2];
|
||||||
|
const queryData = {
|
||||||
|
query: `select * from table ${table1.entity.name}`,
|
||||||
|
description: 'select all the field from table',
|
||||||
|
owner: user1.getUserName(),
|
||||||
|
tagFqn: 'PersonalData.Personal',
|
||||||
|
tagName: 'Personal',
|
||||||
|
queryUsedIn: {
|
||||||
|
table1: table2.entity.name,
|
||||||
|
table2: table3.entity.name,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
test.beforeAll(async ({ browser }) => {
|
||||||
|
const { afterAction, apiContext } = await createNewPage(browser);
|
||||||
|
for (const entity of entityData) {
|
||||||
|
await entity.create(apiContext);
|
||||||
|
}
|
||||||
|
await createQueryByTableName({
|
||||||
|
apiContext,
|
||||||
|
tableResponseData: table2.entityResponseData,
|
||||||
|
});
|
||||||
|
await afterAction();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Query Entity', async ({ page }) => {
|
||||||
|
test.slow(true);
|
||||||
|
|
||||||
|
await redirectToHomePage(page);
|
||||||
|
await table1.visitEntityPage(page);
|
||||||
|
|
||||||
|
await test.step('Create a new query entity', async () => {
|
||||||
|
const queryResponse = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?q=*&index=query_search_index*'
|
||||||
|
);
|
||||||
|
await page.click(`[data-testid="table_queries"]`);
|
||||||
|
await queryResponse;
|
||||||
|
await page.click(`[data-testid="add-query-btn"]`);
|
||||||
|
await page
|
||||||
|
.getByTestId('code-mirror-container')
|
||||||
|
.getByRole('textbox')
|
||||||
|
.fill(queryData.query);
|
||||||
|
await page.click(descriptionBox);
|
||||||
|
await page.keyboard.type(queryData.description);
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByTestId('query-used-in')
|
||||||
|
.locator('div')
|
||||||
|
.filter({ hasText: 'Please Select a Query Used In' })
|
||||||
|
.click();
|
||||||
|
await page.keyboard.type(queryData.queryUsedIn.table1);
|
||||||
|
|
||||||
|
await page.click(`[title="${queryData.queryUsedIn.table1}"]`);
|
||||||
|
await clickOutside(page);
|
||||||
|
|
||||||
|
const createQueryResponse = page.waitForResponse('/api/v1/queries');
|
||||||
|
await page.click('[data-testid="save-btn"]');
|
||||||
|
await createQueryResponse;
|
||||||
|
await page.waitForURL('**/table_queries**');
|
||||||
|
|
||||||
|
await expect(page.locator(`text=${queryData.query}`)).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Update owner, description and tag', async () => {
|
||||||
|
const ownerListResponse = page.waitForResponse('/api/v1/users?*');
|
||||||
|
await page
|
||||||
|
.getByTestId(
|
||||||
|
'entity-summary-resizable-right-panel-container entity-resizable-panel-container'
|
||||||
|
)
|
||||||
|
.getByTestId('edit-owner')
|
||||||
|
.click();
|
||||||
|
await ownerListResponse;
|
||||||
|
|
||||||
|
await page.waitForSelector('[data-testid="loader"]', {
|
||||||
|
state: 'detached',
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchOwnerResponse = page.waitForResponse('api/v1/search/query?q=*');
|
||||||
|
await page.fill(
|
||||||
|
'[data-testid="owner-select-users-search-bar"]',
|
||||||
|
queryData.owner
|
||||||
|
);
|
||||||
|
await searchOwnerResponse;
|
||||||
|
await page.click(`.ant-popover [title="${queryData.owner}"]`);
|
||||||
|
const updateOwnerResponse = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/api/v1/queries/') &&
|
||||||
|
response.request().method() === 'PATCH'
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="selectable-list-update-btn"]');
|
||||||
|
await updateOwnerResponse;
|
||||||
|
|
||||||
|
await expect(page.getByRole('link', { name: 'admin' })).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByRole('link', { name: queryData.owner })
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
// Update Description
|
||||||
|
await page.click(`[data-testid="edit-description"]`);
|
||||||
|
await page.fill(descriptionBox, 'updated description');
|
||||||
|
const updateDescriptionResponse = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/api/v1/queries/') &&
|
||||||
|
response.request().method() === 'PATCH'
|
||||||
|
);
|
||||||
|
await page.click(`[data-testid="save"]`);
|
||||||
|
await updateDescriptionResponse;
|
||||||
|
await page.waitForSelector('.ant-modal-body', {
|
||||||
|
state: 'detached',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Tags
|
||||||
|
await page.getByTestId('add-tag').click();
|
||||||
|
await page.locator('#tagsForm_tags').click();
|
||||||
|
await page.locator('#tagsForm_tags').fill(queryData.tagFqn);
|
||||||
|
await page.getByTestId(`tag-${queryData.tagFqn}`).click();
|
||||||
|
const updateTagResponse = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/api/v1/queries/') &&
|
||||||
|
response.request().method() === 'PATCH'
|
||||||
|
);
|
||||||
|
await page.getByTestId('saveAssociatedTag').click();
|
||||||
|
await updateTagResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Update query and QueryUsedIn', async () => {
|
||||||
|
await page.click('[data-testid="query-btn"]');
|
||||||
|
await page.click(`[data-menu-id*="edit-query"]`);
|
||||||
|
await page.click('.CodeMirror-line', { clickCount: 3 });
|
||||||
|
await page.keyboard.press('Backspace');
|
||||||
|
await page.keyboard.type(`${queryData.queryUsedIn.table1}`);
|
||||||
|
await page.click('[data-testid="edit-query-used-in"]');
|
||||||
|
const tableSearchResponse = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?q=*&index=table_search_index'
|
||||||
|
);
|
||||||
|
await page.keyboard.type(queryData.queryUsedIn.table2);
|
||||||
|
await tableSearchResponse;
|
||||||
|
await page.click(`[title="${queryData.queryUsedIn.table2}"]`);
|
||||||
|
await clickOutside(page);
|
||||||
|
const updateQueryResponse = page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().includes('/api/v1/queries/') &&
|
||||||
|
response.request().method() === 'PATCH'
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="save-query-btn"]');
|
||||||
|
await updateQueryResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Verify query filter', async () => {
|
||||||
|
const userName = user2.getUserName();
|
||||||
|
await queryFilters({
|
||||||
|
filter: userName,
|
||||||
|
apiKey: `/api/v1/search/query?*${encodeURI(
|
||||||
|
userName
|
||||||
|
)}*index=user_search_index,team_search_index*`,
|
||||||
|
key: 'Owner',
|
||||||
|
page,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-testid="no-data-placeholder"]')
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await queryFilters({
|
||||||
|
filter: queryData.owner,
|
||||||
|
apiKey: `/api/v1/search/query?*${encodeURI(
|
||||||
|
queryData.owner
|
||||||
|
)}*index=user_search_index,team_search_index*`,
|
||||||
|
key: 'Owner',
|
||||||
|
page,
|
||||||
|
});
|
||||||
|
const queryCards = await page.$$('[data-testid="query-card"]');
|
||||||
|
|
||||||
|
expect(queryCards.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
await queryFilters({
|
||||||
|
filter: 'None',
|
||||||
|
apiKey: '/api/v1/search/query?*None*index=tag_search_index*',
|
||||||
|
key: 'Tag',
|
||||||
|
page,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-testid="no-data-placeholder"]')
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await queryFilters({
|
||||||
|
filter: queryData.tagName,
|
||||||
|
apiKey: `/api/v1/search/query?*${queryData.tagName}*index=tag_search_index*`,
|
||||||
|
key: 'Tag',
|
||||||
|
page,
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedQueryCards = await page.$$('[data-testid="query-card"]');
|
||||||
|
|
||||||
|
expect(updatedQueryCards.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step('Visit full screen view of query and Delete', async () => {
|
||||||
|
const queryResponse = page.waitForResponse('/api/v1/queries/*');
|
||||||
|
await page.click(`[data-testid="query-entity-expand-button"]`);
|
||||||
|
await queryResponse;
|
||||||
|
|
||||||
|
await page.click(`[data-testid="query-btn"]`);
|
||||||
|
await page.waitForSelector('.ant-dropdown', { state: 'visible' });
|
||||||
|
await page.click(`[data-menu-id*="delete-query"]`);
|
||||||
|
await page.click(`[data-testid="save-button"]`);
|
||||||
|
await page.waitForResponse('/api/v1/queries/*');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Verify query duration', async ({ page }) => {
|
||||||
|
await redirectToHomePage(page);
|
||||||
|
await table2.visitEntityPage(page);
|
||||||
|
const queryResponse = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?q=*&index=query_search_index*'
|
||||||
|
);
|
||||||
|
await page.click(`[data-testid="table_queries"]`);
|
||||||
|
await queryResponse;
|
||||||
|
await page.waitForSelector('[data-testid="query-run-duration"]', {
|
||||||
|
state: 'visible',
|
||||||
|
});
|
||||||
|
const durationText = await page.textContent(
|
||||||
|
'[data-testid="query-run-duration"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(durationText).toContain('6.199 sec');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll(async ({ browser }) => {
|
||||||
|
const { afterAction, apiContext } = await createNewPage(browser);
|
||||||
|
for (const entity of entityData) {
|
||||||
|
await entity.delete(apiContext);
|
||||||
|
}
|
||||||
|
await afterAction();
|
||||||
|
});
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import { APIRequestContext, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export const createQueryByTableName = async (data: {
|
||||||
|
apiContext: APIRequestContext;
|
||||||
|
tableResponseData: unknown;
|
||||||
|
}) => {
|
||||||
|
const { apiContext, tableResponseData } = data;
|
||||||
|
const queryResponse = await apiContext
|
||||||
|
.post('/api/v1/queries', {
|
||||||
|
data: {
|
||||||
|
query: `SELECT * FROM SALES-${tableResponseData?.['name']}`,
|
||||||
|
description: 'this is query description',
|
||||||
|
queryUsedIn: [
|
||||||
|
{
|
||||||
|
id: tableResponseData?.['id'],
|
||||||
|
type: 'table',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
duration: 6199,
|
||||||
|
queryDate: 1700225667191,
|
||||||
|
service: tableResponseData?.['service']?.['name'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response.json());
|
||||||
|
|
||||||
|
return await queryResponse;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const queryFilters = async ({
|
||||||
|
key,
|
||||||
|
filter,
|
||||||
|
apiKey,
|
||||||
|
page,
|
||||||
|
}: {
|
||||||
|
key: string;
|
||||||
|
filter: string;
|
||||||
|
apiKey: string;
|
||||||
|
page: Page;
|
||||||
|
}) => {
|
||||||
|
await page.click(`[data-testid="search-dropdown-${key}"]`);
|
||||||
|
const searchInputResponse = page.waitForResponse(apiKey);
|
||||||
|
await page.fill('[data-testid="search-input"]', filter);
|
||||||
|
await searchInputResponse;
|
||||||
|
await page.hover(`[data-testid="search-dropdown-${key}"]`);
|
||||||
|
await page.click(`[data-testid="drop-down-menu"] [title="${filter}"]`);
|
||||||
|
const queryResponse = page.waitForResponse(
|
||||||
|
'/api/v1/search/query?q=*&index=query_search_index*'
|
||||||
|
);
|
||||||
|
await page.click('[data-testid="update-btn"]');
|
||||||
|
await queryResponse;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user