From 21ed929f8a52089adae441233db918afe75aa7e5 Mon Sep 17 00:00:00 2001 From: Andrew Ballantyne Date: Wed, 20 Sep 2023 12:35:20 -0400 Subject: [PATCH] Revert "Revamp empty state in Model Serving Global" This reverts commit 2b3949d7b8bb73f17c9f265f986ea0c1fbadaf2f. --- docs/architecture.md | 8 +++- .../integration/hooks/useFetchState.spec.ts | 17 ++++--- .../clusterSettings/ClusterSettings.spec.ts | 5 ++- .../modelServing/ModelServingGlobal.spec.ts | 42 +++++------------ .../ModelServingGlobal.stories.tsx | 45 ------------------- .../modelServing/ServingRuntimeList.spec.ts | 7 +-- .../pages/projects/ProjectDetails.spec.ts | 9 ++-- .../pages/projects/ProjectView.spec.ts | 13 ++++-- frontend/src/__tests__/integration/utils.ts | 2 - .../screens/global/EmptyModelServing.tsx | 26 ++++------- frontend/tsconfig.json | 3 +- 11 files changed, 61 insertions(+), 116 deletions(-) delete mode 100644 frontend/src/__tests__/integration/utils.ts diff --git a/docs/architecture.md b/docs/architecture.md index 7e10452388..564a3af313 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -196,7 +196,9 @@ export const EditModel = { import { test, expect } from '@playwright/test'; test('Create project', async ({ page }) => { - await page.goto(navigateToStory('projects-projectview', 'create-project')); + await page.goto( + './iframe.html?id=tests-stories-pages-projects-projectview--create-project&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Create data science project'); @@ -215,7 +217,9 @@ test('Create project', async ({ page }) => { To run storybook UI: `cd ./frontend && npm run storybook` ```ts -await page.goto(navigateToStory('projects-projectview', 'create-project')); +await page.goto( + './iframe.html?id=tests-stories-pages-projects-projectview--create-project&viewMode=story', +); ``` 6. Wait for the page to load and the story to settle before performing any assertions or actions. Use `page.waitForSelector()` to wait for a specific element to appear as an indication of the story being loaded. diff --git a/frontend/src/__tests__/integration/hooks/useFetchState.spec.ts b/frontend/src/__tests__/integration/hooks/useFetchState.spec.ts index eae447c826..940f18088e 100644 --- a/frontend/src/__tests__/integration/hooks/useFetchState.spec.ts +++ b/frontend/src/__tests__/integration/hooks/useFetchState.spec.ts @@ -1,8 +1,9 @@ import { test, expect } from '@playwright/test'; -import { navigateToStory } from '~/__tests__/integration/utils'; test('Success', async ({ page }) => { - await page.goto(navigateToStory('hooks-usefetchstate', 'success')); + await page.goto( + './iframe.html?args=&id=tests-integration-hooks-usefetchstate--success&viewMode=story', + ); // wait 2 seconds to settle await new Promise((resolve) => setTimeout(resolve, 2000)); @@ -15,7 +16,9 @@ test('Success', async ({ page }) => { }); test('Failure', async ({ page }) => { - await page.goto(navigateToStory('hooks-usefetchstate', 'failure')); + await page.goto( + './iframe.html?args=&id=tests-integration-hooks-usefetchstate--failure&viewMode=story', + ); // wait 2 seconds to settle await new Promise((resolve) => setTimeout(resolve, 2000)); @@ -31,7 +34,9 @@ test('Failure', async ({ page }) => { }); test('Stable', async ({ page }) => { - await page.goto(navigateToStory('hooks-usefetchstate', 'stable')); + await page.goto( + './iframe.html?args=&id=tests-integration-hooks-usefetchstate--stable&viewMode=story', + ); // wait 2 seconds to settle await new Promise((resolve) => setTimeout(resolve, 2000)); @@ -71,7 +76,9 @@ test('Stable', async ({ page }) => { }); test('Refresh rate', async ({ page }) => { - await page.goto(navigateToStory('hooks-usefetchstate', 'refresh-rate')); + await page.goto( + './iframe.html?args=&id=tests-integration-hooks-usefetchstate--refresh-rate&viewMode=story', + ); // wait 2 seconds to settle await new Promise((resolve) => setTimeout(resolve, 2000)); diff --git a/frontend/src/__tests__/integration/pages/clusterSettings/ClusterSettings.spec.ts b/frontend/src/__tests__/integration/pages/clusterSettings/ClusterSettings.spec.ts index b4b861499a..0a68a8faca 100644 --- a/frontend/src/__tests__/integration/pages/clusterSettings/ClusterSettings.spec.ts +++ b/frontend/src/__tests__/integration/pages/clusterSettings/ClusterSettings.spec.ts @@ -1,8 +1,9 @@ import { test, expect } from '@playwright/test'; -import { navigateToStory } from '~/__tests__/integration/utils'; test('Cluster settings', async ({ page }) => { - await page.goto(navigateToStory('pages-clustersettings-clustersettings', 'default')); + await page.goto( + './iframe.html?args=&id=tests-integration-pages-clustersettings-clustersettings--default&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Save changes'); const submitButton = page.locator('[data-id="submit-cluster-settings"]'); diff --git a/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.spec.ts b/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.spec.ts index 7a8aa986e6..dee2ce86ae 100644 --- a/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.spec.ts +++ b/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.spec.ts @@ -1,36 +1,10 @@ import { test, expect } from '@playwright/test'; -import { navigateToStory } from '~/__tests__/integration/utils'; -test('Empty State No Serving Runtime', async ({ page }) => { - await page.goto( - navigateToStory('pages-modelserving-modelservingglobal', 'empty-state-no-serving-runtime'), - ); - - // wait for page to load - await page.waitForSelector('text=No deployed models yet'); - - // Test that the button is enabled - await expect(page.getByRole('button', { name: 'Go to the Projects page' })).toBeTruthy(); -}); - -test('Empty State No Inference Service', async ({ page }) => { +test('Delete model', async ({ page }) => { await page.goto( - navigateToStory('pages-modelserving-modelservingglobal', 'empty-state-no-inference-service'), + './iframe.html?args=&id=tests-integration-pages-modelserving-modelservingglobal--delete-model&viewMode=story', ); - // wait for page to load - await page.waitForSelector('text=No deployed models'); - - // Test that the button is enabled - await page.getByRole('button', { name: 'Deploy model' }).click(); - - // test that you can not submit on empty - await expect(await page.getByRole('button', { name: 'Deploy' })).toBeDisabled(); -}); - -test('Delete model', async ({ page }) => { - await page.goto(navigateToStory('pages-modelserving-modelservingglobal', 'delete-model')); - // wait for page to load await page.waitForSelector('text=Delete deployed model?'); @@ -45,7 +19,9 @@ test('Delete model', async ({ page }) => { }); test('Edit model', async ({ page }) => { - await page.goto(navigateToStory('pages-modelserving-modelservingglobal', 'edit-model')); + await page.goto( + './iframe.html?args=&id=tests-integration-pages-modelserving-modelservingglobal--edit-model&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Deploy model'); @@ -77,7 +53,9 @@ test('Edit model', async ({ page }) => { }); test('Create model', async ({ page }) => { - await page.goto(navigateToStory('pages-modelserving-modelservingglobal', 'deploy-model')); + await page.goto( + './iframe.html?args=&id=tests-integration-pages-modelserving-modelservingglobal--deploy-model&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Deploy model'); @@ -116,7 +94,9 @@ test('Create model', async ({ page }) => { }); test('Create model error', async ({ page }) => { - await page.goto(navigateToStory('pages-modelserving-modelservingglobal', 'deploy-model')); + await page.goto( + './iframe.html?args=&id=tests-integration-pages-modelserving-modelservingglobal--deploy-model&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Deploy model'); diff --git a/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.stories.tsx b/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.stories.tsx index 348d608ea5..488b034124 100644 --- a/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.stories.tsx +++ b/frontend/src/__tests__/integration/pages/modelServing/ModelServingGlobal.stories.tsx @@ -63,51 +63,6 @@ const Template: StoryFn = (args) => ( ); -export const EmptyStateNoServingRuntime: StoryObj = { - render: Template, - - parameters: { - msw: { - handlers: [ - rest.get( - 'api/k8s/apis/serving.kserve.io/v1alpha1/namespaces/test-project/servingruntimes', - (req, res, ctx) => res(ctx.json(mockK8sResourceList([]))), - ), - rest.get( - 'api/k8s/apis/serving.kserve.io/v1beta1/namespaces/test-project/inferenceservices', - (req, res, ctx) => res(ctx.json(mockK8sResourceList([]))), - ), - rest.get('/api/k8s/apis/project.openshift.io/v1/projects', (req, res, ctx) => - res(ctx.json(mockK8sResourceList([mockProjectK8sResource({})]))), - ), - ], - }, - }, -}; - -export const EmptyStateNoInferenceServices: StoryObj = { - render: Template, - - parameters: { - msw: { - handlers: [ - rest.get( - 'api/k8s/apis/serving.kserve.io/v1alpha1/namespaces/test-project/servingruntimes', - (req, res, ctx) => - res(ctx.json(mockK8sResourceList([mockServingRuntimeK8sResource({})]))), - ), - rest.get( - 'api/k8s/apis/serving.kserve.io/v1beta1/namespaces/test-project/inferenceservices', - (req, res, ctx) => res(ctx.json(mockK8sResourceList([]))), - ), - rest.get('/api/k8s/apis/project.openshift.io/v1/projects', (req, res, ctx) => - res(ctx.json(mockK8sResourceList([mockProjectK8sResource({})]))), - ), - ], - }, - }, -}; - export const EditModel: StoryObj = { render: Template, diff --git a/frontend/src/__tests__/integration/pages/modelServing/ServingRuntimeList.spec.ts b/frontend/src/__tests__/integration/pages/modelServing/ServingRuntimeList.spec.ts index 585f794d0d..486bc8233c 100644 --- a/frontend/src/__tests__/integration/pages/modelServing/ServingRuntimeList.spec.ts +++ b/frontend/src/__tests__/integration/pages/modelServing/ServingRuntimeList.spec.ts @@ -1,8 +1,9 @@ import { test, expect } from '@playwright/test'; -import { navigateToStory } from '~/__tests__/integration/utils'; test('Deploy model', async ({ page }) => { - await page.goto(navigateToStory('pages-modelserving-servingruntimelist', 'deploy-model')); + await page.goto( + './iframe.html?args=&id=tests-integration-pages-modelserving-servingruntimelist--deploy-model&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Deploy model'); @@ -37,7 +38,7 @@ test('Deploy model', async ({ page }) => { test('Legacy Serving Runtime', async ({ page }) => { await page.goto( - navigateToStory('pages-modelserving-servingruntimelist', 'list-available-models'), + './iframe.html?args=&id=tests-integration-pages-modelserving-servingruntimelist--list-available-models&viewMode=story', ); // wait for page to load diff --git a/frontend/src/__tests__/integration/pages/projects/ProjectDetails.spec.ts b/frontend/src/__tests__/integration/pages/projects/ProjectDetails.spec.ts index a89ca6bf86..bb17017d8e 100644 --- a/frontend/src/__tests__/integration/pages/projects/ProjectDetails.spec.ts +++ b/frontend/src/__tests__/integration/pages/projects/ProjectDetails.spec.ts @@ -1,8 +1,9 @@ import { test, expect } from '@playwright/test'; -import { navigateToStory } from '~/__tests__/integration/utils'; test('Empty project', async ({ page }) => { - await page.goto(navigateToStory('pages-projects-projectdetails', 'empty-details-page')); + await page.goto( + './iframe.html?args=&id=tests-integration-pages-projects-projectdetails--empty-details-page&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=No model servers'); @@ -15,7 +16,9 @@ test('Empty project', async ({ page }) => { }); test('Non-empty project', async ({ page }) => { - await page.goto(navigateToStory('pages-projects-projectdetails', 'default')); + await page.goto( + './iframe.html?id=tests-integration-pages-projects-projectdetails--default&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Test Notebook'); diff --git a/frontend/src/__tests__/integration/pages/projects/ProjectView.spec.ts b/frontend/src/__tests__/integration/pages/projects/ProjectView.spec.ts index 3ded1a4dd2..7f4800427b 100644 --- a/frontend/src/__tests__/integration/pages/projects/ProjectView.spec.ts +++ b/frontend/src/__tests__/integration/pages/projects/ProjectView.spec.ts @@ -1,8 +1,9 @@ import { test, expect } from '@playwright/test'; -import { navigateToStory } from '~/__tests__/integration/utils'; test('Create project', async ({ page }) => { - await page.goto(navigateToStory('pages-projects-projectview', 'create-project')); + await page.goto( + './iframe.html?id=tests-integration-pages-projects-projectview--create-project&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Create data science project'); @@ -51,7 +52,9 @@ test('Create project', async ({ page }) => { }); test('Edit project', async ({ page }) => { - await page.goto(navigateToStory('pages-projects-projectview', 'edit-project')); + await page.goto( + './iframe.html?id=tests-integration-pages-projects-projectview--edit-project&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Edit data science project'); @@ -68,7 +71,9 @@ test('Edit project', async ({ page }) => { }); test('Delete project', async ({ page }) => { - await page.goto(navigateToStory('pages-projects-projectview', 'delete-project')); + await page.goto( + './iframe.html?id=tests-integration-pages-projects-projectview--delete-project&viewMode=story', + ); // wait for page to load await page.waitForSelector('text=Delete project?'); diff --git a/frontend/src/__tests__/integration/utils.ts b/frontend/src/__tests__/integration/utils.ts deleted file mode 100644 index 6c7a2a8f22..0000000000 --- a/frontend/src/__tests__/integration/utils.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const navigateToStory = (folder: string, storyId: string) => - `./iframe.html?args=&id=tests-integration-${folder}--${storyId}&viewMode=story`; diff --git a/frontend/src/pages/modelServing/screens/global/EmptyModelServing.tsx b/frontend/src/pages/modelServing/screens/global/EmptyModelServing.tsx index afe0a54481..4bd7471bd9 100644 --- a/frontend/src/pages/modelServing/screens/global/EmptyModelServing.tsx +++ b/frontend/src/pages/modelServing/screens/global/EmptyModelServing.tsx @@ -1,13 +1,6 @@ import * as React from 'react'; -import { - Button, - EmptyState, - EmptyStateBody, - EmptyStateIcon, - EmptyStateVariant, - Title, -} from '@patternfly/react-core'; -import { PlusCircleIcon, WrenchIcon } from '@patternfly/react-icons'; +import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, Title } from '@patternfly/react-core'; +import { PlusCircleIcon } from '@patternfly/react-icons'; import { useNavigate } from 'react-router-dom'; import { ModelServingContext } from '~/pages/modelServing/ModelServingContext'; import ServeModelButton from './ServeModelButton'; @@ -20,17 +13,16 @@ const EmptyModelServing: React.FC = () => { if (servingRuntimes.length === 0) { return ( - - + + - No deployed models yet + No model servers - To get started, deploy a model from the Models and model servers section - of a project. + Before deploying a model, you must first configure a model server. - ); @@ -40,7 +32,7 @@ const EmptyModelServing: React.FC = () => { - No deployed models + No deployed models. To get started, use existing model servers to serve a model. diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index e584ca32d3..32c295a529 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -16,9 +16,8 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, - "baseUrl": "./src", "paths": { - "~/*": ["./*"] + "~/*": ["./src/*"] }, "importHelpers": true, "skipLibCheck": true