From 77b8ca4dc2282b72a1e5cd0a049a8a7ca8ef422e Mon Sep 17 00:00:00 2001 From: Ryan Willis Date: Mon, 19 May 2025 11:45:01 -0700 Subject: [PATCH] feat: improve design doc samples [INS-5526] (#8719) * feat: improve design doc samples [INS-5526] * update to latest petstore, fixing lint errors --- .../tests/smoke/openapi.test.ts | 5 +- .../src/ui/components/design-empty-state.tsx | 148 ++- .../src/ui/components/example-openapi-spec.ts | 617 ------------ .../ui/components/example-openapi-specs.ts | 934 ++++++++++++++++++ packages/insomnia/src/ui/routes/design.tsx | 167 ++-- 5 files changed, 1120 insertions(+), 751 deletions(-) delete mode 100644 packages/insomnia/src/ui/components/example-openapi-spec.ts create mode 100644 packages/insomnia/src/ui/components/example-openapi-specs.ts diff --git a/packages/insomnia-smoke-test/tests/smoke/openapi.test.ts b/packages/insomnia-smoke-test/tests/smoke/openapi.test.ts index 88a362ace4..5c95761c24 100644 --- a/packages/insomnia-smoke-test/tests/smoke/openapi.test.ts +++ b/packages/insomnia-smoke-test/tests/smoke/openapi.test.ts @@ -5,10 +5,11 @@ import { test } from '../../playwright/test'; test('can render Spectral OpenAPI lint errors', async ({ page }) => { await page.getByRole('button', { name: 'Create document' }).click(); await page.getByRole('dialog').getByRole('button', { name: 'Create' }).click(); - await page.click('text=start from boilerplate'); + await page.click('text=Use example'); + await page.click('text=Pet Store'); const codeEditor = page.locator('.pane-one'); - await expect.soft(codeEditor).toContainText('openapi: 3.0.0'); + await expect.soft(codeEditor).toContainText('openapi: 3.0.4'); // Cause a lint error await page.locator('[data-testid="CodeEditor"] >> text=info').click(); diff --git a/packages/insomnia/src/ui/components/design-empty-state.tsx b/packages/insomnia/src/ui/components/design-empty-state.tsx index 89d3085a74..48c6b9092f 100644 --- a/packages/insomnia/src/ui/components/design-empty-state.tsx +++ b/packages/insomnia/src/ui/components/design-empty-state.tsx @@ -5,6 +5,7 @@ import { Button, Heading, Menu, MenuItem, MenuTrigger, Popover } from 'react-ari import { documentationLinks } from '../../common/documentation'; import { selectFileOrFolder } from '../../common/select-file-or-folder'; +import { blankSpec as emptySpec, petStoreSpec, todoSpec } from './example-openapi-specs'; import { Icon } from './icon'; import { showPrompt } from './modals'; @@ -13,6 +14,35 @@ interface Props { } export const DesignEmptyState: FC = ({ onImport }) => { + const exampleSpecs = [ + { + id: 'petstore-spec', + name: 'Pet Store', + icon: 'cat', + action: async () => onImport(petStoreSpec), + }, + { + id: 'todo-spec', + name: 'Todo List', + icon: 'list-check', + action: async () => onImport(todoSpec), + }, + { + id: 'separator1', + }, + { + id: 'empty-spec', + name: 'Empty', + icon: 'file', + action: async () => onImport(emptySpec), + }, + ] satisfies { + id: string; + name?: string; + icon?: IconName; + action?: () => void; + }[]; + const importActionsList = [ { id: 'import-file', @@ -63,59 +93,77 @@ export const DesignEmptyState: FC = ({ onImport }) => { return (
- - - Enter an OpenAPI specification here + + + Enter your OpenAPI specification here -
+

- - - Or import an existing OpenAPI spec or - - -

- - - - { - importActionsList.find(({ id }) => key === id)?.action(); - }} - items={importActionsList} - className="min-w-max select-none overflow-y-auto rounded-md border border-solid border-[--hl-sm] bg-[--color-bg] py-2 text-sm shadow-lg focus:outline-none" - > - {item => ( - + Or quick start: +
+ +
-
-
+ + Use example + + + + { + exampleSpecs.find(({ id }) => key === id)?.action?.(); + }} + items={exampleSpecs} + className="min-w-max cursor-pointer select-none overflow-y-auto rounded-md border border-solid border-[--hl-sm] bg-[--color-bg] text-sm shadow-lg focus:outline-none" + > + {item => + item.id.startsWith('separator') ? ( + + ) : ( + + {item.icon && } + {item.name} + + ) + } + + + + + +
+
+

-
-
- - - -
- {rulesetPath ? ( - -

Using ruleset from

- {rulesetPath} -
- ) : ( - -

Using default OAS ruleset.

-

- To use a custom ruleset add a .spectral.yaml file to the root - of your git repository -

-
- )} + {apiSpec.contents ? ( +
+
+ + + +
+ {rulesetPath ? ( + +

Using ruleset from

+ {rulesetPath} +
+ ) : ( + +

Using default OAS ruleset.

+

+ To use a custom ruleset add a .spectral.yaml file to the + root of your git repository +

+
+ )} +
+
+
+ {lintErrors.length > 0 && ( +
+ + {lintErrors.length}
- - - {lintErrors.length > 0 && ( -
- - {lintErrors.length} -
- )} - {lintWarnings.length > 0 && ( -
- - {lintWarnings.length} -
- )} - {lintMessages.length === 0 && apiSpec.contents && ( -
- - No lint problems -
- )} - - {lintMessages.length > 0 && ( - + )} + {lintWarnings.length > 0 && ( +
+ + {lintWarnings.length} +
+ )} + {lintMessages.length === 0 && apiSpec.contents && ( +
+ + No lint problems +
+ )} + + {lintMessages.length > 0 && ( + + )} +
+ {isLintPaneOpen && ( + { + const listIndex = parseInt(index.toString(), 10); + const lintMessage = lintMessages[listIndex]; + handleScrollToLintMessage(lintMessage); + }} + items={lintMessages.map((message, index) => ({ + ...message, + id: index, + value: message, + }))} + > + {item => ( + + + {item.message} + [Ln {item.line}] + + )} + )}
- {isLintPaneOpen && ( - { - const listIndex = parseInt(index.toString(), 10); - const lintMessage = lintMessages[listIndex]; - handleScrollToLintMessage(lintMessage); - }} - items={lintMessages.map((message, index) => ({ - ...message, - id: index, - value: message, - }))} - > - {item => ( - - - {item.message} - [Ln {item.line}] - - )} - - )} -
+ ) : null}
{isSpecPaneOpen && (