Skip to content
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

test: add unit test base for www #8

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
14 changes: 14 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ jobs:
executor: node
<<: *test_template

unit_tests_www:
executor: node
steps:
- checkout
- run:
command: yarn
working_directory: ~/project/www
- run:
command: yarn test
working_directory: ~/project/www

integration_tests_long_term_caching:
executor: node
steps:
Expand Down Expand Up @@ -215,6 +226,9 @@ workflows:
<<: *ignore_docs
requires:
- bootstrap
- unit_tests_www:
requires:
- bootstrap
- integration_tests_long_term_caching:
<<: *e2e-test-workflow
- integration_tests_gatsby_pipeline:
Expand Down
1 change: 1 addition & 0 deletions www/__mocks__/file-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = `test-file-stub`
20 changes: 20 additions & 0 deletions www/__mocks__/gatsby.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const React = require(`react`)
const gatsby = jest.requireActual(`gatsby`)

module.exports = {
...gatsby,
graphql: jest.fn(),
Link: jest.fn().mockImplementation(({ children, to, onClick, id }) =>
React.createElement(
`a`,
{
href: to,
onClick,
id,
},
children
)
),
StaticQuery: jest.fn(),
useStaticQuery: jest.fn(),
}
5 changes: 5 additions & 0 deletions www/jest-preprocess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const babelOptions = {
presets: [`babel-preset-gatsby`],
}

