-
Notifications
You must be signed in to change notification settings - Fork 7
feat: Add 'Code Snippets' to the Playground's Query bar (4007) #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import { test, expect } from '../../playwright'; | ||
|
|
||
| const DESKTOP = { width: 1280, height: 900 }; | ||
|
|
||
| test.describe('Playground query bar — code snippet', () => { | ||
| test.use({ viewport: DESKTOP }); | ||
|
|
||
| test.beforeEach(async ({ playground }) => { | ||
| await playground.open('bottom'); | ||
| }); | ||
|
|
||
| test('the query bar offers an icon-only snippet control that opens the snippet modal', async ({ playground }) => { | ||
| await playground.openRequest('get users'); | ||
|
|
||
| const { codeSnippet } = playground; | ||
| await expect(codeSnippet.iconTrigger).toBeVisible(); | ||
| await expect(codeSnippet.iconTrigger).toHaveAttribute('aria-label', 'Generate Code'); | ||
| // Icon only — the code box lives in the modal. | ||
| await expect(codeSnippet.code).toHaveCount(0); | ||
|
|
||
| await codeSnippet.openFromIcon(); | ||
| await expect(codeSnippet.modalCode).toContainText('curl'); | ||
| }); | ||
|
|
||
| test('switches languages inside the modal', async ({ playground }) => { | ||
| await playground.openRequest('get users'); | ||
| await playground.codeSnippet.openFromIcon(); | ||
|
|
||
| await playground.codeSnippet.selectModalLanguage('python'); | ||
| await expect(playground.codeSnippet.modalLanguageTab('python')).toHaveAttribute('aria-selected', 'true'); | ||
| await expect(playground.codeSnippet.modalCode).toContainText('requests'); | ||
| }); | ||
|
|
||
| test('the snippet url substitutes filled path params and keeps unfilled placeholders', async ({ | ||
| page, | ||
| playground | ||
| }) => { | ||
| await playground.openRequest('Jokes'); | ||
| await playground.codeSnippet.openFromIcon(); | ||
| await expect(playground.codeSnippet.modalCode).toContainText('/posts/1'); | ||
| await page.keyboard.press('Escape'); | ||
|
|
||
| // A fresh `:commentId` segment is a path param with no value yet. | ||
| await playground.urlInput.click(); | ||
| await page.keyboard.press('End'); | ||
| await page.keyboard.type('/:commentId'); | ||
|
|
||
| await playground.codeSnippet.openFromIcon(); | ||
| // Empty path params keep their placeholder instead of collapsing. | ||
| await expect(playground.codeSnippet.modalCode).toContainText('/posts/1/:commentId'); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import React from 'react'; | ||
| import { describe, it, expect } from 'vitest'; | ||
| import type { HttpRequest } from '@opencollection/types/requests/http'; | ||
| import { useRenderToDom } from '@/hooks/useRenderToDom'; | ||
| import { queryByTestId } from '@/test-utils/dom'; | ||
| import QueryBar from './QueryBar'; | ||
|
|
||
| const item: HttpRequest = { | ||
| info: { name: 'Get Customer', type: 'http' }, | ||
| http: { | ||
| method: 'get', | ||
| url: '{{baseUrl}}/billing/customers/:customerId', | ||
| headers: [{ name: 'Accept', value: 'application/json' }], | ||
| params: [{ name: 'customerId', value: '42', type: 'path' }] | ||
| } | ||
| } as HttpRequest; | ||
|
|
||
| const queryBar = <QueryBar item={item} onSendRequest={() => {}} isLoading={false} onItemChange={() => {}} />; | ||
|
|
||
| describe('Playground QueryBar — code snippet', () => { | ||
| it('offers the code-snippet control alongside the copy-url action', () => { | ||
| const root = useRenderToDom(queryBar); | ||
|
|
||
| expect(queryByTestId(root, 'query-bar-code-snippet-trigger')).not.toBeNull(); | ||
| expect(queryByTestId(root, 'query-bar-copy-url')).not.toBeNull(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,6 +57,25 @@ describe('SnippetTabs', () => { | |
| expect(queryByTestId(root, 'example-code-snippet-expand')).toBeNull(); | ||
| }); | ||
|
|
||
| it('collapses to an icon-only trigger when the variant is icon', () => { | ||
| const root = useRenderToDom(<SnippetTabs snippets={snippets} variant="icon" testId="query-bar-code-snippet" />); | ||
|
|
||
| const trigger = getByTestId(root, 'query-bar-code-snippet-trigger'); | ||
| expect(trigger.classNames).toContain('snippet-icon-trigger'); | ||
| // Icon only — no label, no inline code box. | ||
| expect(trigger.text.trim()).toBe(''); | ||
| expect(queryByTestId(root, 'query-bar-code-snippet-code')).toBeNull(); | ||
| expect(queryByTestId(root, 'query-bar-code-snippet-expand')).toBeNull(); | ||
| }); | ||
|
|
||
| it('labels the icon trigger for screen readers and marks it as opening a dialog', () => { | ||
| const root = useRenderToDom(<SnippetTabs snippets={snippets} variant="icon" testId="query-bar-code-snippet" />); | ||
|
|
||
| const trigger = getByTestId(root, 'query-bar-code-snippet-trigger'); | ||
| expect(trigger.attributes['aria-label']).toBe('Generate Code'); | ||
| expect(trigger.attributes['aria-haspopup']).toBe('dialog'); | ||
| }); | ||
|
Comment on lines
+71
to
+77
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we also add a test for clicking on the trigger button, and then check the modal renders with content inside it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have covered this in the e2e(query-bar-code-snippet.spec.ts) ,clicking cannot be simulated in rendertoStaticMarkup. |
||
|
|
||
| it('renders variables in the code as hover tokens', () => { | ||
| const root = useRenderToDom(<SnippetTabs snippets={snippets} />); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sundram-bruno, I see this block been written multiple times in the whole application. Since you have worked on Auth, can we have a new reusable hook which does this, and update the implementation at other places accordingly.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly it's in GrpcRequest, and now in the PlaygroundView. We have the
useRequestPageDatahook, but that's more than what is needed for this implementation.Maybe, we can use the said hook inside the
useRequestPageData,There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vasharma05-bruno , ok will look into it and see what can be done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we let this change go ahead in this PR, or make the change in this PR itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let this change go. Currently I dont have the bandwidth to do the change and no need to hold this pr for something where we can change it across the whole repo. I feel we can let it be a separate task for it.