mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-26 01:46:26 +00:00
minor: add encoding and decoding for policy rule name (#17344)
* minor: add encoding and decoding for policy rule name * move encoding logic to util method * refactor: move the constant to separate file * chore: Remove unnecessary wait for timeout in Policies.spec.ts
This commit is contained in:
parent
81e467a225
commit
c6ee207837
@ -1,374 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 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,
|
||||
uuid,
|
||||
verifyResponseStatusCode,
|
||||
} from '../../common/common';
|
||||
import { validateFormNameFieldInput } from '../../common/Utils/Form';
|
||||
import { BASE_URL } from '../../constants/constants';
|
||||
import { GlobalSettingOptions } from '../../constants/settings.constant';
|
||||
|
||||
const roles = {
|
||||
dataConsumer: 'Data Consumer',
|
||||
dataSteward: 'Data Steward',
|
||||
};
|
||||
|
||||
const policies = {
|
||||
dataConsumerPolicy: 'Data Consumer Policy',
|
||||
dataStewardPolicy: 'Data Steward Policy',
|
||||
organizationPolicy: 'Organization Policy',
|
||||
teamOnlyAccessPolicy: 'Team only access Policy',
|
||||
};
|
||||
|
||||
const ruleDetails = {
|
||||
resources: 'All',
|
||||
operations: 'All',
|
||||
effect: 'Allow',
|
||||
condition: 'isOwner()',
|
||||
inValidCondition: 'isOwner(',
|
||||
};
|
||||
|
||||
const errorMessageValidation = {
|
||||
lastPolicyCannotBeRemoved: 'At least one policy is required in a role',
|
||||
lastRuleCannotBeRemoved: 'At least one rule is required in a policy',
|
||||
};
|
||||
|
||||
const policyName = `Policy-test-${uuid()}`;
|
||||
const description = `This is ${policyName} description`;
|
||||
|
||||
const ruleName = `Rule-test-${uuid()}`;
|
||||
const ruleDescription = `This is ${ruleName} description`;
|
||||
const updatedDescription = 'This is updated description';
|
||||
|
||||
const newRuleName = `New-Rule-test-${uuid()}`;
|
||||
const newRuledescription = `This is ${newRuleName} description`;
|
||||
|
||||
const updatedRuleName = `New-Rule-test-${uuid()}-updated`;
|
||||
|
||||
const addRule = (rulename, ruleDescription, descriptionIndex) => {
|
||||
validateFormNameFieldInput({
|
||||
value: rulename,
|
||||
fieldName: 'Name',
|
||||
fieldSelector: '[data-testid="rule-name"]',
|
||||
errorDivSelector: '#ruleName_help',
|
||||
});
|
||||
// Enter rule description
|
||||
cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')
|
||||
.eq(descriptionIndex)
|
||||
.scrollIntoView()
|
||||
.type(ruleDescription);
|
||||
// Select resource dropdown
|
||||
cy.get('[data-testid="resources"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
// Select All
|
||||
cy.get('.ant-select-tree-checkbox-inner').should('be.visible').click();
|
||||
|
||||
// Click on operations dropdown
|
||||
cy.get('[data-testid="operations"]').should('be.visible').click();
|
||||
|
||||
cy.get('.ant-select-tree-checkbox-inner').eq(1).should('be.visible').click();
|
||||
// Click on condition combobox
|
||||
|
||||
cy.get('[data-testid="condition"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get(`[title="${ruleDetails.condition}"]`).should('be.visible').click();
|
||||
|
||||
cy.get('[data-testid="condition-success"]').contains('✅ Valid condition');
|
||||
|
||||
cy.wait(500);
|
||||
// Submit
|
||||
cy.get('[data-testid="submit-btn"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
};
|
||||
|
||||
describe('Policy page should work properly', { tags: 'Settings' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.intercept('GET', '*api/v1/policies*').as('getPolicies');
|
||||
|
||||
cy.settingClick(GlobalSettingOptions.POLICIES);
|
||||
|
||||
cy.wait('@getPolicies', { timeout: 15000 })
|
||||
.its('response.statusCode')
|
||||
.should('equal', 200);
|
||||
|
||||
cy.url().should('eq', `${BASE_URL}/settings/access/policies`);
|
||||
});
|
||||
|
||||
it('Default Policies and Roles should be displayed', () => {
|
||||
// Verifying the default roles and policies are present
|
||||
|
||||
Object.values(policies).forEach((policy) => {
|
||||
cy.get('[data-testid="policy-name"]')
|
||||
.should('contain', policy)
|
||||
.should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('Add new policy', () => {
|
||||
// Click on add new policy
|
||||
cy.get('[data-testid="add-policy"]').should('be.visible').click();
|
||||
cy.get('[data-testid="inactive-link"]');
|
||||
|
||||
// Enter policy name
|
||||
cy.get('[data-testid="policy-name"]').should('be.visible').type(policyName);
|
||||
validateFormNameFieldInput({
|
||||
value: policyName,
|
||||
fieldName: 'Name',
|
||||
fieldSelector: '[data-testid="policy-name"]',
|
||||
errorDivSelector: '#name_help',
|
||||
});
|
||||
|
||||
// Enter description
|
||||
cy.get(descriptionBox).eq(0).type(description);
|
||||
|
||||
// Enter rule name
|
||||
addRule(ruleName, ruleDescription, 1);
|
||||
|
||||
// Validate the added policy
|
||||
cy.get('[data-testid="inactive-link"]')
|
||||
.should('be.visible')
|
||||
.should('have.text', policyName);
|
||||
|
||||
cy.get('[data-testid="rule-name"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleName);
|
||||
|
||||
// Verify policy description
|
||||
cy.get(
|
||||
'[data-testid="asset-description-container"] [data-testid="viewer-container"]'
|
||||
)
|
||||
.eq(0)
|
||||
.should('be.visible')
|
||||
.should('contain', description);
|
||||
|
||||
// verify rule description
|
||||
cy.get('[data-testid="viewer-container"] > [data-testid="markdown-parser"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleDescription);
|
||||
|
||||
// Verify other details
|
||||
cy.get('[data-testid="rule-name"]').should('be.visible').click();
|
||||
|
||||
cy.get('[data-testid="resources"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleDetails.resources);
|
||||
|
||||
cy.get('[data-testid="operations"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleDetails.operations);
|
||||
|
||||
cy.get('[data-testid="effect"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleDetails.effect);
|
||||
|
||||
cy.get('[data-testid="condition"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleDetails.condition);
|
||||
});
|
||||
|
||||
it('Edit policy description', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/policies/name/${policyName}*`,
|
||||
'getSelectedPolicy'
|
||||
);
|
||||
// Click on created policy name
|
||||
cy.get('[data-testid="policy-name"]').contains(policyName).click();
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
cy.get('[data-testid="edit-description"]').should('be.visible').click();
|
||||
// Enter updated description
|
||||
cy.get(descriptionBox)
|
||||
.should('be.visible')
|
||||
.clear()
|
||||
.type(`${updatedDescription}-${policyName}`);
|
||||
// Click on save
|
||||
cy.get('[data-testid="save"]').should('be.visible').click();
|
||||
|
||||
// Validate added description
|
||||
cy.get(
|
||||
'[data-testid="asset-description-container"] [data-testid="viewer-container"]'
|
||||
)
|
||||
.should('be.visible')
|
||||
.should('contain', `${updatedDescription}-${policyName}`);
|
||||
});
|
||||
|
||||
it('Add new rule', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/policies/name/${policyName}*`,
|
||||
'getSelectedPolicy'
|
||||
);
|
||||
// Click on created policy name
|
||||
cy.get('[data-testid="policy-name"]').contains(policyName).click();
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
|
||||
interceptURL('GET', '/api/v1/policies/*', 'addRulepage');
|
||||
// Click on add rule button
|
||||
cy.get('[data-testid="add-rule"]').should('be.visible').click();
|
||||
|
||||
verifyResponseStatusCode('@addRulepage', 200);
|
||||
|
||||
addRule(newRuleName, newRuledescription, 0);
|
||||
|
||||
// Validate added rule
|
||||
cy.get('[data-testid="rule-name"]')
|
||||
.should('be.visible')
|
||||
.should('contain', ruleName);
|
||||
|
||||
// Verify other details
|
||||
cy.get('[data-testid="rule-name"]')
|
||||
.last()
|
||||
.scrollIntoView()
|
||||
.contains(ruleName)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="resources"]')
|
||||
.last()
|
||||
.scrollIntoView()
|
||||
.should('exist')
|
||||
.should('contain', ruleDetails.resources);
|
||||
|
||||
cy.get('[data-testid="operations"]')
|
||||
.last()
|
||||
.scrollIntoView()
|
||||
.should('exist')
|
||||
.should('contain', ruleDetails.operations);
|
||||
|
||||
cy.get('[data-testid="effect"]')
|
||||
.last()
|
||||
.scrollIntoView()
|
||||
.should('exist')
|
||||
.should('contain', ruleDetails.effect);
|
||||
|
||||
cy.get('[data-testid="condition"]')
|
||||
.last()
|
||||
.scrollIntoView()
|
||||
.should('exist')
|
||||
.should('contain', ruleDetails.condition);
|
||||
});
|
||||
|
||||
it('Edit rule name for created Rule', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/policies/name/${policyName}*`,
|
||||
'getSelectedPolicy'
|
||||
);
|
||||
// Click on created policy name
|
||||
cy.get('[data-testid="policy-name"]').contains(policyName).click();
|
||||
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
// Click on new rule manage button
|
||||
cy.get(`[data-testid="manage-button-${newRuleName}"]`)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
interceptURL('GET', '/api/v1/policies/*', 'editRulePage');
|
||||
cy.get('[data-testid="edit-rule"]').should('be.visible').click();
|
||||
|
||||
verifyResponseStatusCode('@editRulePage', 200);
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
|
||||
// Enter new name
|
||||
cy.get('[data-testid="rule-name"]').clear().type(updatedRuleName);
|
||||
|
||||
interceptURL('PATCH', '/api/v1/policies/*', 'updateRule');
|
||||
|
||||
cy.get('[data-testid="submit-btn"]')
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
verifyResponseStatusCode('@updateRule', 200);
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
|
||||
cy.url().should('include', policyName);
|
||||
|
||||
cy.get('[data-testid="rule-name"]').should('contain', updatedRuleName);
|
||||
});
|
||||
|
||||
it('Delete new rule', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/policies/name/${policyName}*`,
|
||||
'getSelectedPolicy'
|
||||
);
|
||||
// Click on created policy name
|
||||
cy.get('[data-testid="policy-name"]').contains(policyName).click();
|
||||
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
|
||||
// Click on new rule manage button
|
||||
cy.get(`[data-testid="manage-button-${updatedRuleName}"]`)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="delete-rule"]').should('be.visible').click();
|
||||
|
||||
// Validate the deleted rule
|
||||
cy.get('[data-testid="rule-name"]')
|
||||
.should('be.visible')
|
||||
.should('not.contain', updatedRuleName);
|
||||
});
|
||||
|
||||
it('Delete last rule and validate', () => {
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/policies/name/${policyName}*`,
|
||||
'getSelectedPolicy'
|
||||
);
|
||||
// Click on created policy name
|
||||
cy.get('[data-testid="policy-name"]').contains(policyName).click();
|
||||
|
||||
verifyResponseStatusCode('@getSelectedPolicy', 200);
|
||||
|
||||
// Click on new rule manage button
|
||||
cy.get(`[data-testid="manage-button-${ruleName}"]`)
|
||||
.should('be.visible')
|
||||
.click();
|
||||
interceptURL('PATCH', '/api/v1/policies/*', 'deletelastPolicy');
|
||||
|
||||
cy.get('[data-testid="delete-rule"]').should('be.visible').click();
|
||||
|
||||
verifyResponseStatusCode('@deletelastPolicy', 400);
|
||||
|
||||
cy.get('.Toastify__toast-body')
|
||||
.should('be.visible')
|
||||
.should('contain', errorMessageValidation.lastRuleCannotBeRemoved);
|
||||
});
|
||||
|
||||
it('Delete created policy', () => {
|
||||
cy.get(`[data-testid="delete-action-${policyName}"]`).click({
|
||||
force: true,
|
||||
});
|
||||
|
||||
cy.get('[data-testid="confirmation-text-input"]').type('DELETE');
|
||||
|
||||
cy.get('[data-testid="confirm-button"]').click();
|
||||
|
||||
// Validate deleted policy
|
||||
cy.get('[data-testid="policy-name"]').should('not.contain', policyName);
|
||||
});
|
||||
});
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 { uuid } from '../utils/common';
|
||||
|
||||
export const DEFAULT_POLICIES = {
|
||||
dataConsumerPolicy: 'Data Consumer Policy',
|
||||
dataStewardPolicy: 'Data Steward Policy',
|
||||
organizationPolicy: 'Organization Policy',
|
||||
teamOnlyAccessPolicy: 'Team only access Policy',
|
||||
};
|
||||
|
||||
export const RULE_DETAILS = {
|
||||
resources: 'All',
|
||||
operations: 'All',
|
||||
effect: 'Allow',
|
||||
condition: 'isOwner()',
|
||||
inValidCondition: 'isOwner(',
|
||||
};
|
||||
|
||||
export const ERROR_MESSAGE_VALIDATION = {
|
||||
lastPolicyCannotBeRemoved: 'At least one policy is required in a role',
|
||||
lastRuleCannotBeRemoved: 'At least one rule is required in a policy',
|
||||
};
|
||||
|
||||
export const POLICY_NAME = `Policy-test-${uuid()}`;
|
||||
export const DESCRIPTION = `This is ${POLICY_NAME} description`;
|
||||
|
||||
export const RULE_NAME = `Rule / test-${uuid()}`;
|
||||
export const RULE_DESCRIPTION = `This is ${RULE_NAME} description`;
|
||||
export const UPDATED_DESCRIPTION = 'This is updated description';
|
||||
|
||||
export const NEW_RULE_NAME = `New / Rule-test-${uuid()}`;
|
||||
export const NEW_RULE_DESCRIPTION = `This is ${NEW_RULE_NAME} description`;
|
||||
|
||||
export const UPDATED_RULE_NAME = `New-Rule-test-${uuid()}-updated`;
|
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* 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, Page } from '@playwright/test';
|
||||
import {
|
||||
DEFAULT_POLICIES,
|
||||
DESCRIPTION,
|
||||
ERROR_MESSAGE_VALIDATION,
|
||||
NEW_RULE_DESCRIPTION,
|
||||
NEW_RULE_NAME,
|
||||
POLICY_NAME,
|
||||
RULE_DESCRIPTION,
|
||||
RULE_DETAILS,
|
||||
RULE_NAME,
|
||||
UPDATED_DESCRIPTION,
|
||||
UPDATED_RULE_NAME,
|
||||
} from '../../constant/permission';
|
||||
import { GlobalSettingOptions } from '../../constant/settings';
|
||||
import { descriptionBox, redirectToHomePage } from '../../utils/common';
|
||||
import { validateFormNameFieldInput } from '../../utils/form';
|
||||
import { settingClick } from '../../utils/sidebar';
|
||||
|
||||
// use the admin user to login
|
||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||
|
||||
const addRule = async (
|
||||
page: Page,
|
||||
rulename: string,
|
||||
ruleDescription: string,
|
||||
descriptionIndex: number
|
||||
) => {
|
||||
// Validate form name field input
|
||||
await page.fill('[data-testid="rule-name"]', rulename);
|
||||
|
||||
// Enter rule description
|
||||
await page
|
||||
.locator(descriptionBox)
|
||||
.nth(descriptionIndex)
|
||||
.fill(ruleDescription);
|
||||
|
||||
// Select resource dropdown
|
||||
await page.locator('[data-testid="resources"]').click();
|
||||
|
||||
// Select All
|
||||
await page.locator('.ant-select-tree-checkbox-inner').first().click();
|
||||
|
||||
// Click on operations dropdown
|
||||
await page.locator('[data-testid="operations"]').click();
|
||||
|
||||
// Select operation
|
||||
await page.locator('.ant-select-tree-checkbox-inner').nth(1).click();
|
||||
|
||||
// Click on condition combobox
|
||||
await page.locator('[data-testid="condition"]').click();
|
||||
|
||||
// Select condition
|
||||
await page.locator(`[title="${RULE_DETAILS.condition}"]`).click();
|
||||
|
||||
// Verify condition success
|
||||
await expect(page.locator('[data-testid="condition-success"]')).toContainText(
|
||||
'✅ Valid condition'
|
||||
);
|
||||
|
||||
// Submit
|
||||
await page.locator('[data-testid="submit-btn"]').click();
|
||||
};
|
||||
|
||||
test.describe('Policy page should work properly', () => {
|
||||
test.beforeEach('Visit entity details page', async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
await settingClick(page, GlobalSettingOptions.POLICIES);
|
||||
await page.waitForSelector('[data-testid="loader"]', { state: 'detached' });
|
||||
});
|
||||
|
||||
test('Add new policy with invalid condition', async ({ page }) => {
|
||||
await test.step(
|
||||
'Default Policies and Roles should be displayed',
|
||||
async () => {
|
||||
// Verifying the default roles and policies are present
|
||||
for (const policy of Object.values(DEFAULT_POLICIES)) {
|
||||
const policyElement = page.locator('[data-testid="policy-name"]', {
|
||||
hasText: policy,
|
||||
});
|
||||
|
||||
await expect(policyElement).toBeVisible();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
await test.step('Add new policy', async () => {
|
||||
// Click on add new policy
|
||||
await page.locator('[data-testid="add-policy"]').click();
|
||||
|
||||
await expect(page.locator('[data-testid="inactive-link"]')).toBeVisible();
|
||||
|
||||
// Enter policy name
|
||||
await page.locator('[data-testid="policy-name"]').fill(POLICY_NAME);
|
||||
await validateFormNameFieldInput({
|
||||
page,
|
||||
value: POLICY_NAME,
|
||||
fieldName: 'Name',
|
||||
fieldSelector: '[data-testid="policy-name"]',
|
||||
errorDivSelector: '#name_help',
|
||||
});
|
||||
|
||||
// Enter description
|
||||
await page.locator(descriptionBox).nth(0).fill(DESCRIPTION);
|
||||
|
||||
// Enter rule name
|
||||
await addRule(page, RULE_NAME, RULE_DESCRIPTION, 1);
|
||||
|
||||
// Validate the added policy
|
||||
await expect(page.locator('[data-testid="inactive-link"]')).toHaveText(
|
||||
POLICY_NAME
|
||||
);
|
||||
|
||||
await page.getByText(RULE_NAME, { exact: true }).isVisible();
|
||||
|
||||
// Verify policy description
|
||||
await expect(
|
||||
page
|
||||
.locator(
|
||||
'[data-testid="asset-description-container"] [data-testid="viewer-container"]'
|
||||
)
|
||||
.nth(0)
|
||||
).toContainText(DESCRIPTION);
|
||||
|
||||
// Verify rule description
|
||||
await expect(
|
||||
page
|
||||
.locator(
|
||||
'[data-testid="viewer-container"] > [data-testid="markdown-parser"]'
|
||||
)
|
||||
.nth(1)
|
||||
).toContainText(RULE_DESCRIPTION);
|
||||
|
||||
// Verify other details
|
||||
await page.locator('[data-testid="rule-name"]').click();
|
||||
|
||||
await expect(page.locator('[data-testid="resources"]')).toContainText(
|
||||
RULE_DETAILS.resources
|
||||
);
|
||||
|
||||
await expect(page.locator('[data-testid="operations"]')).toContainText(
|
||||
RULE_DETAILS.operations
|
||||
);
|
||||
|
||||
await expect(page.locator('[data-testid="effect"]')).toContainText(
|
||||
RULE_DETAILS.effect
|
||||
);
|
||||
|
||||
await expect(page.locator('[data-testid="condition"]')).toContainText(
|
||||
RULE_DETAILS.condition
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Edit policy description', async () => {
|
||||
// Click on edit description
|
||||
await page.locator('[data-testid="edit-description"]').click();
|
||||
|
||||
await page
|
||||
.locator(descriptionBox)
|
||||
.fill(`${UPDATED_DESCRIPTION}-${POLICY_NAME}`);
|
||||
|
||||
// Click on save
|
||||
await page.locator('[data-testid="save"]').click();
|
||||
|
||||
// Validate added description
|
||||
await expect(
|
||||
page
|
||||
.locator(
|
||||
'[data-testid="asset-description-container"] [data-testid="viewer-container"]'
|
||||
)
|
||||
.nth(0)
|
||||
).toContainText(`${UPDATED_DESCRIPTION}-${POLICY_NAME}`);
|
||||
});
|
||||
|
||||
await test.step('Add new rule', async () => {
|
||||
// Click on add rule button
|
||||
await page.locator('[data-testid="add-rule"]').click();
|
||||
|
||||
// Add rule (assuming addRule is a function you have defined elsewhere)
|
||||
await addRule(page, NEW_RULE_NAME, NEW_RULE_DESCRIPTION, 0);
|
||||
|
||||
// Validate added rule
|
||||
await page.getByText(RULE_NAME, { exact: true }).isVisible();
|
||||
|
||||
// Verify other details
|
||||
await page.getByText(RULE_NAME, { exact: true }).click();
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="resources"]').last()
|
||||
).toContainText(RULE_DETAILS.resources);
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="operations"]').last()
|
||||
).toContainText(RULE_DETAILS.operations);
|
||||
|
||||
await expect(page.locator('[data-testid="effect"]').last()).toContainText(
|
||||
RULE_DETAILS.effect
|
||||
);
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="condition"]').last()
|
||||
).toContainText(RULE_DETAILS.condition);
|
||||
});
|
||||
|
||||
await test.step('Edit rule name for created Rule', async () => {
|
||||
// Click on new rule manage button
|
||||
await page
|
||||
.locator(`[data-testid="manage-button-${NEW_RULE_NAME}"]`)
|
||||
.click();
|
||||
|
||||
// Click on edit rule button
|
||||
await page.locator('[data-testid="edit-rule"]').click();
|
||||
|
||||
// Enter new name
|
||||
await page.locator('[data-testid="rule-name"]').fill(UPDATED_RULE_NAME);
|
||||
|
||||
// Click on submit button
|
||||
await page.locator('[data-testid="submit-btn"]').click();
|
||||
|
||||
// Verify the URL contains the policy name
|
||||
await expect(page).toHaveURL(new RegExp(POLICY_NAME));
|
||||
|
||||
// Verify the rule name is updated
|
||||
await page.getByText(UPDATED_RULE_NAME, { exact: true }).isVisible();
|
||||
});
|
||||
|
||||
await test.step('Delete new rule', async () => {
|
||||
// Click on new rule manage button
|
||||
await page
|
||||
.locator(`[data-testid="manage-button-${UPDATED_RULE_NAME}"]`)
|
||||
.click();
|
||||
|
||||
// Click on delete rule button
|
||||
await page.locator('[data-testid="delete-rule"]').click();
|
||||
|
||||
await expect(
|
||||
page.getByText(UPDATED_RULE_NAME, { exact: true })
|
||||
).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Delete last rule and validate', async () => {
|
||||
// Click on new rule manage button
|
||||
await page.locator(`[data-testid="manage-button-${RULE_NAME}"]`).click();
|
||||
|
||||
// Click on delete rule button
|
||||
await page.locator('[data-testid="delete-rule"]').click();
|
||||
|
||||
// Validate the error message
|
||||
await expect(page.locator('.Toastify__toast-body')).toContainText(
|
||||
ERROR_MESSAGE_VALIDATION.lastRuleCannotBeRemoved
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Delete created policy', async () => {
|
||||
await settingClick(page, GlobalSettingOptions.POLICIES);
|
||||
await page.waitForSelector('[data-testid="loader"]', {
|
||||
state: 'detached',
|
||||
});
|
||||
// Click on delete action button
|
||||
await page
|
||||
.locator(`[data-testid="delete-action-${POLICY_NAME}"]`)
|
||||
.click({ force: true });
|
||||
|
||||
// Type 'DELETE' in the confirmation text input
|
||||
await page
|
||||
.locator('[data-testid="confirmation-text-input"]')
|
||||
.fill('DELETE');
|
||||
|
||||
// Click on confirm button
|
||||
await page.locator('[data-testid="confirm-button"]').click();
|
||||
|
||||
// Validate deleted policy
|
||||
await expect(
|
||||
page.getByText(POLICY_NAME, { exact: true })
|
||||
).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 { Page } from '@playwright/test';
|
||||
|
||||
export const validateFormNameFieldInput = async ({
|
||||
page,
|
||||
fieldSelector = '#name',
|
||||
checkEmpty = true,
|
||||
checkLong = true,
|
||||
fieldName,
|
||||
value,
|
||||
}: {
|
||||
page: Page;
|
||||
value: string;
|
||||
fieldName: string;
|
||||
errorDivSelector: string;
|
||||
fieldSelector?: string;
|
||||
checkEmpty?: boolean;
|
||||
checkLong?: boolean;
|
||||
}) => {
|
||||
if (checkEmpty) {
|
||||
// Check empty name field message
|
||||
await page.fill(fieldSelector, 'test');
|
||||
await page.locator(fieldSelector).clear();
|
||||
|
||||
await page.getByText(`${fieldName} is required`).isVisible();
|
||||
}
|
||||
|
||||
if (checkLong) {
|
||||
// Check long name field message
|
||||
await page.fill(fieldSelector, 'name'.repeat(33));
|
||||
|
||||
await page
|
||||
.getByText(`${fieldName} size must be between 1 and 128`)
|
||||
.isVisible();
|
||||
|
||||
await page.locator(fieldSelector).clear();
|
||||
}
|
||||
|
||||
await page.fill(fieldSelector, value);
|
||||
};
|
@ -27,6 +27,7 @@ describe('useFqn', () => {
|
||||
(useParams as jest.Mock).mockReturnValue({
|
||||
fqn: 'sample_data.db_sample.schema_sample.dim%2Fclient.',
|
||||
ingestionFQN: 'sample_data.db_sample.schema_sample.dim%2Fclient.',
|
||||
ruleName: 'testing%20%2F%20policy%20rule%20do%20not%20use',
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useFqn());
|
||||
@ -34,6 +35,7 @@ describe('useFqn', () => {
|
||||
expect(result.current).toEqual({
|
||||
fqn: 'sample_data.db_sample.schema_sample.dim/client.',
|
||||
ingestionFQN: 'sample_data.db_sample.schema_sample.dim/client.',
|
||||
ruleName: 'testing / policy rule do not use',
|
||||
});
|
||||
});
|
||||
|
||||
@ -45,6 +47,7 @@ describe('useFqn', () => {
|
||||
expect(result.current).toEqual({
|
||||
fqn: '',
|
||||
ingestionFQN: '',
|
||||
ruleName: '',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -13,17 +13,18 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { getDecodedFqn } from '../utils/StringsUtils';
|
||||
|
||||
type Fqn = { fqn: string; ingestionFQN: string };
|
||||
type Fqn = { fqn: string; ingestionFQN: string; ruleName: string };
|
||||
|
||||
/**
|
||||
* @description Hook to get the decoded fqn and ingestionFQN from the url
|
||||
* @returns {fqn: string, ingestionFQN: string} - fqn and ingestionFQN from the url
|
||||
*/
|
||||
export const useFqn = (): Fqn => {
|
||||
const { fqn, ingestionFQN } = useParams<Fqn>();
|
||||
const { fqn, ingestionFQN, ruleName } = useParams<Fqn>();
|
||||
|
||||
return {
|
||||
fqn: fqn ? getDecodedFqn(fqn) : '',
|
||||
ingestionFQN: ingestionFQN ? getDecodedFqn(ingestionFQN) : '',
|
||||
ruleName: ruleName ? getDecodedFqn(ruleName) : '',
|
||||
};
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ import { compare } from 'fast-json-patch';
|
||||
import { trim } from 'lodash';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import Loader from '../../../components/common/Loader/Loader';
|
||||
import TitleBreadcrumb from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
||||
import PageLayoutV1 from '../../../components/PageLayoutV1/PageLayoutV1';
|
||||
@ -51,8 +51,7 @@ const InitialData: Rule = {
|
||||
const EditRulePage = () => {
|
||||
const { t } = useTranslation();
|
||||
const history = useHistory();
|
||||
const { ruleName } = useParams<{ ruleName: string }>();
|
||||
const { fqn } = useFqn();
|
||||
const { fqn, ruleName } = useFqn();
|
||||
const [isLoading, setLoading] = useState<boolean>(false);
|
||||
const [policy, setPolicy] = useState<Policy>({} as Policy);
|
||||
const [ruleData, setRuleData] = useState<Rule>(InitialData);
|
||||
|
@ -323,7 +323,8 @@ export const getEditPolicyRulePath = (fqn: string, ruleName: string) => {
|
||||
|
||||
path = path
|
||||
.replace(PLACEHOLDER_ROUTE_FQN, getEncodedFqn(fqn))
|
||||
.replace(PLACEHOLDER_RULE_NAME, ruleName);
|
||||
// rule name is same as entity fqn so we need to encode it to pass it as a param
|
||||
.replace(PLACEHOLDER_RULE_NAME, getEncodedFqn(ruleName));
|
||||
|
||||
return path;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user