Skip to content

Commit

Permalink
feat(gatsby): Track static queries by template (#25549)
Browse files Browse the repository at this point in the history
Track static queries by template

Co-authored-by: Sidhartha Chatterjee <[email protected]>
  • Loading branch information
freiksenet and sidharthachatterjee authored Jul 13, 2020
1 parent 8345b46 commit e640c5b
Show file tree
Hide file tree
Showing 41 changed files with 869 additions and 12 deletions.
8 changes: 8 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ jobs:
- e2e-test:
test_path: integration-tests/structured-logging

integration_tests_artifacts:
executor: node
steps:
- e2e-test:
test_path: integration-tests/artifacts

e2e_tests_path-prefix:
<<: *e2e-executor
environment:
Expand Down Expand Up @@ -572,6 +578,8 @@ workflows:
<<: *e2e-test-workflow
- integration_tests_structured_logging:
<<: *e2e-test-workflow
- integration_tests_artifacts:
<<: *e2e-test-workflow
- integration_tests_gatsby_cli:
requires:
- bootstrap
Expand Down
21 changes: 21 additions & 0 deletions integration-tests/artifacts/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 gatsbyjs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
3 changes: 3 additions & 0 deletions integration-tests/artifacts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Artifacts test suite

This integration test suite helps us assert some of the artifacts written out for a Gatsby build. The test suite runs a real Gatsby build and then checks the generated `public` directory for `page-data.json` files. Since we added static query hashes to `page-data.json` files, the tests in this suite assert whether the correct static query hashes are included in every respective page.
183 changes: 183 additions & 0 deletions integration-tests/artifacts/__tests__/static-queries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
const { spawn } = require(`child_process`)
const path = require(`path`)
const { murmurhash } = require(`babel-plugin-remove-graphql-queries`)
const { readPageData } = require(`gatsby/dist/utils/page-data`)
const { stripIgnoredCharacters } = require(`gatsby/graphql`)

jest.setTimeout(100000)

const publicDir = path.join(process.cwd(), `public`)

const gatsbyBin = path.join(`node_modules`, `.bin`, `gatsby`)

const titleQuery = `
{
site {
siteMetadata {
title
}
}
}
`

const authorQuery = `
{
site {
siteMetadata {
author
}
}
}
`

const githubQuery = `
{
site {
siteMetadata {
github
}
}
}
`

const moreInfoQuery = `
{
site {
siteMetadata {
moreInfo
}
}
}
`

function hashQuery(query) {
const text = stripIgnoredCharacters(query)
const hash = murmurhash(text, `abc`)
return String(hash)
}

const globalQueries = [githubQuery, moreInfoQuery]

describe(`Static Queries`, () => {
beforeAll(async done => {
const gatsbyProcess = spawn(gatsbyBin, [`build`], {
stdio: [`inherit`, `inherit`, `inherit`, `inherit`],
env: {
...process.env,
NODE_ENV: `production`,
},
})

gatsbyProcess.on(`exit`, exitCode => {
done()
})
})

test(`are written correctly when inline`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/inline/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when imported`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/import/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when dynamically imported`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/dynamic/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly in jsx`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/jsx/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly in tsx`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/tsx/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly in typescript`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/typescript/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when nesting imports`, async () => {
const queries = [titleQuery, authorQuery, ...globalQueries]
const pagePath = `/import-import/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when nesting dynamic imports`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/dynamic-dynamic/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when nesting a dynamic import in a regular import`, async () => {
const queries = [titleQuery, authorQuery, ...globalQueries]
const pagePath = `/import-dynamic/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when nesting a regular import in a dynamic import`, async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/dynamic-import/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test("are written correctly with circular dependency", async () => {
const queries = [titleQuery, ...globalQueries]
const pagePath = `/circular-dep/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})

test(`are written correctly when using gatsby-browser`, async () => {
const queries = [...globalQueries]
const pagePath = `/gatsby-browser/`

const { staticQueryHashes } = await readPageData(publicDir, pagePath)

expect(staticQueryHashes.sort()).toEqual(queries.map(hashQuery).sort())
})
})
20 changes: 20 additions & 0 deletions integration-tests/artifacts/gatsby-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const React = require(`react`)
const { useMoreInfoQuery } = require("./src/hooks/use-more-info-query")
const Github = require(`./src/components/github`).default

exports.wrapRootElement = ({ element }) => (
<>
<Github />
{element}
</>
)

exports.wrapPageElement = ({ element, props }) => {
const data = useMoreInfoQuery()
return (
<>
<h1>{data.site.siteMetadata.moreInfo}</h1>
{element}
</>
)
}
10 changes: 10 additions & 0 deletions integration-tests/artifacts/gatsby-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
siteMetadata: {
title: `Hello world`,
author: `Sid Chatterjee`,
twitter: `chatsidhartha`,
github: `sidharthachatterjee`,
moreInfo: `Sid is amazing`,
},
plugins: [],
}
Empty file.
3 changes: 3 additions & 0 deletions integration-tests/artifacts/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
testPathIgnorePatterns: [`/node_modules/`, `__tests__/fixtures`, `.cache`],
}
32 changes: 32 additions & 0 deletions integration-tests/artifacts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "artifacts",
"private": true,
"author": "Sid Chatterjee",
"description": "A simplified bare-bones starter for Gatsby",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "jest --config=jest.config.js --runInBand"
},
"dependencies": {
"gatsby": "^2.22.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
},
"devDependencies": {
"fs-extra": "^9.0.0",
"jest": "^24.0.0",
"jest-cli": "^24.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-hello-world"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}
15 changes: 15 additions & 0 deletions integration-tests/artifacts/src/components/author.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"

export default function Author() {
const { site } = useStaticQuery(graphql`
{
site {
siteMetadata {
author
}
}
}
`)
return <div>{site.siteMetadata.author}</div>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from "react"
import { aVar } from "../pages/circular-dep"

export default function CircularComponent() {
return <div>Foo</div>
}
15 changes: 15 additions & 0 deletions integration-tests/artifacts/src/components/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"

export default function Github() {
const { site } = useStaticQuery(graphql`
{
site {
siteMetadata {
github
}
}
}
`)
return <div>{site.siteMetadata.github}</div>
}
7 changes: 7 additions & 0 deletions integration-tests/artifacts/src/components/title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react"
import { useTitle } from "../hooks/use-title"

export default function Title() {
const title = useTitle()
return <div>{title}</div>
}
15 changes: 15 additions & 0 deletions integration-tests/artifacts/src/components/twitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"

export default function Twitter() {
const { site } = useStaticQuery(graphql`
{
site {
siteMetadata {
twitter
}
}
}
`)
return <div>{site.siteMetadata.twitter}</div>
}
14 changes: 14 additions & 0 deletions integration-tests/artifacts/src/hooks/use-more-info-query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useStaticQuery, graphql } from "gatsby"

export const useMoreInfoQuery = () => {
const data = useStaticQuery(graphql`
{
site {
siteMetadata {
moreInfo
}
}
}
`)
return data
}
14 changes: 14 additions & 0 deletions integration-tests/artifacts/src/hooks/use-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useStaticQuery, graphql } from "gatsby"

export const useTitle = () => {
const { site } = useStaticQuery(graphql`
{
site {
siteMetadata {
title
}
}
}
`)
return site.siteMetadata.title
}
Loading

0 comments on commit e640c5b

Please sign in to comment.