Skip to content

Commit 091bb3f

Browse files
authored
Merge pull request #18012 from github/graphql-explorer-query-params
Pass query params from URL to GraphQL Explorer
2 parents 9f24923 + d3838e8 commit 091bb3f

3 files changed

Lines changed: 49 additions & 4 deletions

File tree

javascripts/explorer.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
const explorerUrl = location.hostname === 'localhost'
2+
? 'http://localhost:3000'
3+
: 'https://graphql.github.com/explorer'
14

5+
// Pass non-search query params to Explorer app via the iFrame
26
export default function () {
3-
// TODO support "Run in Explorer" links in GraphQL guides
4-
// will need to handle query params separately from search queries
7+
const graphiqlExplorer = document.getElementById('graphiql')
8+
const queryString = window.location.search
9+
10+
if (!(queryString && graphiqlExplorer)) return
11+
12+
window.onload = () => {
13+
graphiqlExplorer.contentWindow.postMessage(queryString, explorerUrl)
14+
}
515
}

javascripts/search.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ let $searchResultsContainer
77
let $searchOverlay
88
let $searchInput
99

10+
let isExplorerPage
11+
1012
// This is our default placeholder, but it can be localized with a <meta> tag
1113
let placeholder = 'Search topics, products...'
1214
let version
1315
let language
1416

1517
export default function search () {
18+
// We don't want to mess with query params intended for the GraphQL Explorer
19+
isExplorerPage = Boolean(document.getElementById('graphiql'))
20+
1621
// First, only initialize search if the elements are on the page
1722
$searchInputContainer = document.getElementById('search-input-container')
1823
$searchResultsContainer = document.getElementById('search-results-container')
@@ -51,7 +56,9 @@ export default function search () {
5156
searchWithYourKeyboard('#search-input-container input', '.ais-Hits-item')
5257

5358
// If the user already has a query in the URL, parse it and search away
54-
parseExistingSearch()
59+
if (!isExplorerPage) {
60+
parseExistingSearch()
61+
}
5562

5663
// If not on home page, decide if search panel should be open
5764
toggleSearchDisplay() // must come after parseExistingSearch
@@ -133,8 +140,9 @@ async function onSearch () {
133140
const query = $searchInput.value
134141

135142
// Update the URL with the search parameters in the query string
143+
// UNLESS this is the GraphQL Explorer page, where a query in the URL is a GraphQL query
136144
const pushUrl = new URL(location)
137-
pushUrl.search = query ? new URLSearchParams({ query }) : ''
145+
pushUrl.search = query && !isExplorerPage ? new URLSearchParams({ query }) : ''
138146
history.pushState({}, '', pushUrl)
139147

140148
// If there's a query, call the endpoint

tests/browser/browser.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,30 @@ describe('language banner', () => {
281281
}
282282
})
283283
})
284+
285+
// The Explorer in the iFrame will not be accessible on localhost, but we can still
286+
// test the query param handling
287+
describe('GraphQL Explorer', () => {
288+
it('preserves query strings on the Explorer page without opening search', async () => {
289+
const queryString = `query {
290+
viewer {
291+
foo
292+
}
293+
}`
294+
// Encoded as: query%20%7B%0A%20%20viewer%20%7B%0A%20%20%20%20foo%0A%20%20%7D%0A%7D
295+
const encodedString = encodeURIComponent(queryString)
296+
const explorerUrl = 'http://localhost:4001/en/graphql/overview/explorer'
297+
298+
await page.goto(`${explorerUrl}?query=${encodedString}`)
299+
300+
// On non-Explorer pages, query params handled by search JS get form-encoded using `+` instead of `%20`.
301+
// So on these pages, the following test will be false; but on the Explorer page, it should be true.
302+
expect(page.url().endsWith(encodedString)).toBe(true)
303+
304+
// On non-Explorer pages, query params handled by search JS will populate in the search box and the `js-open`
305+
// class is added. On these pages, the following test will NOT be null; but on the Explorer page, it should be null.
306+
await page.waitForSelector('#search-results-container')
307+
const searchResult = await page.$('#search-results-container.js-open')
308+
expect(searchResult).toBeNull()
309+
})
310+
})

0 commit comments

Comments
 (0)