diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts index c53c42e60b8..e2f13affea7 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts @@ -10,7 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import test, { expect } from '@playwright/test'; +import base, { expect, Page } from '@playwright/test'; import { Operation } from 'fast-json-patch'; import { get } from 'lodash'; import { SidebarItem } from '../../constant/sidebar'; @@ -40,11 +40,53 @@ import { import { sidebarClick } from '../../utils/sidebar'; import { performUserLogin, visitUserProfilePage } from '../../utils/user'; -test.describe('Domains', () => { - test.use({ storageState: 'playwright/.auth/admin.json' }); +const user = new UserClass(); +const domain = new Domain(); + +const test = base.extend<{ + page: Page; + userPage: Page; +}>({ + page: async ({ browser }, use) => { + const { page } = await performAdminLogin(browser); + await use(page); + await page.close(); + }, + userPage: async ({ browser }, use) => { + const page = await browser.newPage(); + await user.login(page); + await use(page); + await page.close(); + }, +}); + +test.describe('Domains', () => { test.slow(true); + test.beforeAll('Setup pre-requests', async ({ browser }) => { + const { apiContext, afterAction } = await performAdminLogin(browser); + await user.create(apiContext); + + await domain.create(apiContext); + + await domain.patch({ + apiContext, + patchData: [ + { + op: 'add', + path: '/owners/0', + value: { + id: user.responseData.id, + type: 'user', + }, + }, + ], + }); + + await afterAction(); + }); + test.beforeEach('Visit home page', async ({ page }) => { await redirectToHomePage(page); }); @@ -389,6 +431,41 @@ test.describe('Domains', () => { await afterAction(); } }); + + test('Domain owner should able to edit description of domain', async ({ + page, + userPage, + }) => { + const { afterAction, apiContext } = await getApiContext(page); + try { + await sidebarClick(userPage, SidebarItem.DOMAIN); + await selectDomain(userPage, domain.data); + + await expect(userPage.getByTestId('edit-description')).toBeInViewport(); + + await userPage.getByTestId('edit-description').click(); + + await expect(userPage.getByTestId('editor')).toBeInViewport(); + + const descriptionInputBox = '.om-block-editor[contenteditable="true"]'; + + await userPage.fill(descriptionInputBox, 'test description'); + + await userPage.getByTestId('save').click(); + + await userPage.waitForTimeout(3000); + + const descriptionBox = '.om-block-editor[contenteditable="false"]'; + + await expect(userPage.locator(descriptionBox)).toHaveText( + 'test description' + ); + } finally { + await domain?.delete(apiContext); + await user.delete(apiContext); + } + await afterAction(); + }); }); test.describe('Domains Rbac', () => { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/domain/Domain.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/domain/Domain.ts index e3cbee7ed96..93a982f08ab 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/domain/Domain.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/domain/Domain.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import { APIRequestContext } from '@playwright/test'; +import { Operation } from 'fast-json-patch'; import { uuid } from '../../utils/common'; type UserTeamRef = { @@ -72,4 +73,28 @@ export class Domain { return response.body; } + + async patch({ + apiContext, + patchData, + }: { + apiContext: APIRequestContext; + patchData: Operation[]; + }) { + const response = await apiContext.patch( + `/api/v1/domains/${this.responseData?.id}`, + { + data: patchData, + headers: { + 'Content-Type': 'application/json-patch+json', + }, + } + ); + + this.responseData = await response.json(); + + return { + entity: this.responseData, + }; + } } diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/domain/SubDomain.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/domain/SubDomain.ts index dabe1cafb84..41d5b09c9b3 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/domain/SubDomain.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/domain/SubDomain.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import { APIRequestContext } from '@playwright/test'; +import { Operation } from 'fast-json-patch'; import { uuid } from '../../utils/common'; import { Domain } from './Domain'; @@ -76,4 +77,28 @@ export class SubDomain { return response.body; } + + async patch({ + apiContext, + patchData, + }: { + apiContext: APIRequestContext; + patchData: Operation[]; + }) { + const response = await apiContext.patch( + `/api/v1/domains/${this.responseData?.id}`, + { + data: patchData, + headers: { + 'Content-Type': 'application/json-patch+json', + }, + } + ); + + this.responseData = await response.json(); + + return { + entity: this.responseData, + }; + } } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx index b57c43f7503..bf3513bd515 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataProducts/DataProductsDetailsPage/DataProductsDetailsPage.component.tsx @@ -411,14 +411,9 @@ const DataProductsDetailsPage = ({ children: ( onUpdate(data as DataProduct) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx index f9fe1a18d42..58953c2f9e5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainDetailsPage/DomainDetailsPage.component.tsx @@ -122,7 +122,7 @@ const DomainDetailsPage = ({ }: DomainDetailsPageProps) => { const { t } = useTranslation(); const [form] = useForm(); - const { getEntityPermission } = usePermissionProvider(); + const { getEntityPermission, permissions } = usePermissionProvider(); const history = useHistory(); const { tab: activeTab, version } = useParams<{ tab: string; version: string }>(); @@ -202,21 +202,29 @@ const DomainDetailsPage = ({ }, [domainPermission]); const addButtonContent = [ - { - label: t('label.asset-plural'), - key: '1', - onClick: () => setAssetModalVisible(true), - }, - { - label: t('label.sub-domain-plural'), - key: '2', - onClick: () => setShowAddSubDomainModal(true), - }, - { - label: t('label.data-product-plural'), - key: '3', - onClick: () => setShowAddDataProductModal(true), - }, + ...(domainPermission.Create + ? [ + { + label: t('label.asset-plural'), + key: '1', + onClick: () => setAssetModalVisible(true), + }, + { + label: t('label.sub-domain-plural'), + key: '2', + onClick: () => setShowAddSubDomainModal(true), + }, + ] + : []), + ...(permissions.dataProduct.Create + ? [ + { + label: t('label.data-product-plural'), + key: '3', + onClick: () => setShowAddDataProductModal(true), + }, + ] + : []), ]; const fetchSubDomains = useCallback(async () => { @@ -511,6 +519,7 @@ const DomainDetailsPage = ({ onUpdate(data as Domain)} /> ), @@ -667,7 +676,7 @@ const DomainDetailsPage = ({
- {!isVersionsView && domainPermission.Create && ( + {!isVersionsView && addButtonContent.length > 0 && ( { const { t } = useTranslation(); - const { permissions } = usePermissionProvider(); const [isDescriptionEditable, setIsDescriptionEditable] = useState(false); const [editDomainType, setEditDomainType] = useState(false); @@ -72,40 +67,40 @@ const DocumentationTab = ({ ? ResourceEntity.DOMAIN : ResourceEntity.DATA_PRODUCT; - const { editDescriptionPermission, editOwnerPermission, editAllPermission } = - useMemo(() => { - if (isVersionsView) { - return { - editDescriptionPermission: false, - editOwnerPermission: false, - editAllPermission: false, - }; - } - - const editDescription = checkPermission( - Operation.EditDescription, - resourceType, - permissions - ); - - const editOwner = checkPermission( - Operation.EditOwners, - resourceType, - permissions - ); - - const editAll = checkPermission( - Operation.EditAll, - resourceType, - permissions - ); - + const { + editDescriptionPermission, + editOwnerPermission, + editAllPermission, + editCustomAttributePermission, + viewAllPermission, + } = useMemo(() => { + if (isVersionsView) { return { - editDescriptionPermission: editDescription || editAll, - editOwnerPermission: editOwner || editAll, - editAllPermission: editAll, + editDescriptionPermission: false, + editOwnerPermission: false, + editAllPermission: false, + editCustomAttributePermission: false, }; - }, [permissions, isVersionsView, resourceType]); + } + + const editDescription = permissions?.EditDescription; + + const editOwner = permissions?.EditOwners; + + const editAll = permissions?.EditAll; + + const editCustomAttribute = permissions?.EditCustomFields; + + const viewAll = permissions?.ViewAll; + + return { + editDescriptionPermission: editAll || editDescription, + editOwnerPermission: editAll || editOwner, + editAllPermission: editAll, + editCustomAttributePermission: editAll || editCustomAttribute, + viewAllPermission: viewAll, + }; + }, [permissions, isVersionsView, resourceType]); const description = useMemo( () => diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.interface.ts index e10500799b5..faf3bb36380 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.interface.ts @@ -10,6 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { OperationPermission } from '../../../../context/PermissionProvider/PermissionProvider.interface'; import { DataProduct } from '../../../../generated/entity/domains/dataProduct'; import { Domain } from '../../../../generated/entity/domains/domain'; @@ -19,8 +20,7 @@ export interface DocumentationTabProps { isVersionsView?: boolean; type?: DocumentationEntity; onExtensionUpdate?: (updatedDataProduct: DataProduct) => Promise; - editCustomAttributePermission?: boolean; - viewAllPermission?: boolean; + permissions?: OperationPermission; } export enum DocumentationEntity { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.test.tsx index f2fe4e09640..dbdd8f3222b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Domain/DomainTabs/DocumentationTab/DocumentationTab.test.tsx @@ -14,6 +14,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; import { MemoryRouter } from 'react-router-dom'; import { MOCK_DOMAIN } from '../../../../mocks/Domains.mock'; +import { MOCK_PERMISSIONS } from '../../../../mocks/Glossary.mock'; import DocumentationTab from './DocumentationTab.component'; // Mock the onUpdate function @@ -23,6 +24,7 @@ const defaultProps = { domain: MOCK_DOMAIN, onUpdate: mockOnUpdate, isVersionsView: false, + permissions: MOCK_PERMISSIONS, }; jest.mock('../../../common/EntityDescription/DescriptionV1', () => { @@ -33,10 +35,6 @@ jest.mock('../../../common/ProfilePicture/ProfilePicture', () => jest.fn().mockReturnValue(<>ProfilePicture) ); -jest.mock('../../../../utils/PermissionsUtils', () => ({ - checkPermission: jest.fn().mockReturnValue(true), -})); - describe('DocumentationTab', () => { it('should render the initial content', () => { const { getByTestId } = render(, {