diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts index 91483d32ebf..73889bd2e30 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/Tour.spec.ts @@ -10,13 +10,102 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { expect, test } from '@playwright/test'; +import { expect, Page, test } from '@playwright/test'; import { UserClass } from '../../support/user/UserClass'; import { performAdminLogin } from '../../utils/admin'; import { redirectToHomePage } from '../../utils/common'; const user = new UserClass(); +const validateTourSteps = async (page: Page) => { + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('1'); + + // step 1 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('2'); + + // step 2 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('3'); + + await page.getByTestId('searchBox').fill('dim_a'); + await page.getByTestId('searchBox').press('Enter'); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('4'); + + // step 3 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('5'); + + await expect( + page.getByTestId('sample_data.ecommerce_db.shopify.dim_address') + ).toBeVisible(); + + // step 4 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('6'); + + // step 5 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('7'); + + // step 6 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('8'); + + // step 7 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('9'); + + // step 8 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('10'); + + await expect( + page.getByTestId('sample_data').getByText('Sample Data') + ).toBeVisible(); + + // step 9 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('11'); + + // step 10 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('12'); + + await expect(page.getByText('Data Observability')).toBeVisible(); + + // step 11 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('13'); + + // step 12 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('14'); + + await expect(page.getByTestId('lineage').getByText('Lineage')).toBeVisible(); + + // step 13 + await page.locator('[data-tour-elem="right-arrow"]').click(); + + await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('15'); + + await page.getByTestId('last-step-button').click(); + await page.getByTestId('saveButton').click(); +}; + test.describe('Tour should work properly', () => { test.beforeAll(async ({ browser }) => { const { apiContext, afterAction } = await performAdminLogin(browser); @@ -35,98 +124,23 @@ test.describe('Tour should work properly', () => { await redirectToHomePage(page); }); - test('All tour steps should work', async ({ page }) => { + test('Tour should work from help section', async ({ page }) => { await page.locator('[data-testid="help-icon"]').click(); await page.getByRole('link', { name: 'Tour', exact: true }).click(); await page.waitForURL('**/tour'); + await validateTourSteps(page); + }); - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('1'); + test('Tour should work from welcome screen', async ({ page }) => { + await page.getByText('Take a product tour to get started!').click(); + await page.waitForURL('**/tour'); - // step 1 - await page.locator('[data-tour-elem="right-arrow"]').click(); + await validateTourSteps(page); + }); - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('2'); - - // step 2 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('3'); - - await page.getByTestId('searchBox').fill('dim_a'); - await page.getByTestId('searchBox').press('Enter'); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('4'); - - // step 3 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('5'); - - await expect( - page.getByTestId('sample_data.ecommerce_db.shopify.dim_address') - ).toBeVisible(); - - // step 4 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('6'); - - // step 5 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('7'); - - // step 6 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('8'); - - // step 7 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('9'); - - // step 8 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('10'); - - await expect( - page.getByTestId('sample_data').getByText('Sample Data') - ).toBeVisible(); - - // step 9 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('11'); - - // step 10 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('12'); - - await expect(page.getByText('Data Observability')).toBeVisible(); - - // step 11 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('13'); - - // step 12 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('14'); - - await expect( - page.getByTestId('lineage').getByText('Lineage') - ).toBeVisible(); - - // step 13 - await page.locator('[data-tour-elem="right-arrow"]').click(); - - await expect(page.locator(`[data-tour-elem="badge"]`)).toHaveText('15'); - - await page.getByTestId('last-step-button').click(); - await page.getByTestId('saveButton').click(); + test('Tour should work from URL directly', async ({ page }) => { + await page.goto('/tour'); + await page.waitForURL('**/tour'); + await validateTourSteps(page); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.interface.ts index 2e21220e2b2..25003ea03e5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.interface.ts @@ -14,5 +14,4 @@ import { App } from '../../../../generated/entity/applications/app'; export type ApplicationsContextType = { applications: App[]; - loading: boolean; }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx index 9a1656bedb1..66187ca0dc1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Settings/Applications/ApplicationsProvider/ApplicationsProvider.tsx @@ -24,13 +24,14 @@ import { usePermissionProvider } from '../../../../context/PermissionProvider/Pe import { App } from '../../../../generated/entity/applications/app'; import { useApplicationStore } from '../../../../hooks/useApplicationStore'; import { getApplicationList } from '../../../../rest/applicationAPI'; +import Loader from '../../../common/Loader/Loader'; import { ApplicationsContextType } from './ApplicationsProvider.interface'; export const ApplicationsContext = createContext({} as ApplicationsContextType); export const ApplicationsProvider = ({ children }: { children: ReactNode }) => { const [applications, setApplications] = useState([]); - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(true); const { permissions } = usePermissionProvider(); const { setApplicationsName } = useApplicationStore(); @@ -54,16 +55,18 @@ export const ApplicationsProvider = ({ children }: { children: ReactNode }) => { useEffect(() => { if (!isEmpty(permissions)) { fetchApplicationList(); + } else { + setLoading(false); } }, [permissions]); const appContext = useMemo(() => { - return { applications, loading }; - }, [applications, loading]); + return { applications }; + }, [applications]); return ( - {children} + {loading ? : children} ); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/context/PermissionProvider/PermissionProvider.tsx b/openmetadata-ui/src/main/resources/ui/src/context/PermissionProvider/PermissionProvider.tsx index 56246d482c9..b04522ae010 100644 --- a/openmetadata-ui/src/main/resources/ui/src/context/PermissionProvider/PermissionProvider.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/context/PermissionProvider/PermissionProvider.tsx @@ -98,7 +98,7 @@ const PermissionProvider: FC = ({ children }) => { } finally { setLoading(false); } - }, [setLoading, setPermissions, redirectToStoredPath]); + }, [redirectToStoredPath]); const fetchEntityPermission = useCallback( async (resource: ResourceEntity, entityId: string) => { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx index 4c1967e8e97..18452131eac 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx @@ -19,7 +19,6 @@ import { useHistory } from 'react-router-dom'; import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder'; import PageHeader from '../../components/PageHeader/PageHeader.component'; import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1'; -import { useApplicationsProvider } from '../../components/Settings/Applications/ApplicationsProvider/ApplicationsProvider'; import SettingItemCard from '../../components/Settings/SettingItemCard/SettingItemCard.component'; import { PAGE_HEADERS } from '../../constants/PageHeaders.constant'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; @@ -39,7 +38,6 @@ const GlobalSettingPage = () => { const { permissions } = usePermissionProvider(); const { isAdminUser } = useAuth(); - const { loading } = useApplicationsProvider(); const settingItems = useMemo( () => @@ -58,7 +56,7 @@ const GlobalSettingPage = () => { return false; }), - [permissions, isAdminUser, loading] + [permissions, isAdminUser] ); const handleSettingItemClick = useCallback((category: string) => { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx index 36980424c02..6c6d8323703 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/MyDataPage/MyDataPage.component.tsx @@ -13,20 +13,13 @@ import { AxiosError } from 'axios'; import { isEmpty } from 'lodash'; -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import RGL, { WidthProvider } from 'react-grid-layout'; import { useTranslation } from 'react-i18next'; import { withActivityFeed } from '../../components/AppRouter/withActivityFeed'; import Loader from '../../components/common/Loader/Loader'; import WelcomeScreen from '../../components/MyData/WelcomeScreen/WelcomeScreen.component'; import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1'; -import { useApplicationsProvider } from '../../components/Settings/Applications/ApplicationsProvider/ApplicationsProvider'; import { KNOWLEDGE_LIST_LENGTH, LOGGED_IN_USER_STORAGE_KEY, @@ -54,14 +47,13 @@ const ReactGridLayout = WidthProvider(RGL); const MyDataPage = () => { const { t } = useTranslation(); const { currentUser, selectedPersona } = useApplicationStore(); - const { loading: applicationsLoading } = useApplicationsProvider(); const { isWelcomeVisible } = useWelcomeStore(); const [followedData, setFollowedData] = useState>([]); const [followedDataCount, setFollowedDataCount] = useState(0); const [isLoadingOwnedData, setIsLoadingOwnedData] = useState(false); const [isLoading, setIsLoading] = useState(true); const [layout, setLayout] = useState>([]); - const isMounted = useRef(false); + const [showWelcomeScreen, setShowWelcomeScreen] = useState(false); const [isAnnouncementLoading, setIsAnnouncementLoading] = useState(true); @@ -116,15 +108,14 @@ const MyDataPage = () => { }; useEffect(() => { - !applicationsLoading && fetchDocument(); - }, [selectedPersona, applicationsLoading]); + fetchDocument(); + }, [selectedPersona]); useEffect(() => { - isMounted.current = true; updateWelcomeScreen(!usernameExistsInCookie && isWelcomeVisible); return () => updateWelcomeScreen(false); - }, [isWelcomeVisible]); + }, []); const fetchUserFollowedData = async () => { if (!currentUser?.id) { @@ -205,7 +196,7 @@ const MyDataPage = () => { // call the hook to set the direction of the grid layout useGridLayoutDirection(isLoading); - if (isLoading || applicationsLoading) { + if (isLoading) { return ; }