module.exports = require(`babel-jest`).createTransformer(babelOptions)
20 changes: 20 additions & 0 deletions www/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
transform: {
"^.+\\.jsx?$": `<rootDir>/jest-preprocess.js`,
},
moduleNameMapper: {
".+\\.(css|styl|less|sass|scss)$": `identity-obj-proxy`,
".+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": `<rootDir>/__mocks__/file-mock.js`,
},
testPathIgnorePatterns: [`node_modules`, `.cache`],
transformIgnorePatterns: [`node_modules/(?!(gatsby)/)`],
globals: {
__PATH_PREFIX__: ``,
},
testURL: `http://localhost`,
setupFiles: [`<rootDir>/loadershim.js`],
setupFilesAfterEnv: [
`react-testing-library/cleanup-after-each`,
`jest-dom/extend-expect`,
],
}
3 changes: 3 additions & 0 deletions www/loadershim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global.___loader = {
enqueue: jest.fn(),
}
8 changes: 7 additions & 1 deletion www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,21 @@
"develop": "GATSBY_GRAPHQL_IDE=playground gatsby develop",
"start": "npm run develop",
"serve": "gatsby serve",
"test": "echo \"Error: no test specified\" && exit 1",
"test": "jest",
"scrapeStarters": "cd src/data/StarterShowcase && node scraper.js",
"stylelint": "stylelint './src/**/*.js'",
"forestry:preview": "gatsby develop -p 8080 -H 0.0.0.0"
},
"devDependencies": {
"babel-jest": "^24.3.1",
"babel-preset-gatsby": "^0.1.8",
"front-matter": "^2.3.0",
"get-package-json-from-github": "^1.2.1",
"github-api": "^3.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.3.1",
"jest-dom": "^3.1.3",
"react-testing-library": "^6.0.0",
"stylelint": "^9.6.0",
"stylelint-config-standard": "^18.2.0",
"stylelint-config-styled-components": "^0.1.1",
Expand Down
12 changes: 12 additions & 0 deletions www/src/components/__tests__/banner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react"
import { render } from "react-testing-library"

import Banner from "../banner"

test(`it renders an external link`, () => {
const { getByText } = render(<Banner />)

const link = getByText(`Register now`)

expect(link.getAttribute(`href`)).toContain(`https://`)
})
117 changes: 117 additions & 0 deletions www/src/components/__tests__/button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React from "react"
import { fireEvent, render } from "react-testing-library"

import Button from "../button"

describe(`selective tag rendering`, () => {
it(`defaults to rendering a Gatsby Link`, () => {
const { container, getByText } = render(
<Button to="/somewhere">Hello</Button>
)

expect(container.nodeName).toBe(`DIV`)
expect(getByText(`Hello`).nodeName).toBe(`A`)
})

it(`renders a button if tag=button`, () => {
const { getByText } = render(
<Button to="/somewhere" tag="button">
Hello
</Button>
)

expect(getByText(`Hello`).nodeName).toBe(`BUTTON`)
})

it(`renders an anchor if tag=a`, () => {
const { getByText } = render(
<Button to="/somewhere" tag="link">
Hello
</Button>
)

expect(getByText(`Hello`).nodeName).toBe(`A`)
})
})

describe(`tracking`, () => {
let ga
beforeEach(() => {
ga = window.ga = jest.fn()
})

it(`does not send tracking event, by default`, () => {
const { getByText } = render(<Button to="/not-tracked">Hello</Button>)
fireEvent.click(getByText(`Hello`))

expect(ga).not.toHaveBeenCalled()
})

it(`does not send tracking event if ga is undefined`, () => {
delete window.ga

const { getByText } = render(
<Button to="/not-tracked" tracking={true}>
Hello
</Button>
)
fireEvent.click(getByText(`Hello`))

expect(ga).not.toHaveBeenCalled()
})

it(`sends tracking event if tracking=true`, () => {
const to = `/tracking/somewhere`
const { getByText } = render(
<Button to={to} tracking={true}>
Hello
</Button>
)

fireEvent.click(getByText(`Hello`))

expect(ga).toHaveBeenCalledWith(
`send`,
`event`,
expect.objectContaining({
eventCategory: `Outbound Link`,
eventAction: `click`,
eventLabel: expect.stringContaining(to),
})
)
})
})

describe(`props forwarding`, () => {
it(`invokes custom onClick handler`, () => {
const onClick = jest.fn()

const { getByText } = render(
<Button to="/custom-click" onClick={onClick}>
Hello
</Button>
)
fireEvent.click(getByText(`Hello`))

expect(onClick).toHaveBeenCalledWith(expect.any(Object))
})

it(`renders children`, () => {
const children = <span>Hello World</span>
const { getByText } = render(<Button to="/children">{children}</Button>)

expect(getByText(`Hello World`)).toBeDefined()
})

it(`renders icon, if defined`, () => {
const icon = <span>Icon</span>

const { getByText } = render(
<Button to="/with-icon" icon={icon}>
Hello
</Button>
)

expect(getByText(`Icon`)).toBeDefined()
})
})
75 changes: 38 additions & 37 deletions www/src/components/site-metadata.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
import React from "react"
import { Helmet } from "react-helmet"
import { graphql, StaticQuery } from "gatsby"
import { graphql, useStaticQuery } from "gatsby"

import gatsbyIcon from "../assets/gatsby-icon.png"

const SiteMetadata = ({ pathname }) => (
<StaticQuery
query={graphql`
query SiteMetadata {
site {
siteMetadata {
siteUrl
title
twitter
}
}
}
`}
render={({
const SiteMetadata = ({ pathname }) => {
const {
data: {
site: {
siteMetadata: { siteUrl, title, twitter },
},
}) => (
<Helmet defaultTitle={title} titleTemplate={`%s | ${title}`}>
<html lang="en" />
<link rel="canonical" href={`${siteUrl}${pathname}`} />
<meta name="docsearch:version" content="2.0" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,shrink-to-fit=no,viewport-fit=cover"
/>
},
} = useStaticQuery(graphql`
query SiteMetadata {
site {
siteMetadata {
siteUrl
title
twitter
}
}
}
`)

return (
<Helmet defaultTitle={title} titleTemplate={`%s | ${title}`}>
<html lang="en" />
<link rel="canonical" href={`${siteUrl}${pathname}`} />
<meta name="docsearch:version" content="2.0" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,shrink-to-fit=no,viewport-fit=cover"
/>

<meta property="og:url" content={siteUrl} />
<meta property="og:type" content="website" />
<meta property="og:locale" content="en" />
<meta property="og:site_name" content={title} />
<meta property="og:image" content={`${siteUrl}${gatsbyIcon}`} />
<meta property="og:image:width" content="512" />
<meta property="og:image:height" content="512" />
<meta property="og:url" content={siteUrl} />
<meta property="og:type" content="website" />
<meta property="og:locale" content="en" />
<meta property="og:site_name" content={title} />
<meta property="og:image" content={`${siteUrl}${gatsbyIcon}`} />
<meta property="og:image:width" content="512" />
<meta property="og:image:height" content="512" />

<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content={twitter} />
</Helmet>
)}
/>
)
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content={twitter} />
</Helmet>
)
}

export default SiteMetadata
Loading