-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NEBULA-1385: Add initial state to embeddable sandbox and HTML unit te…
…sts (#6633) Allow configuration of embeddable sandbox initial state. The initial `document`, `variables`, and `headers` can now be provided to the plugin config to populate these values on page load. Ported for AS4 from #6628
- Loading branch information
1 parent
9b8274e
commit 1d8c2f5
Showing
7 changed files
with
1,260 additions
and
486 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
packages/server/src/__tests__/plugin/landingPage/getEmbeddedExplorerHTML.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { getEmbeddedExplorerHTML } from '../../../plugin/landingPage/default/getEmbeddedHTML'; | ||
import type { ApolloServerPluginEmbeddedLandingPageProductionDefaultOptions } from '../../../plugin/landingPage/default/types'; | ||
|
||
const version = '_latest'; | ||
expect.addSnapshotSerializer(require('jest-serializer-html')); | ||
|
||
describe('Embedded Explorer Landing Page Config HTML', () => { | ||
it('with document, variables, headers and displayOptions provided', () => { | ||
const config: ApolloServerPluginEmbeddedLandingPageProductionDefaultOptions = | ||
{ | ||
includeCookies: true, | ||
document: 'query Test { id }', | ||
variables: { | ||
option: { | ||
a: 'val', | ||
b: 1, | ||
c: true, | ||
}, | ||
}, | ||
headers: { authorization: 'true' }, | ||
embed: { | ||
displayOptions: { | ||
showHeadersAndEnvVars: true, | ||
docsPanelState: 'open', | ||
theme: 'light', | ||
}, | ||
persistExplorerState: true, | ||
}, | ||
graphRef: 'graph@current', | ||
}; | ||
expect(getEmbeddedExplorerHTML(version, config)).toMatchInlineSnapshot(` | ||
<style> | ||
iframe { | ||
background-color: white; | ||
} | ||
</style> | ||
<div style="width: 100vw; height: 100vh; position: absolute; top: 0;" | ||
id="embeddableExplorer" | ||
> | ||
</div> | ||
<script src="https://embeddable-explorer.cdn.apollographql.com/_latest/embeddable-explorer.umd.production.min.js"> | ||
</script> | ||
<script> | ||
var endpointUrl = window.location.href; | ||
var embeddedExplorerConfig = {"includeCookies":true,"document":"query Test { id }","variables":{"option":{"a":"val","b":1,"c":true}},"headers":{"authorization":"true"},"embed":{"displayOptions":{"showHeadersAndEnvVars":true,"docsPanelState":"open","theme":"light"},"persistExplorerState":true},"graphRef":"graph@current","target":"#embeddableExplorer","initialState":{"includeCookies":true,"document":"query Test { id }","variables":{"option":{"a":"val","b":1,"c":true}},"headers":{"authorization":"true"},"embed":{"displayOptions":{"showHeadersAndEnvVars":true,"docsPanelState":"open","theme":"light"},"persistExplorerState":true},"graphRef":"graph@current","displayOptions":{"showHeadersAndEnvVars":true,"docsPanelState":"open","theme":"light"}},"persistExplorerState":true}; | ||
new window.EmbeddedExplorer({ | ||
...embeddedExplorerConfig, | ||
endpointUrl, | ||
}); | ||
</script> | ||
`); | ||
}); | ||
|
||
it('for embedded explorer with document, variables, headers and displayOptions excluded', () => { | ||
const config: ApolloServerPluginEmbeddedLandingPageProductionDefaultOptions = | ||
{ | ||
includeCookies: false, | ||
embed: true as true, | ||
graphRef: 'graph@current', | ||
}; | ||
expect(getEmbeddedExplorerHTML(version, config)).toMatchInlineSnapshot(` | ||
<style> | ||
iframe { | ||
background-color: white; | ||
} | ||
</style> | ||
<div style="width: 100vw; height: 100vh; position: absolute; top: 0;" | ||
id="embeddableExplorer" | ||
> | ||
</div> | ||
<script src="https://embeddable-explorer.cdn.apollographql.com/_latest/embeddable-explorer.umd.production.min.js"> | ||
</script> | ||
<script> | ||
var endpointUrl = window.location.href; | ||
var embeddedExplorerConfig = {"includeCookies":false,"embed":true,"graphRef":"graph@current","target":"#embeddableExplorer","initialState":{"includeCookies":false,"embed":true,"graphRef":"graph@current","displayOptions":{}},"persistExplorerState":false}; | ||
new window.EmbeddedExplorer({ | ||
...embeddedExplorerConfig, | ||
endpointUrl, | ||
}); | ||
</script> | ||
`); | ||
}); | ||
}); |
74 changes: 74 additions & 0 deletions
74
packages/server/src/__tests__/plugin/landingPage/getEmbeddedSandboxHTML.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { getEmbeddedSandboxHTML } from '../../../plugin/landingPage/default/getEmbeddedHTML'; | ||
import type { LandingPageConfig } from '../../../plugin/landingPage/default/types'; | ||
|
||
const version = '_latest'; | ||
expect.addSnapshotSerializer(require('jest-serializer-html')); | ||
|
||
describe('Landing Page Config HTML', () => { | ||
it('for embedded sandbox with document, variables and headers provided', () => { | ||
const config: LandingPageConfig = { | ||
includeCookies: true, | ||
document: 'query Test { id }', | ||
variables: { | ||
option: { | ||
a: 'val', | ||
b: 1, | ||
c: true, | ||
}, | ||
}, | ||
headers: { authorization: 'true' }, | ||
embed: true, | ||
}; | ||
expect(getEmbeddedSandboxHTML(version, config)).toMatchInlineSnapshot(` | ||
<style> | ||
iframe { | ||
background-color: white; | ||
} | ||
</style> | ||
<div style="width: 100vw; height: 100vh; position: absolute; top: 0;" | ||
id="embeddableSandbox" | ||
> | ||
</div> | ||
<script src="https://embeddable-sandbox.cdn.apollographql.com/_latest/embeddable-sandbox.umd.production.min.js"> | ||
</script> | ||
<script> | ||
var initialEndpoint = window.location.href; | ||
new window.EmbeddedSandbox({ | ||
target: '#embeddableSandbox', | ||
initialEndpoint, | ||
includeCookies: true, | ||
initialState: {"document":"query Test { id }","variables":{"option":{"a":"val","b":1,"c":true}},"headers":{"authorization":"true"}}, | ||
}); | ||
</script> | ||
`); | ||
}); | ||
|
||
it('for embedded sandbox with document, variables and headers excluded', () => { | ||
const config: LandingPageConfig = { | ||
includeCookies: false, | ||
embed: true, | ||
}; | ||
expect(getEmbeddedSandboxHTML(version, config)).toMatchInlineSnapshot(` | ||
<style> | ||
iframe { | ||
background-color: white; | ||
} | ||
</style> | ||
<div style="width: 100vw; height: 100vh; position: absolute; top: 0;" | ||
id="embeddableSandbox" | ||
> | ||
</div> | ||
<script src="https://embeddable-sandbox.cdn.apollographql.com/_latest/embeddable-sandbox.umd.production.min.js"> | ||
</script> | ||
<script> | ||
var initialEndpoint = window.location.href; | ||
new window.EmbeddedSandbox({ | ||
target: '#embeddableSandbox', | ||
initialEndpoint, | ||
includeCookies: false, | ||
initialState: {}, | ||
}); | ||
</script> | ||
`); | ||
}); | ||
}); |
119 changes: 119 additions & 0 deletions
119
packages/server/src/plugin/landingPage/default/getEmbeddedHTML.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import type { | ||
ApolloServerPluginEmbeddedLandingPageProductionDefaultOptions, | ||
LandingPageConfig, | ||
} from './types'; | ||
|
||
// This function turns an object into a string and replaces | ||
// <, >, &, ' with their unicode chars to avoid adding html tags to | ||
// the landing page html that might be passed from the config. | ||
// The only place these characters can appear in the output of | ||
// JSON.stringify is within string literals, where they can equally | ||
// well appear \u-escaped. This specifically means that | ||
// `</script>` won't terminate the script block early. | ||
// (Perhaps we should have done this instead of the triple-encoding | ||
// of encodeConfig for the main landing page.) | ||
function getConfigStringForHtml(config: LandingPageConfig) { | ||
return JSON.stringify(config) | ||
.replace('<', '\\u003c') | ||
.replace('>', '\\u003e') | ||
.replace('&', '\\u0026') | ||
.replace("'", '\\u0027'); | ||
} | ||
|
||
export const getEmbeddedExplorerHTML = ( | ||
version: string, | ||
config: ApolloServerPluginEmbeddedLandingPageProductionDefaultOptions, | ||
) => { | ||
interface EmbeddableExplorerOptions { | ||
graphRef: string; | ||
target: string; | ||
|
||
initialState?: { | ||
document?: string; | ||
variables?: Record<string, any>; | ||
headers?: Record<string, string>; | ||
displayOptions: { | ||
docsPanelState?: 'open' | 'closed'; // default to 'open', | ||
showHeadersAndEnvVars?: boolean; // default to `false` | ||
theme?: 'dark' | 'light'; | ||
}; | ||
}; | ||
persistExplorerState?: boolean; // defaults to 'false' | ||
|
||
endpointUrl: string; | ||
|
||
includeCookies?: boolean; // defaults to 'false' | ||
} | ||
const productionLandingPageConfigOrDefault = { | ||
displayOptions: {}, | ||
persistExplorerState: false, | ||
...(typeof config.embed === 'boolean' ? {} : config.embed), | ||
}; | ||
const embeddedExplorerParams: Omit<EmbeddableExplorerOptions, 'endpointUrl'> = | ||
{ | ||
...config, | ||
target: '#embeddableExplorer', | ||
initialState: { | ||
...config, | ||
displayOptions: { | ||
...productionLandingPageConfigOrDefault.displayOptions, | ||
}, | ||
}, | ||
persistExplorerState: | ||
productionLandingPageConfigOrDefault.persistExplorerState, | ||
}; | ||
|
||
return ` | ||
<style> | ||
iframe { | ||
background-color: white; | ||
} | ||
</style> | ||
<div | ||
style="width: 100vw; height: 100vh; position: absolute; top: 0;" | ||
id="embeddableExplorer" | ||
></div> | ||
<script src="https://embeddable-explorer.cdn.apollographql.com/${version}/embeddable-explorer.umd.production.min.js"></script> | ||
<script> | ||
var endpointUrl = window.location.href; | ||
var embeddedExplorerConfig = ${getConfigStringForHtml( | ||
embeddedExplorerParams, | ||
)}; | ||
new window.EmbeddedExplorer({ | ||
...embeddedExplorerConfig, | ||
endpointUrl, | ||
}); | ||
</script> | ||
`; | ||
}; | ||
|
||
export const getEmbeddedSandboxHTML = ( | ||
version: string, | ||
config: LandingPageConfig, | ||
) => { | ||
return ` | ||
<style> | ||
iframe { | ||
background-color: white; | ||
} | ||
</style> | ||
<div | ||
style="width: 100vw; height: 100vh; position: absolute; top: 0;" | ||
id="embeddableSandbox" | ||
></div> | ||
<script src="https://embeddable-sandbox.cdn.apollographql.com/${version}/embeddable-sandbox.umd.production.min.js"></script> | ||
<script> | ||
var initialEndpoint = window.location.href; | ||
new window.EmbeddedSandbox({ | ||
target: '#embeddableSandbox', | ||
initialEndpoint, | ||
includeCookies: ${config.includeCookies ?? 'false'}, | ||
initialState: ${getConfigStringForHtml({ | ||
document: config.document ?? undefined, | ||
variables: config.variables ?? undefined, | ||
headers: config.headers ?? undefined, | ||
})}, | ||
}); | ||
</script> | ||
`; | ||
}; |
Oops, something went wrong.