mirror of
https://github.com/kremalicious/blog.git
synced 2024-12-22 17:23:50 +01:00
refactor jest config, add more tests
This commit is contained in:
parent
9074735451
commit
61f46d4058
@ -2,7 +2,7 @@
|
|||||||
<a href="https://kremalicious.com"><img src="src/images/github-header.png" /></a>
|
<a href="https://kremalicious.com"><img src="src/images/github-header.png" /></a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<strong>🍭 My blog built with <a href="http://gatsbyjs.org">Gatsby</a>. Neat.</strong>
|
<strong>🍭 My blog built with <a href="http://gatsbyjs.org">Gatsby</a> + TypeScript. Neat.</strong>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://kremalicious.com">kremalicious.com</a>
|
<a href="https://kremalicious.com">kremalicious.com</a>
|
||||||
|
@ -3,12 +3,12 @@ module.exports = {
|
|||||||
'^.+\\.(tsx?|jsx?)$': 'ts-jest',
|
'^.+\\.(tsx?|jsx?)$': 'ts-jest',
|
||||||
'^.+\\.jsx?$': '<rootDir>/jest/jest-preprocess.js'
|
'^.+\\.jsx?$': '<rootDir>/jest/jest-preprocess.js'
|
||||||
},
|
},
|
||||||
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$',
|
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.([tj]sx?)$',
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'.+\\.(css|styl|less|sass|scss)$': 'identity-obj-proxy',
|
'.+\\.(css|styl|less|sass|scss)$': 'identity-obj-proxy',
|
||||||
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
'.+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||||
'<rootDir>/jest/__mocks__/file-mock.ts',
|
'<rootDir>/jest/__mocks__/file-mock.js',
|
||||||
'\\.svg': '<rootDir>/jest/__mocks__/svgr-mock.ts'
|
'\\.svg': '<rootDir>/jest/__mocks__/svgr-mock.js'
|
||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||||
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
|
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
|
||||||
@ -16,7 +16,6 @@ module.exports = {
|
|||||||
globals: {
|
globals: {
|
||||||
__PATH_PREFIX__: ''
|
__PATH_PREFIX__: ''
|
||||||
},
|
},
|
||||||
testURL: 'http://localhost',
|
|
||||||
setupFiles: ['<rootDir>/jest/loadershim.js'],
|
setupFiles: ['<rootDir>/jest/loadershim.js'],
|
||||||
setupFilesAfterEnv: ['<rootDir>/jest/setup-test-env.ts'],
|
setupFilesAfterEnv: ['<rootDir>/jest/setup-test-env.ts'],
|
||||||
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/@types/**/*']
|
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/@types/**/*']
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"avatar": {
|
||||||
"edges": [
|
"edges": [
|
||||||
{
|
{
|
||||||
"node": {
|
"node": {
|
||||||
@ -18,3 +19,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
219
jest/__fixtures__/github.json
Normal file
219
jest/__fixtures__/github.json
Normal file
File diff suppressed because one or more lines are too long
39
jest/__fixtures__/meta.json
Normal file
39
jest/__fixtures__/meta.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"site": {
|
||||||
|
"siteMetadata": {
|
||||||
|
"siteTitle": "kremalicious",
|
||||||
|
"siteTitleShort": "krlc",
|
||||||
|
"siteDescription": "Blog of designer & developer Matthias Kretschmann",
|
||||||
|
"siteUrl": "https://kremalicious.com",
|
||||||
|
"author": {
|
||||||
|
"name": "Matthias Kretschmann",
|
||||||
|
"email": "m@kretschmann.io",
|
||||||
|
"uri": "https://matthiaskretschmann.com",
|
||||||
|
"twitter": "https://twitter.com/kremalicious",
|
||||||
|
"github": "https://github.com/kremalicious",
|
||||||
|
"facebook": "https://facebook.com/matthiaskretschmann",
|
||||||
|
"bitcoin": "171qDmKEXm9YBgBLXyGjjPvopP5o9htQ1V",
|
||||||
|
"ether": "0x339dbC44d39bf1961E385ed0Ae88FC6069b87Ea1"
|
||||||
|
},
|
||||||
|
"typekitID": "msu4qap",
|
||||||
|
"menu": [
|
||||||
|
{
|
||||||
|
"title": "Photos",
|
||||||
|
"link": "/photos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Goodies",
|
||||||
|
"link": "/tags/goodies"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tags",
|
||||||
|
"link": "/tags"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rss": "/feed.xml",
|
||||||
|
"jsonfeed": "/feed.json",
|
||||||
|
"itemsPerPage": 20,
|
||||||
|
"repoContentPath": "https://github.com/kremalicious/blog/tree/master/content"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
jest/__fixtures__/photos.json
Normal file
62
jest/__fixtures__/photos.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"photos": {
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"node": {
|
||||||
|
"id": "6effe45d-0884-527c-9fba-6f7f567979fd",
|
||||||
|
"frontmatter": {
|
||||||
|
"title": "Országház II",
|
||||||
|
"type": "photo",
|
||||||
|
"image": {
|
||||||
|
"childImageSharp": {
|
||||||
|
"fluid": {
|
||||||
|
"aspectRatio": 1,
|
||||||
|
"src": "/static/2dbcf257b4bdf625c24fede935d32425/2423a/2019-11-03-orszaghaz-ii.jpg",
|
||||||
|
"srcSet": "/static/2dbcf257b4bdf625c24fede935d32425/b7835/2019-11-03-orszaghaz-ii.jpg 100w,\n/static/2dbcf257b4bdf625c24fede935d32425/2de44/2019-11-03-orszaghaz-ii.jpg 200w,\n/static/2dbcf257b4bdf625c24fede935d32425/2423a/2019-11-03-orszaghaz-ii.jpg 400w,\n/static/2dbcf257b4bdf625c24fede935d32425/66039/2019-11-03-orszaghaz-ii.jpg 600w,\n/static/2dbcf257b4bdf625c24fede935d32425/ba820/2019-11-03-orszaghaz-ii.jpg 800w,\n/static/2dbcf257b4bdf625c24fede935d32425/d04d5/2019-11-03-orszaghaz-ii.jpg 3793w",
|
||||||
|
"srcWebp": "/static/2dbcf257b4bdf625c24fede935d32425/33771/2019-11-03-orszaghaz-ii.webp",
|
||||||
|
"srcSetWebp": "/static/2dbcf257b4bdf625c24fede935d32425/4f5da/2019-11-03-orszaghaz-ii.webp 100w,\n/static/2dbcf257b4bdf625c24fede935d32425/72345/2019-11-03-orszaghaz-ii.webp 200w,\n/static/2dbcf257b4bdf625c24fede935d32425/33771/2019-11-03-orszaghaz-ii.webp 400w,\n/static/2dbcf257b4bdf625c24fede935d32425/f12d8/2019-11-03-orszaghaz-ii.webp 600w,\n/static/2dbcf257b4bdf625c24fede935d32425/b975c/2019-11-03-orszaghaz-ii.webp 800w,\n/static/2dbcf257b4bdf625c24fede935d32425/f7332/2019-11-03-orszaghaz-ii.webp 3793w",
|
||||||
|
"sizes": "(max-width: 400px) 100vw, 400px",
|
||||||
|
"originalImg": "/static/2dbcf257b4bdf625c24fede935d32425/d04d5/2019-11-03-orszaghaz-ii.jpg",
|
||||||
|
"originalName": "2019-11-03-orszaghaz-ii.jpg",
|
||||||
|
"presentationWidth": 400,
|
||||||
|
"presentationHeight": 300
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"slug": "/orszaghaz-ii/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": {
|
||||||
|
"id": "c80697e5-681d-5fcc-9dab-c3a3821ff0b1",
|
||||||
|
"frontmatter": {
|
||||||
|
"title": "Országház I",
|
||||||
|
"type": "photo",
|
||||||
|
"image": {
|
||||||
|
"childImageSharp": {
|
||||||
|
"fluid": {
|
||||||
|
"aspectRatio": 1,
|
||||||
|
"src": "/static/36d87329aeeda296ae923606e5a4a785/2423a/2019-11-02-orszaghaz-i.jpg",
|
||||||
|
"srcSet": "/static/36d87329aeeda296ae923606e5a4a785/b7835/2019-11-02-orszaghaz-i.jpg 100w,\n/static/36d87329aeeda296ae923606e5a4a785/2de44/2019-11-02-orszaghaz-i.jpg 200w,\n/static/36d87329aeeda296ae923606e5a4a785/2423a/2019-11-02-orszaghaz-i.jpg 400w,\n/static/36d87329aeeda296ae923606e5a4a785/66039/2019-11-02-orszaghaz-i.jpg 600w,\n/static/36d87329aeeda296ae923606e5a4a785/ba820/2019-11-02-orszaghaz-i.jpg 800w,\n/static/36d87329aeeda296ae923606e5a4a785/c9c86/2019-11-02-orszaghaz-i.jpg 3708w",
|
||||||
|
"srcWebp": "/static/36d87329aeeda296ae923606e5a4a785/33771/2019-11-02-orszaghaz-i.webp",
|
||||||
|
"srcSetWebp": "/static/36d87329aeeda296ae923606e5a4a785/4f5da/2019-11-02-orszaghaz-i.webp 100w,\n/static/36d87329aeeda296ae923606e5a4a785/72345/2019-11-02-orszaghaz-i.webp 200w,\n/static/36d87329aeeda296ae923606e5a4a785/33771/2019-11-02-orszaghaz-i.webp 400w,\n/static/36d87329aeeda296ae923606e5a4a785/f12d8/2019-11-02-orszaghaz-i.webp 600w,\n/static/36d87329aeeda296ae923606e5a4a785/b975c/2019-11-02-orszaghaz-i.webp 800w,\n/static/36d87329aeeda296ae923606e5a4a785/262c1/2019-11-02-orszaghaz-i.webp 3708w",
|
||||||
|
"sizes": "(max-width: 400px) 100vw, 400px",
|
||||||
|
"originalImg": "/static/36d87329aeeda296ae923606e5a4a785/c9c86/2019-11-02-orszaghaz-i.jpg",
|
||||||
|
"originalName": "2019-11-02-orszaghaz-i.jpg",
|
||||||
|
"presentationWidth": 400,
|
||||||
|
"presentationHeight": 297
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"slug": "/orszaghaz-i/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
41
jest/__fixtures__/post.json
Normal file
41
jest/__fixtures__/post.json
Normal file
File diff suppressed because one or more lines are too long
118
jest/__fixtures__/posts.json
Normal file
118
jest/__fixtures__/posts.json
Normal file
File diff suppressed because one or more lines are too long
1
jest/__mocks__/file-mock.js
Normal file
1
jest/__mocks__/file-mock.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = 'test-file-stub'
|
@ -1 +0,0 @@
|
|||||||
export default 'test-file-stub'
|
|
29
jest/__mocks__/gatsby.js
Normal file
29
jest/__mocks__/gatsby.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
|
||||||
|
const React = require('react')
|
||||||
|
const gatsby = jest.requireActual('gatsby')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
...gatsby,
|
||||||
|
graphql: jest.fn(),
|
||||||
|
Link: jest.fn().mockImplementation(
|
||||||
|
// these props are invalid for an `a` tag
|
||||||
|
({
|
||||||
|
activeClassName,
|
||||||
|
activeStyle,
|
||||||
|
getProps,
|
||||||
|
innerRef,
|
||||||
|
partiallyActive,
|
||||||
|
ref,
|
||||||
|
replace,
|
||||||
|
to,
|
||||||
|
...rest
|
||||||
|
}) =>
|
||||||
|
React.createElement('a', {
|
||||||
|
...rest,
|
||||||
|
href: to
|
||||||
|
})
|
||||||
|
),
|
||||||
|
StaticQuery: jest.fn(),
|
||||||
|
useStaticQuery: jest.fn()
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
const gatsby = jest.requireActual('gatsby')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
...gatsby,
|
|
||||||
graphql: jest.fn(),
|
|
||||||
Link: jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementation(({ to, ...rest }) =>
|
|
||||||
React.createElement('a', { ...rest, href: to })
|
|
||||||
),
|
|
||||||
StaticQuery: jest.fn(),
|
|
||||||
useStaticQuery: jest.fn()
|
|
||||||
}
|
|
6
jest/__mocks__/svgr-mock.js
Normal file
6
jest/__mocks__/svgr-mock.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export default 'SvgrURL'
|
||||||
|
const SvgrMock = React.forwardRef((props, ref) => <span ref={ref} {...props} />)
|
||||||
|
|
||||||
|
export const ReactComponent = SvgrMock
|
@ -1,3 +0,0 @@
|
|||||||
const content = 'svg'
|
|
||||||
export const ReactComponent = content
|
|
||||||
export default content
|
|
@ -1 +1,18 @@
|
|||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
|
||||||
|
import * as Gatsby from 'gatsby'
|
||||||
|
const useStaticQuery = jest.spyOn(Gatsby, 'useStaticQuery')
|
||||||
|
import meta from '../jest/__fixtures__/meta.json'
|
||||||
|
import avatar from '../jest/__fixtures__/avatar.json'
|
||||||
|
import posts from '../jest/__fixtures__/posts.json'
|
||||||
|
import github from '../jest/__fixtures__/github.json'
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
useStaticQuery.mockImplementation(() => ({
|
||||||
|
...meta,
|
||||||
|
...avatar,
|
||||||
|
logo: { edges: [{ node: { relativePath: 'apple-touch-icon.png' } }] },
|
||||||
|
...posts,
|
||||||
|
...github
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"start": "gatsby develop --host 0.0.0.0",
|
"start": "gatsby develop --host 0.0.0.0",
|
||||||
"build": "gatsby build && npm run copy",
|
"build": "gatsby build && npm run copy",
|
||||||
"ssr": "npm run build && serve -s public/",
|
"ssr": "npm run build && serve -s public/",
|
||||||
"test": "npm run lint && jest --coverage",
|
"test": "npm run lint && jest --coverage --silent",
|
||||||
"test:watch": "npm run lint && jest --coverage --watch",
|
"test:watch": "npm run lint && jest --coverage --watch",
|
||||||
"copy": "cp -R content/media/ public",
|
"copy": "cp -R content/media/ public",
|
||||||
"lint": "run-p --continue-on-error lint:js lint:css lint:md",
|
"lint": "run-p --continue-on-error lint:js lint:css lint:md",
|
||||||
|
2
src/@types/Image.d.ts
vendored
2
src/@types/Image.d.ts
vendored
@ -4,7 +4,7 @@ export interface ImageProps {
|
|||||||
title?: string
|
title?: string
|
||||||
fluid?: FluidObject
|
fluid?: FluidObject
|
||||||
fixed?: FixedObject
|
fixed?: FixedObject
|
||||||
alt: string
|
alt?: string
|
||||||
original?: { src: string }
|
original?: { src: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
src/components/Layout.test.tsx
Normal file
7
src/components/Layout.test.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import testRender from '../../jest/testRender'
|
||||||
|
import Layout from './Layout'
|
||||||
|
|
||||||
|
describe('Layout', () => {
|
||||||
|
testRender(<Layout>Hello</Layout>)
|
||||||
|
})
|
@ -1,23 +1,17 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import testRender from '../../../jest/testRender'
|
import { render } from '@testing-library/react'
|
||||||
|
|
||||||
import { PureChangelog as Changelog } from './Changelog'
|
import Changelog from './Changelog'
|
||||||
import { GitHubRepo } from '../../@types/GitHub'
|
|
||||||
|
|
||||||
const repos: [{ node: GitHubRepo }] = [
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
name: 'gatsby-plugin-matomo',
|
|
||||||
url: 'https://hello.com',
|
|
||||||
owner: { login: 'kremalicious' },
|
|
||||||
object: {
|
|
||||||
id: 'hello',
|
|
||||||
text: 'hello'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
describe('Changelog', () => {
|
describe('Changelog', () => {
|
||||||
testRender(<Changelog repo="gatsby-plugin-matomo" repos={repos} />)
|
it('renders without crashing', () => {
|
||||||
|
const { container, rerender } = render(
|
||||||
|
<Changelog repo="gatsby-plugin-matomo" />
|
||||||
|
)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
|
||||||
|
// return nothing when no match
|
||||||
|
rerender(<Changelog repo="nomatch" />)
|
||||||
|
expect(container.firstChild).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -22,7 +22,6 @@ export function PureChangelog({
|
|||||||
if (!repoMatch) return null
|
if (!repoMatch) return null
|
||||||
|
|
||||||
const { object, url, owner } = repoMatch
|
const { object, url, owner } = repoMatch
|
||||||
if (!object) return null
|
|
||||||
|
|
||||||
const changelogHtml =
|
const changelogHtml =
|
||||||
object &&
|
object &&
|
||||||
@ -53,7 +52,6 @@ export function PureChangelog({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Changelog({ repo }: { repo: string }) {
|
|
||||||
const queryGithub = graphql`
|
const queryGithub = graphql`
|
||||||
query GitHubReposInfo {
|
query GitHubReposInfo {
|
||||||
github {
|
github {
|
||||||
@ -79,6 +77,8 @@ export default function Changelog({ repo }: { repo: string }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export default function Changelog({ repo }: { repo: string }) {
|
||||||
const data: GitHub = useStaticQuery(queryGithub)
|
const data: GitHub = useStaticQuery(queryGithub)
|
||||||
const repos: [{ node: GitHubRepo }] = data.github.viewer.repositories.edges
|
const repos: [{ node: GitHubRepo }] = data.github.viewer.repositories.edges
|
||||||
return <PureChangelog repo={repo} repos={repos} />
|
return <PureChangelog repo={repo} repos={repos} />
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
// import { render } from '@testing-library/react'
|
|
||||||
import testRender from '../../../jest/testRender'
|
|
||||||
|
|
||||||
import Container from './Container'
|
|
||||||
|
|
||||||
describe('Container', () => {
|
|
||||||
testRender(<Container>Hello</Container>)
|
|
||||||
})
|
|
@ -14,7 +14,7 @@ export default function Copy({ text }: { text: string }) {
|
|||||||
<Clipboard
|
<Clipboard
|
||||||
data-clipboard-text={text}
|
data-clipboard-text={text}
|
||||||
button-title="Copy to clipboard"
|
button-title="Copy to clipboard"
|
||||||
onSuccess={e => onCopySuccess(e)}
|
onSuccess={(e: ClipboardJS.Event) => onCopySuccess(e)}
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
>
|
>
|
||||||
<Icon name="Copy" />
|
<Icon name="Copy" />
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
// import { render } from '@testing-library/react'
|
|
||||||
import testRender from '../../../jest/testRender'
|
|
||||||
|
|
||||||
import Hamburger from './Hamburger'
|
|
||||||
|
|
||||||
describe('Hamburger', () => {
|
|
||||||
testRender(<Hamburger onClick={() => null} />)
|
|
||||||
})
|
|
@ -1,16 +0,0 @@
|
|||||||
import React, { Suspense } from 'react'
|
|
||||||
import { render, waitForElement } from '@testing-library/react'
|
|
||||||
|
|
||||||
import Time from './Time'
|
|
||||||
|
|
||||||
describe('Time', () => {
|
|
||||||
test('renders lazy', async () => {
|
|
||||||
const { getByText } = render(
|
|
||||||
<Suspense fallback="test loading">
|
|
||||||
<Time date="2017/12/23" />
|
|
||||||
</Suspense>
|
|
||||||
)
|
|
||||||
const lazyElement = await waitForElement(() => getByText(/years ago/i))
|
|
||||||
expect(lazyElement).toBeInTheDocument()
|
|
||||||
})
|
|
||||||
})
|
|
@ -4,11 +4,23 @@ import { Image } from '../atoms/Image'
|
|||||||
import styles from './Featured.module.scss'
|
import styles from './Featured.module.scss'
|
||||||
import { Post } from '../../@types/Post'
|
import { Post } from '../../@types/Post'
|
||||||
|
|
||||||
function FeaturedPure({
|
const query = graphql`
|
||||||
data
|
query {
|
||||||
}: {
|
allMarkdownRemark(
|
||||||
data: { allMarkdownRemark: { edges: [{ node: Post }] } }
|
filter: { frontmatter: { featured: { eq: true } } }
|
||||||
}) {
|
sort: { fields: [fields___date], order: DESC }
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...PostTeaser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default function Featured() {
|
||||||
|
const data = useStaticQuery(query)
|
||||||
return (
|
return (
|
||||||
<div className={styles.featured}>
|
<div className={styles.featured}>
|
||||||
{data.allMarkdownRemark.edges.map(({ node }: { node: Post }) => {
|
{data.allMarkdownRemark.edges.map(({ node }: { node: Post }) => {
|
||||||
@ -27,34 +39,3 @@ function FeaturedPure({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = graphql`
|
|
||||||
query {
|
|
||||||
allMarkdownRemark(
|
|
||||||
filter: { frontmatter: { featured: { eq: true } } }
|
|
||||||
sort: { fields: [fields___date], order: DESC }
|
|
||||||
) {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
id
|
|
||||||
frontmatter {
|
|
||||||
title
|
|
||||||
image {
|
|
||||||
childImageSharp {
|
|
||||||
...ImageFluidThumb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fields {
|
|
||||||
slug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default function Featured() {
|
|
||||||
const data = useStaticQuery(query)
|
|
||||||
return <FeaturedPure data={data} />
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'gatsby'
|
import { Link, graphql } from 'gatsby'
|
||||||
import { Image } from '../../components/atoms/Image'
|
import { Image } from '../atoms/Image'
|
||||||
import styles from './PostTeaser.module.scss'
|
import styles from './PostTeaser.module.scss'
|
||||||
import { Post } from '../../@types/Post'
|
import { Post } from '../../@types/Post'
|
||||||
|
|
||||||
|
export const postTeaserQuery = graphql`
|
||||||
|
fragment PostTeaser on MarkdownRemark {
|
||||||
|
id
|
||||||
|
fileAbsolutePath
|
||||||
|
frontmatter {
|
||||||
|
title
|
||||||
|
type
|
||||||
|
linkurl
|
||||||
|
tags
|
||||||
|
featured
|
||||||
|
image {
|
||||||
|
childImageSharp {
|
||||||
|
...ImageFluidThumb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields {
|
||||||
|
slug
|
||||||
|
date(formatString: "MMMM DD, YYYY")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
export default function PostTeaser({
|
export default function PostTeaser({
|
||||||
post,
|
post,
|
||||||
toggleSearch
|
toggleSearch
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import PostTeaser from '../../templates/Post/PostTeaser'
|
import PostTeaser from './PostTeaser'
|
||||||
import styles from './RelatedPosts.module.scss'
|
import styles from './RelatedPosts.module.scss'
|
||||||
import { Post, Frontmatter } from '../../@types/Post'
|
import { Post, Frontmatter } from '../../@types/Post'
|
||||||
|
|
||||||
@ -9,23 +9,7 @@ const query = graphql`
|
|||||||
allMarkdownRemark(sort: { order: DESC, fields: [fields___date] }) {
|
allMarkdownRemark(sort: { order: DESC, fields: [fields___date] }) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...PostTeaser
|
||||||
fileAbsolutePath
|
|
||||||
frontmatter {
|
|
||||||
title
|
|
||||||
type
|
|
||||||
linkurl
|
|
||||||
tags
|
|
||||||
image {
|
|
||||||
childImageSharp {
|
|
||||||
...ImageFluidThumb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fields {
|
|
||||||
slug
|
|
||||||
date(formatString: "MMMM DD, YYYY")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import Container from '../../atoms/Container'
|
import Container from '../../atoms/Container'
|
||||||
import PostTeaser from '../../../templates/Post/PostTeaser'
|
import PostTeaser from '../PostTeaser'
|
||||||
import SearchResultsEmpty from './SearchResultsEmpty'
|
import SearchResultsEmpty from './SearchResultsEmpty'
|
||||||
import styles from './SearchResults.module.scss'
|
import styles from './SearchResults.module.scss'
|
||||||
import { Post } from '../../../@types/Post'
|
import { Post } from '../../../@types/Post'
|
||||||
@ -16,18 +16,7 @@ const query = graphql`
|
|||||||
allMarkdownRemark {
|
allMarkdownRemark {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...PostTeaser
|
||||||
frontmatter {
|
|
||||||
title
|
|
||||||
image {
|
|
||||||
childImageSharp {
|
|
||||||
...ImageFluidThumb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fields {
|
|
||||||
slug
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,7 @@ const ThemeToggleInput = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default function ThemeSwitch() {
|
const HeadMarkup = ({ themeColor }: { themeColor: string }) => (
|
||||||
const darkMode = useDarkMode(false, {
|
|
||||||
classNameDark: 'dark',
|
|
||||||
classNameLight: 'light'
|
|
||||||
})
|
|
||||||
|
|
||||||
const themeColor = darkMode.value ? '#1d2224' : '#e7eef4'
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<meta name="theme-color" content={themeColor} />
|
<meta name="theme-color" content={themeColor} />
|
||||||
<meta
|
<meta
|
||||||
@ -46,6 +37,18 @@ export default function ThemeSwitch() {
|
|||||||
content="black-translucent"
|
content="black-translucent"
|
||||||
/>
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default function ThemeSwitch() {
|
||||||
|
const darkMode = useDarkMode(false, {
|
||||||
|
classNameDark: 'dark',
|
||||||
|
classNameLight: 'light'
|
||||||
|
})
|
||||||
|
const themeColor = darkMode.value ? '#1d2224' : '#e7eef4'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HeadMarkup themeColor={themeColor} />
|
||||||
<aside className={styles.themeSwitch}>
|
<aside className={styles.themeSwitch}>
|
||||||
<label
|
<label
|
||||||
htmlFor="toggle"
|
htmlFor="toggle"
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render } from '@testing-library/react'
|
|
||||||
|
|
||||||
import { VcardPure as Vcard } from './Vcard'
|
|
||||||
import avatar from '../../../jest/__fixtures__/avatar.json'
|
|
||||||
|
|
||||||
const links = [
|
|
||||||
'twitter.com',
|
|
||||||
'github.com',
|
|
||||||
'facebook.com',
|
|
||||||
'feed.xml',
|
|
||||||
'feed.json',
|
|
||||||
'whatever'
|
|
||||||
]
|
|
||||||
|
|
||||||
describe('Vcard', () => {
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
const { container } = render(
|
|
||||||
<Vcard
|
|
||||||
avatar={avatar.edges[0].node.childImageSharp.fixed}
|
|
||||||
name="Hello You"
|
|
||||||
uri="https://demo.com"
|
|
||||||
links={links}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,37 +1,10 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import Img, { FixedObject } from 'gatsby-image'
|
import Img from 'gatsby-image'
|
||||||
import IconLinks from './Networks'
|
import IconLinks from './Networks'
|
||||||
import styles from './Vcard.module.scss'
|
import styles from './Vcard.module.scss'
|
||||||
import { useSiteMetadata } from '../../hooks/use-site-metadata'
|
import { useSiteMetadata } from '../../hooks/use-site-metadata'
|
||||||
|
|
||||||
export function VcardPure({
|
|
||||||
avatar,
|
|
||||||
uri,
|
|
||||||
name,
|
|
||||||
links
|
|
||||||
}: {
|
|
||||||
avatar: FixedObject
|
|
||||||
uri: string
|
|
||||||
name: string
|
|
||||||
links: string[]
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div className={styles.vcard}>
|
|
||||||
<Img className={styles.avatar} fixed={avatar} alt="avatar" />
|
|
||||||
<p className={styles.description}>
|
|
||||||
Blog of designer & developer{' '}
|
|
||||||
<a className="fn" rel="author" href={uri}>
|
|
||||||
{name}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<IconLinks links={links} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Vcard() {
|
|
||||||
const query = graphql`
|
const query = graphql`
|
||||||
query {
|
query {
|
||||||
avatar: allFile(filter: { name: { eq: "avatar" } }) {
|
avatar: allFile(filter: { name: { eq: "avatar" } }) {
|
||||||
@ -48,11 +21,24 @@ export default function Vcard() {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export default function Vcard() {
|
||||||
const data = useStaticQuery(query)
|
const data = useStaticQuery(query)
|
||||||
const { author, rss, jsonfeed } = useSiteMetadata()
|
const { author, rss, jsonfeed } = useSiteMetadata()
|
||||||
const { twitter, github, name, uri } = author
|
const { twitter, github, name, uri } = author
|
||||||
const avatar = data.avatar.edges[0].node.childImageSharp.fixed
|
const avatar = data.avatar.edges[0].node.childImageSharp.fixed
|
||||||
const links = [twitter, github, rss, jsonfeed]
|
const links = [twitter, github, rss, jsonfeed]
|
||||||
|
|
||||||
return <VcardPure avatar={avatar} links={links} uri={uri} name={name} />
|
return (
|
||||||
|
<div className={styles.vcard}>
|
||||||
|
<Img className={styles.avatar} fixed={avatar} alt="avatar" />
|
||||||
|
<p className={styles.description}>
|
||||||
|
Blog of designer & developer{' '}
|
||||||
|
<a className="fn" rel="author" href={uri}>
|
||||||
|
{name}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<IconLinks links={links} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
7
src/components/organisms/Footer.test.tsx
Normal file
7
src/components/organisms/Footer.test.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import testRender from '../../../jest/testRender'
|
||||||
|
import Footer from './Footer'
|
||||||
|
|
||||||
|
describe('Footer', () => {
|
||||||
|
testRender(<Footer />)
|
||||||
|
})
|
7
src/components/organisms/Header.test.tsx
Normal file
7
src/components/organisms/Header.test.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import testRender from '../../../jest/testRender'
|
||||||
|
import Header from './Header'
|
||||||
|
|
||||||
|
describe('Header', () => {
|
||||||
|
testRender(<Header />)
|
||||||
|
})
|
@ -1,7 +1,6 @@
|
|||||||
import { useStaticQuery, graphql } from 'gatsby'
|
import { useStaticQuery, graphql } from 'gatsby'
|
||||||
import { Site } from '../@types/Site'
|
import { Site } from '../@types/Site'
|
||||||
|
|
||||||
export function useSiteMetadata(): Site {
|
|
||||||
const query = graphql`
|
const query = graphql`
|
||||||
query {
|
query {
|
||||||
site {
|
site {
|
||||||
@ -34,6 +33,7 @@ export function useSiteMetadata(): Site {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export function useSiteMetadata(): Site {
|
||||||
const { site } = useStaticQuery(query)
|
const { site } = useStaticQuery(query)
|
||||||
return site.siteMetadata
|
return site.siteMetadata
|
||||||
}
|
}
|
||||||
|
13
src/pages/__tests__/404.test.tsx
Normal file
13
src/pages/__tests__/404.test.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { createHistory, createMemorySource } from '@reach/router'
|
||||||
|
|
||||||
|
import NotFound from '../404'
|
||||||
|
|
||||||
|
describe('/404', () => {
|
||||||
|
const history = createHistory(createMemorySource('/404'))
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const { container } = render(<NotFound location={history.location} />)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
17
src/pages/__tests__/photos.test.tsx
Normal file
17
src/pages/__tests__/photos.test.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { createHistory, createMemorySource } from '@reach/router'
|
||||||
|
|
||||||
|
import Photos from '../photos'
|
||||||
|
import data from '../../../jest/__fixtures__/photos.json'
|
||||||
|
|
||||||
|
describe('/photos', () => {
|
||||||
|
const history = createHistory(createMemorySource('/photos'))
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Photos data={data} location={history.location} />
|
||||||
|
)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
24
src/pages/__tests__/tags.test.tsx
Normal file
24
src/pages/__tests__/tags.test.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { createHistory, createMemorySource } from '@reach/router'
|
||||||
|
|
||||||
|
import Tags from '../tags'
|
||||||
|
|
||||||
|
describe('/tags', () => {
|
||||||
|
const history = createHistory(createMemorySource('/tags'))
|
||||||
|
const data = {
|
||||||
|
allMarkdownRemark: {
|
||||||
|
group: [
|
||||||
|
{ fieldValue: 'android', totalCount: 2 },
|
||||||
|
{ fieldValue: 'aperture', totalCount: 18 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Tags data={data} location={history.location} />
|
||||||
|
)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
13
src/pages/__tests__/thanks.test.tsx
Normal file
13
src/pages/__tests__/thanks.test.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render, waitForElement } from '@testing-library/react'
|
||||||
|
import Thanks from '../thanks'
|
||||||
|
|
||||||
|
describe('/thanks', () => {
|
||||||
|
it('renders without crashing', async () => {
|
||||||
|
const { container } = render(<Thanks />)
|
||||||
|
const lazyElement = await waitForElement(() =>
|
||||||
|
container.querySelector('button')
|
||||||
|
)
|
||||||
|
expect(lazyElement).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
@ -32,7 +32,7 @@ export default function Photos({
|
|||||||
data,
|
data,
|
||||||
location
|
location
|
||||||
}: {
|
}: {
|
||||||
data: { photos: { edges: [{ node: Post }] } }
|
data: any
|
||||||
location: Location
|
location: Location
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
@ -42,7 +42,7 @@ export default function Photos({
|
|||||||
location={location}
|
location={location}
|
||||||
section={styles.photos}
|
section={styles.photos}
|
||||||
>
|
>
|
||||||
{data.photos.edges.map(({ node }) => (
|
{data.photos.edges.map(({ node }: { node: Post }) => (
|
||||||
<PhotoThumb key={node.id} photo={node} />
|
<PhotoThumb key={node.id} photo={node} />
|
||||||
))}
|
))}
|
||||||
</Page>
|
</Page>
|
||||||
|
17
src/templates/Post/index.test.tsx
Normal file
17
src/templates/Post/index.test.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
|
||||||
|
import Post from '.'
|
||||||
|
import data from '../../../jest/__fixtures__/post.json'
|
||||||
|
|
||||||
|
describe('Post', () => {
|
||||||
|
const pageContext = {
|
||||||
|
next: { title: 'hello', slug: '/hello' },
|
||||||
|
prev: { title: 'hello2', slug: '/hello2' }
|
||||||
|
}
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const { container } = render(<Post data={data} pageContext={pageContext} />)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
28
src/templates/Posts.test.tsx
Normal file
28
src/templates/Posts.test.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { createHistory, createMemorySource } from '@reach/router'
|
||||||
|
|
||||||
|
import Posts from './Posts'
|
||||||
|
import data from '../../jest/__fixtures__/posts.json'
|
||||||
|
|
||||||
|
describe('Post', () => {
|
||||||
|
const history = createHistory(createMemorySource('/photos'))
|
||||||
|
|
||||||
|
const pageContext = {
|
||||||
|
tag: 'hello',
|
||||||
|
slug: '/hello',
|
||||||
|
currentPageNumber: 2,
|
||||||
|
numPages: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Posts
|
||||||
|
data={data}
|
||||||
|
pageContext={pageContext}
|
||||||
|
location={history.location}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
@ -17,7 +17,7 @@ export default function Posts({
|
|||||||
location,
|
location,
|
||||||
pageContext
|
pageContext
|
||||||
}: {
|
}: {
|
||||||
data: { allMarkdownRemark: { edges: [{ node: Post }] } }
|
data: any
|
||||||
location: Location
|
location: Location
|
||||||
pageContext: {
|
pageContext: {
|
||||||
tag: string
|
tag: string
|
||||||
|
Loading…
Reference in New Issue
Block a user