mirror of
https://github.com/kremalicious/blog.git
synced 2024-12-22 09:13:35 +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>
|
||||
</p>
|
||||
<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 align="center">
|
||||
<a href="https://kremalicious.com">kremalicious.com</a>
|
||||
|
@ -3,12 +3,12 @@ module.exports = {
|
||||
'^.+\\.(tsx?|jsx?)$': 'ts-jest',
|
||||
'^.+\\.jsx?$': '<rootDir>/jest/jest-preprocess.js'
|
||||
},
|
||||
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$',
|
||||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.([tj]sx?)$',
|
||||
moduleNameMapper: {
|
||||
'.+\\.(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)$':
|
||||
'<rootDir>/jest/__mocks__/file-mock.ts',
|
||||
'\\.svg': '<rootDir>/jest/__mocks__/svgr-mock.ts'
|
||||
'<rootDir>/jest/__mocks__/file-mock.js',
|
||||
'\\.svg': '<rootDir>/jest/__mocks__/svgr-mock.js'
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||
testPathIgnorePatterns: ['node_modules', '.cache', 'public', 'coverage'],
|
||||
@ -16,7 +16,6 @@ module.exports = {
|
||||
globals: {
|
||||
__PATH_PREFIX__: ''
|
||||
},
|
||||
testURL: 'http://localhost',
|
||||
setupFiles: ['<rootDir>/jest/loadershim.js'],
|
||||
setupFilesAfterEnv: ['<rootDir>/jest/setup-test-env.ts'],
|
||||
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/@types/**/*']
|
||||
|
@ -1,20 +1,22 @@
|
||||
{
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"childImageSharp": {
|
||||
"fixed": {
|
||||
"aspectRatio": 1,
|
||||
"width": 80,
|
||||
"height": 80,
|
||||
"src": "/static/b61a09d5f4cbd9d8b2844091590ddea4/fce1d/avatar.jpg",
|
||||
"srcSet": "/static/b61a09d5f4cbd9d8b2844091590ddea4/fce1d/avatar.jpg 1x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/c4de8/avatar.jpg 1.5x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/c3234/avatar.jpg 2x",
|
||||
"srcWebp": "/static/b61a09d5f4cbd9d8b2844091590ddea4/ad6b8/avatar.webp",
|
||||
"srcSetWebp": "/static/b61a09d5f4cbd9d8b2844091590ddea4/ad6b8/avatar.webp 1x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/5c322/avatar.webp 1.5x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/5bf6b/avatar.webp 2x",
|
||||
"originalName": "avatar.jpg"
|
||||
"avatar": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"childImageSharp": {
|
||||
"fixed": {
|
||||
"aspectRatio": 1,
|
||||
"width": 80,
|
||||
"height": 80,
|
||||
"src": "/static/b61a09d5f4cbd9d8b2844091590ddea4/fce1d/avatar.jpg",
|
||||
"srcSet": "/static/b61a09d5f4cbd9d8b2844091590ddea4/fce1d/avatar.jpg 1x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/c4de8/avatar.jpg 1.5x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/c3234/avatar.jpg 2x",
|
||||
"srcWebp": "/static/b61a09d5f4cbd9d8b2844091590ddea4/ad6b8/avatar.webp",
|
||||
"srcSetWebp": "/static/b61a09d5f4cbd9d8b2844091590ddea4/ad6b8/avatar.webp 1x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/5c322/avatar.webp 1.5x,\n/static/b61a09d5f4cbd9d8b2844091590ddea4/5bf6b/avatar.webp 2x",
|
||||
"originalName": "avatar.jpg"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
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 * 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",
|
||||
"build": "gatsby build && npm run copy",
|
||||
"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",
|
||||
"copy": "cp -R content/media/ public",
|
||||
"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
|
||||
fluid?: FluidObject
|
||||
fixed?: FixedObject
|
||||
alt: string
|
||||
alt?: 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 testRender from '../../../jest/testRender'
|
||||
import { render } from '@testing-library/react'
|
||||
|
||||
import { PureChangelog as 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'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
import Changelog from './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
|
||||
|
||||
const { object, url, owner } = repoMatch
|
||||
if (!object) return null
|
||||
|
||||
const changelogHtml =
|
||||
object &&
|
||||
@ -53,24 +52,22 @@ export function PureChangelog({
|
||||
)
|
||||
}
|
||||
|
||||
export default function Changelog({ repo }: { repo: string }) {
|
||||
const queryGithub = graphql`
|
||||
query GitHubReposInfo {
|
||||
github {
|
||||
viewer {
|
||||
repositories(first: 100, privacy: PUBLIC, isFork: false) {
|
||||
edges {
|
||||
node {
|
||||
name
|
||||
url
|
||||
owner {
|
||||
login
|
||||
}
|
||||
object(expression: "master:CHANGELOG.md") {
|
||||
id
|
||||
... on GitHub_Blob {
|
||||
text
|
||||
}
|
||||
const queryGithub = graphql`
|
||||
query GitHubReposInfo {
|
||||
github {
|
||||
viewer {
|
||||
repositories(first: 100, privacy: PUBLIC, isFork: false) {
|
||||
edges {
|
||||
node {
|
||||
name
|
||||
url
|
||||
owner {
|
||||
login
|
||||
}
|
||||
object(expression: "master:CHANGELOG.md") {
|
||||
id
|
||||
... on GitHub_Blob {
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,7 +75,10 @@ export default function Changelog({ repo }: { repo: string }) {
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
`
|
||||
|
||||
export default function Changelog({ repo }: { repo: string }) {
|
||||
const data: GitHub = useStaticQuery(queryGithub)
|
||||
const repos: [{ node: GitHubRepo }] = data.github.viewer.repositories.edges
|
||||
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
|
||||
data-clipboard-text={text}
|
||||
button-title="Copy to clipboard"
|
||||
onSuccess={e => onCopySuccess(e)}
|
||||
onSuccess={(e: ClipboardJS.Event) => onCopySuccess(e)}
|
||||
className={styles.button}
|
||||
>
|
||||
<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 { Post } from '../../@types/Post'
|
||||
|
||||
function FeaturedPure({
|
||||
data
|
||||
}: {
|
||||
data: { allMarkdownRemark: { edges: [{ node: Post }] } }
|
||||
}) {
|
||||
const query = graphql`
|
||||
query {
|
||||
allMarkdownRemark(
|
||||
filter: { frontmatter: { featured: { eq: true } } }
|
||||
sort: { fields: [fields___date], order: DESC }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
...PostTeaser
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default function Featured() {
|
||||
const data = useStaticQuery(query)
|
||||
return (
|
||||
<div className={styles.featured}>
|
||||
{data.allMarkdownRemark.edges.map(({ node }: { node: Post }) => {
|
||||
@ -27,34 +39,3 @@ function FeaturedPure({
|
||||
</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 { Link } from 'gatsby'
|
||||
import { Image } from '../../components/atoms/Image'
|
||||
import { Link, graphql } from 'gatsby'
|
||||
import { Image } from '../atoms/Image'
|
||||
import styles from './PostTeaser.module.scss'
|
||||
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({
|
||||
post,
|
||||
toggleSearch
|
@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import PostTeaser from '../../templates/Post/PostTeaser'
|
||||
import PostTeaser from './PostTeaser'
|
||||
import styles from './RelatedPosts.module.scss'
|
||||
import { Post, Frontmatter } from '../../@types/Post'
|
||||
|
||||
@ -9,23 +9,7 @@ const query = graphql`
|
||||
allMarkdownRemark(sort: { order: DESC, fields: [fields___date] }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
fileAbsolutePath
|
||||
frontmatter {
|
||||
title
|
||||
type
|
||||
linkurl
|
||||
tags
|
||||
image {
|
||||
childImageSharp {
|
||||
...ImageFluidThumb
|
||||
}
|
||||
}
|
||||
}
|
||||
fields {
|
||||
slug
|
||||
date(formatString: "MMMM DD, YYYY")
|
||||
}
|
||||
...PostTeaser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import Container from '../../atoms/Container'
|
||||
import PostTeaser from '../../../templates/Post/PostTeaser'
|
||||
import PostTeaser from '../PostTeaser'
|
||||
import SearchResultsEmpty from './SearchResultsEmpty'
|
||||
import styles from './SearchResults.module.scss'
|
||||
import { Post } from '../../../@types/Post'
|
||||
@ -16,18 +16,7 @@ const query = graphql`
|
||||
allMarkdownRemark {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
frontmatter {
|
||||
title
|
||||
image {
|
||||
childImageSharp {
|
||||
...ImageFluidThumb
|
||||
}
|
||||
}
|
||||
}
|
||||
fields {
|
||||
slug
|
||||
}
|
||||
...PostTeaser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,23 +29,26 @@ const ThemeToggleInput = ({
|
||||
/>
|
||||
)
|
||||
|
||||
const HeadMarkup = ({ themeColor }: { themeColor: string }) => (
|
||||
<Helmet>
|
||||
<meta name="theme-color" content={themeColor} />
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
</Helmet>
|
||||
)
|
||||
|
||||
export default function ThemeSwitch() {
|
||||
const darkMode = useDarkMode(false, {
|
||||
classNameDark: 'dark',
|
||||
classNameLight: 'light'
|
||||
})
|
||||
|
||||
const themeColor = darkMode.value ? '#1d2224' : '#e7eef4'
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<meta name="theme-color" content={themeColor} />
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
</Helmet>
|
||||
<HeadMarkup themeColor={themeColor} />
|
||||
<aside className={styles.themeSwitch}>
|
||||
<label
|
||||
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,21 +1,33 @@
|
||||
import React from 'react'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import Img, { FixedObject } from 'gatsby-image'
|
||||
import Img from 'gatsby-image'
|
||||
import IconLinks from './Networks'
|
||||
import styles from './Vcard.module.scss'
|
||||
import { useSiteMetadata } from '../../hooks/use-site-metadata'
|
||||
|
||||
export function VcardPure({
|
||||
avatar,
|
||||
uri,
|
||||
name,
|
||||
links
|
||||
}: {
|
||||
avatar: FixedObject
|
||||
uri: string
|
||||
name: string
|
||||
links: string[]
|
||||
}) {
|
||||
const query = graphql`
|
||||
query {
|
||||
avatar: allFile(filter: { name: { eq: "avatar" } }) {
|
||||
edges {
|
||||
node {
|
||||
childImageSharp {
|
||||
fixed(width: 80, height: 80, quality: 90) {
|
||||
...GatsbyImageSharpFixed_withWebp_noBase64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default function Vcard() {
|
||||
const data = useStaticQuery(query)
|
||||
const { author, rss, jsonfeed } = useSiteMetadata()
|
||||
const { twitter, github, name, uri } = author
|
||||
const avatar = data.avatar.edges[0].node.childImageSharp.fixed
|
||||
const links = [twitter, github, rss, jsonfeed]
|
||||
|
||||
return (
|
||||
<div className={styles.vcard}>
|
||||
<Img className={styles.avatar} fixed={avatar} alt="avatar" />
|
||||
@ -30,29 +42,3 @@ export function VcardPure({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Vcard() {
|
||||
const query = graphql`
|
||||
query {
|
||||
avatar: allFile(filter: { name: { eq: "avatar" } }) {
|
||||
edges {
|
||||
node {
|
||||
childImageSharp {
|
||||
fixed(width: 80, height: 80, quality: 90) {
|
||||
...GatsbyImageSharpFixed_withWebp_noBase64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const data = useStaticQuery(query)
|
||||
const { author, rss, jsonfeed } = useSiteMetadata()
|
||||
const { twitter, github, name, uri } = author
|
||||
const avatar = data.avatar.edges[0].node.childImageSharp.fixed
|
||||
const links = [twitter, github, rss, jsonfeed]
|
||||
|
||||
return <VcardPure avatar={avatar} links={links} uri={uri} name={name} />
|
||||
}
|
||||
|
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,39 +1,39 @@
|
||||
import { useStaticQuery, graphql } from 'gatsby'
|
||||
import { Site } from '../@types/Site'
|
||||
|
||||
export function useSiteMetadata(): Site {
|
||||
const query = graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
siteTitle
|
||||
siteTitleShort
|
||||
siteDescription
|
||||
siteUrl
|
||||
author {
|
||||
name
|
||||
email
|
||||
uri
|
||||
twitter
|
||||
github
|
||||
facebook
|
||||
bitcoin
|
||||
ether
|
||||
}
|
||||
typekitID
|
||||
menu {
|
||||
title
|
||||
link
|
||||
}
|
||||
rss
|
||||
jsonfeed
|
||||
itemsPerPage
|
||||
repoContentPath
|
||||
const query = graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
siteTitle
|
||||
siteTitleShort
|
||||
siteDescription
|
||||
siteUrl
|
||||
author {
|
||||
name
|
||||
email
|
||||
uri
|
||||
twitter
|
||||
github
|
||||
facebook
|
||||
bitcoin
|
||||
ether
|
||||
}
|
||||
typekitID
|
||||
menu {
|
||||
title
|
||||
link
|
||||
}
|
||||
rss
|
||||
jsonfeed
|
||||
itemsPerPage
|
||||
repoContentPath
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
`
|
||||
|
||||
export function useSiteMetadata(): Site {
|
||||
const { site } = useStaticQuery(query)
|
||||
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,
|
||||
location
|
||||
}: {
|
||||
data: { photos: { edges: [{ node: Post }] } }
|
||||
data: any
|
||||
location: Location
|
||||
}) {
|
||||
return (
|
||||
@ -42,7 +42,7 @@ export default function Photos({
|
||||
location={location}
|
||||
section={styles.photos}
|
||||
>
|
||||
{data.photos.edges.map(({ node }) => (
|
||||
{data.photos.edges.map(({ node }: { node: Post }) => (
|
||||
<PhotoThumb key={node.id} photo={node} />
|
||||
))}
|
||||
</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,
|
||||
pageContext
|
||||
}: {
|
||||
data: { allMarkdownRemark: { edges: [{ node: Post }] } }
|
||||
data: any
|
||||
location: Location
|
||||
pageContext: {
|
||||
tag: string
|
||||
|
Loading…
Reference in New Issue
Block a user