Skip to content

Commit

Permalink
fix: graphiql enable schema description, default headers (#2172)
Browse files Browse the repository at this point in the history
  • Loading branch information
tuanpt-0634 committed Nov 29, 2022
1 parent 534780c commit 62fc9e4
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/nice-shirts-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-yoga/graphiql': patch
---

- fix: enable graphiql schema description, default headers prop
3 changes: 2 additions & 1 deletion packages/graphiql/src/YogaGraphiQL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ export function YogaGraphiQL(props: YogaGraphiQLProps): React.ReactElement {
credentials: 'same-origin',
specifiedByUrl: true,
directiveIsRepeatable: true,
schemaDescription: true,
...props,
headers: props.additionalHeaders || {},
})
Expand Down Expand Up @@ -152,6 +151,8 @@ export function YogaGraphiQL(props: YogaGraphiQLProps): React.ReactElement {
<GraphiQLProvider
plugins={[explorerPlugin]}
query={query}
headers={props.headers}
schemaDescription={true}
fetcher={fetcher}
>
<GraphiQLInterface
Expand Down
130 changes: 129 additions & 1 deletion packages/graphql-yoga/__integration-tests__/browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { InMemoryLiveQueryStore } from '@n1ru4l/in-memory-live-query-store'
import { GraphQLLiveDirective, useLiveQuery } from '@envelop/live-query'
import { CORSOptions, createYoga, Repeater } from '../src/index.js'
import { renderGraphiQL } from '@graphql-yoga/render-graphiql'
import puppeteer, { Browser, Page } from 'puppeteer'
import puppeteer, { Browser, ElementHandle, Page } from 'puppeteer'
import { createServer, Server } from 'http'
import {
GraphQLObjectType,
Expand Down Expand Up @@ -231,7 +231,62 @@ describe('browser', () => {
return resultContents
}

const showGraphiQLSidebar = async () => {
// Click to show sidebar
await page.click(
'.graphiql-sidebar [aria-label="Show Documentation Explorer"]',
)
}

const getElementText = async (element: ElementHandle<Element>) =>
element.evaluate((el) => el.textContent?.trim())

describe('GraphiQL', () => {
it('should show default title', async () => {
await page.goto(`http://localhost:${port}${endpoint}`)

const title = await page.evaluate(() => document.title)

expect(title).toBe('Yoga GraphiQL')
})

it('should show default schema docs', async () => {
await page.goto(`http://localhost:${port}${endpoint}`)

// Click to show sidebar
await showGraphiQLSidebar()

const docsElement = await page.waitForSelector(
'.graphiql-markdown-description',
)

expect(docsElement).not.toBeNull()
const docs = await getElementText(docsElement!)

expect(docs).toBe(
'A GraphQL schema provides a root type for each kind of operation.',
)
})

it('should show editor tools by default', async () => {
await page.goto(`http://localhost:${port}${endpoint}`)

// If this button is visible, that mean editor tools is showing
const buttonHideEditor = await page.$(
'button[aria-label="Hide editor tools"]',
)

const editorTabs = await page.evaluate(() =>
Array.from(
document.querySelectorAll('.graphiql-editor-tools-tabs button'),
(e) => e.textContent,
),
)

expect(buttonHideEditor).not.toBeNull()
expect(editorTabs).toEqual(['Variables', 'Headers'])
})

it('execute simple query operation', async () => {
await page.goto(`http://localhost:${port}${endpoint}`)
await typeOperationText('{ alwaysTrue }')
Expand Down Expand Up @@ -437,6 +492,79 @@ describe('browser', () => {
})
})

describe('GraphiQL with custom options', () => {
let customGraphQLEndpoint: string

const schemaWithDescription = createTestSchema()
schemaWithDescription.description = 'Here is the custom docs for schema'

const defaultHeader = '{"Authorization":"Bearer test-auth-header"}'
const customServer = createServer(
createYoga({
schema: schemaWithDescription,
logging: false,
graphqlEndpoint: endpoint,
graphiql: {
title: 'GraphiQL Custom title here',
headers: defaultHeader,
},
renderGraphiQL,
}),
)

beforeAll(async () => {
await new Promise<void>((resolve) => customServer.listen(0, resolve))
const port = (customServer.address() as AddressInfo).port
customGraphQLEndpoint = `http://localhost:${port}${endpoint}`
})

afterAll(async () => {
await new Promise((resolve) => customServer.close(resolve))
})

it('should show custom title', async () => {
await page.goto(customGraphQLEndpoint)

const title = await page.evaluate(() => document.title)

expect(title).toBe('GraphiQL Custom title here')
})

it('should show custom schema docs', async () => {
await page.goto(customGraphQLEndpoint)

await showGraphiQLSidebar()
const docsElement = await page.waitForSelector(
'.graphiql-markdown-description',
)

expect(docsElement).not.toBeNull()
const docs = await getElementText(docsElement!)

expect(docs).toBe(schemaWithDescription.description)
})

it('should include default header', async () => {
await page.goto(customGraphQLEndpoint)

await page.evaluate(() => {
const tabs = Array.from(
document.querySelectorAll('.graphiql-editor-tools-tabs button'),
) as HTMLButtonElement[]
tabs.find((tab) => tab.textContent === 'Headers')!.click()
})

const headerContentEl = await page.waitForSelector(
'section.graphiql-editor-tool .graphiql-editor:not(.hidden) pre.CodeMirror-line',
)

expect(headerContentEl).not.toBeNull()
const headerContent = await getElementText(headerContentEl!)

expect(headerContent).toBe(defaultHeader)
})
})

describe('CORS', () => {
let anotherServer: Server
let anotherOriginPort: number
Expand Down
8 changes: 7 additions & 1 deletion packages/graphql-yoga/src/plugins/useGraphiQL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ export type GraphiQLOptions = {
defaultQuery?: string
/**
* Whether to open the variable editor by default. Defaults to `true`.
*
* @deprecated Obsolete option. Variable editor was opened by default
*/
defaultVariableEditorOpen?: boolean
/**
* The initial headers to render inside the header editor. Defaults to `"{}"`.
* The value should be a JSON encoded string, for example:
* `headers: JSON.stringify({Authorization: "Bearer your-auth-key"})`
*/
headers?: string
/**
Expand All @@ -28,10 +32,12 @@ export type GraphiQLOptions = {
credentials?: RequestCredentials
/**
* Whether the header editor is enabled. Defaults to `true`.
*
* @deprecated Obsolete option. Header editor was enabled by default
*/
headerEditorEnabled?: boolean
/**
* The title to display at the top of the page. Defaults to `"YogaGraphiQL"`.
* The title to display at the top of the page. Defaults to `"Yoga GraphiQL"`.
*/
title?: string
/**
Expand Down

0 comments on commit 62fc9e4

Please sign in to comment.