Skip to content

Commit

Permalink
Fixes and testing
Browse files Browse the repository at this point in the history
  • Loading branch information
jupl committed Jul 15, 2020
1 parent 9ff86e3 commit 99fdc4a
Show file tree
Hide file tree
Showing 37 changed files with 715 additions and 360 deletions.
17 changes: 17 additions & 0 deletions .eslintrc.js
Expand Up @@ -3,4 +3,21 @@
module.exports = {
extends: './node_modules/@jupl/ts/lint',
ignorePatterns: ['coverage/', 'dist/', 'public/'],
rules: {
'@typescript-eslint/ban-ts-ignore': 'off',
'functional/immutable-data': [
'error',
{
ignoreAccessorPattern: [
'module.exports',
'this',
't.context.**',
'exports.*',
'process.**',
],
ignoreImmediateMutation: true,
},
],
'import/no-named-as-default-member': 'off',
},
}
33 changes: 28 additions & 5 deletions .gitignore
@@ -1,8 +1,8 @@
/dist/
/public/

# Created by https://www.gitignore.io/api/node
# Edit at https://www.gitignore.io/?templates=node
# Created by https://www.toptal.com/developers/gitignore/api/node
# Edit at https://www.toptal.com/developers/gitignore?templates=node

### Node ###
# Logs
Expand All @@ -27,6 +27,7 @@ lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output
Expand All @@ -50,12 +51,21 @@ jspm_packages/
# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

Expand All @@ -72,11 +82,18 @@ typings/
# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
# Next.js build output
.next

# nuxt.js build output
# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist
Expand All @@ -90,4 +107,10 @@ typings/
# DynamoDB Local files
.dynamodb/

# End of https://www.gitignore.io/api/node
# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# End of https://www.toptal.com/developers/gitignore/api/node
12 changes: 4 additions & 8 deletions ava.config.js
@@ -1,13 +1,9 @@
/** Ava configuration. */
/**
* Ava configuration.
*/
// eslint-disable-next-line import/no-default-export
export default {
extensions: ['js', 'ts', 'tsx'],
files: ['src/**/{*.,}test.*'],
require: [
'esm',
'tsconfig-paths/register',
'ts-node/register/transpile-only',
'source-map-support/register',
'browser-env/register',
],
require: ['./test/setup'],
}
2 changes: 1 addition & 1 deletion gatsby-config.ts
@@ -1,5 +1,5 @@
import {GatsbyConfig} from 'gatsby'
import {GatsbyMetadata} from '~/gatsby/types/metadata'
import {GatsbyMetadata} from '_/gatsby/types/metadata'

const COLOR = '#663399'

Expand Down
17 changes: 11 additions & 6 deletions package.json
@@ -1,17 +1,17 @@
{
"private": true,
"scripts": {
"build": "cross-env NODE_OPTIONS='-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r dotenv/config' gatsby build",
"build": "cross-env NODE_OPTIONS=\"-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r dotenv/config\" gatsby build",
"lint": "yarn run lint:type && yarn run lint:file .",
"lint:type": "tsc",
"lint:file": "eslint --ext .js,.ts,.tsx",
"lint:fix": "yarn run lint:fix:file .",
"lint:fix:file": "yarn run lint:file --fix",
"server": "yarn run server:dev",
"server:dev": "cross-env NODE_OPTIONS='-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r dotenv/config' gatsby develop",
"server:prod": "yarn run build && cross-env NODE_OPTIONS='-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r dotenv/config' gatsby serve",
"server:dev": "cross-env NODE_OPTIONS=\"-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r dotenv/config\" yarn dlx gatsby develop",
"server:prod": "yarn run build && cross-env NODE_OPTIONS=\"-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r dotenv/config\" gatsby serve",
"start": "yarn run lint && yarn test && yarn run build",
"test": "ava",
"test": "cross-env NODE_OPTIONS=\"-r esm -r tsconfig-paths/register -r ts-node/register/transpile-only -r source-map-support/register\" ava",
"test:update": "yarn run test --update-snapshots",
"test:watch": "yarn run test --watch"
},
Expand Down Expand Up @@ -42,16 +42,21 @@
"typescript": "^3.5.3"
},
"devDependencies": {
"@testing-library/react-hooks": "^3.3.0",
"@types/node": "^14.0.13",
"@types/react": "^16.8.23",
"@types/react-helmet": "^6.0.0",
"@types/react-test-renderer": "^16.9.2",
"@types/sinon": "^9.0.4",
"@types/styled-components": "^5.1.0",
"@types/webpack": "^4.4.35",
"ava": "^3.9.0",
"browser-env": "^3.3.0",
"eslint": "6",
"esm": "^3.2.25",
"prettier": "^2.0.5",
"source-map-support": "^0.5.19"
"react-test-renderer": "^16.13.1",
"sinon": "^9.0.2",
"source-map-support": "^0.5.19",
"testdouble": "^3.16.1"
}
}
4 changes: 2 additions & 2 deletions src/+pages/404.tsx
@@ -1,6 +1,6 @@
import React from 'react'
import {GatsbyLayout} from '~/gatsby/components/layout'
import {GatsbySEO} from '~/gatsby/components/seo'
import {GatsbyLayout} from '_/gatsby/components/layout'
import {GatsbySEO} from '_/gatsby/components/seo'

const HTTP404Page = () => (
<GatsbyLayout>
Expand Down
8 changes: 4 additions & 4 deletions src/+pages/index.tsx
@@ -1,10 +1,10 @@
import {Link} from 'gatsby'
import React from 'react'
import styled from 'styled-components'
import {GatsbyImage} from '~/gatsby/components/image'
import {GatsbyLayout} from '~/gatsby/components/layout'
import {GatsbySEO} from '~/gatsby/components/seo'
import {useGatsbyAstronaut} from '~/gatsby/hooks/astronaut'
import {GatsbyImage} from '_/gatsby/components/image'
import {GatsbyLayout} from '_/gatsby/components/layout'
import {GatsbySEO} from '_/gatsby/components/seo'
import {useGatsbyAstronaut} from '_/gatsby/hooks/astronaut'

const Image = styled(GatsbyImage)`
margin-block-end: 1rem;
Expand Down
4 changes: 2 additions & 2 deletions src/+pages/page-2.tsx
@@ -1,7 +1,7 @@
import {Link} from 'gatsby'
import React from 'react'
import {GatsbyLayout} from '~/gatsby/components/layout'
import {GatsbySEO} from '~/gatsby/components/seo'
import {GatsbyLayout} from '_/gatsby/components/layout'
import {GatsbySEO} from '_/gatsby/components/seo'

const SecondPage = () => (
<GatsbyLayout>
Expand Down
9 changes: 9 additions & 0 deletions src/common/components/header/test.tsx
@@ -0,0 +1,9 @@
import test from 'ava'
import React from 'react'
import {create} from 'react-test-renderer'

test('render', async t => {
const {Header} = await import('.')
const component = create(<Header title="Title" />)
t.snapshot(component.toJSON())
})
26 changes: 26 additions & 0 deletions src/common/components/header/test.tsx.md
@@ -0,0 +1,26 @@
# Snapshot report for `src/common/components/header/test.tsx`

The actual snapshot is saved in `test.tsx.snap`.

Generated by [AVA](https://avajs.dev).

## render

> Snapshot 1
<header
className="sc-AxirZ gELXlJ"
>
<div
className="sc-AxjAm lkPSa-D"
>
<h1>
<a
className="sc-AxiKw iaIeKE"
href="/"
>
Title
</a>
</h1>
</div>
</header>
Binary file added src/common/components/header/test.tsx.snap
Binary file not shown.
27 changes: 0 additions & 27 deletions src/common/hooks/decode.ts

This file was deleted.

22 changes: 22 additions & 0 deletions src/common/hooks/io/index.ts
@@ -0,0 +1,22 @@
import * as IO from 'io-ts'
import {useMemo} from 'react'
import {decode} from '../../util/io'

/**
* Decode wrapped with memoization.
* @param type IO type
* @param value Value to attempt to decode
* @param fallback Optional fallback value to avoid error thrown
* @return Successful value
*/
export const useDecode: typeof decode = (type, value, fallback) =>
useMemo(() => decode(type, value, fallback), [type, value, fallback])

/**
* Encode wrapped with memoization.
* @param type IO type
* @param value Value to encode
* @return Successful value
*/
export const useEncode = <A, O>(type: IO.Encoder<A, O>, value: A) =>
useMemo(() => type.encode(value), [type, value])
25 changes: 25 additions & 0 deletions src/common/util/io/index.ts
@@ -0,0 +1,25 @@
import {isRight} from 'fp-ts/es6/Either'
import * as IO from 'io-ts'
import {reporter} from 'io-ts-reporters'

/**
* Decode wrapped with memoization.
* @param type IO type
* @param value Value to attempt to decode
* @param fallback Optional fallback value to avoid error thrown
* @return Successful value
*/
export const decode = <A>(
type: IO.Decoder<unknown, A>,
value: unknown,
fallback?: A,
) => {
const validation = type.decode(value)
if (!isRight(validation)) {
if (fallback === undefined) {
throw new Error(reporter(validation).join('\n'))
}
return fallback
}
return validation.right
}
18 changes: 18 additions & 0 deletions src/common/util/io/test.ts
@@ -0,0 +1,18 @@
import * as IO from 'io-ts'
import test from 'ava'

test('decode', async t => {
const {decode} = await import('.')
t.is(decode(IO.number, 1), 1)
})

test('decode with fallback', async t => {
const {decode} = await import('.')
t.is(decode(IO.number, 'a', 1), 1)
})

test('decode with error', async t => {
const {decode} = await import('.')
const e = t.throws(() => decode(IO.number, 'a'))
t.is(e.message, 'Expecting number but instead got: "a"')
})
4 changes: 2 additions & 2 deletions src/gatsby/components/image/image.ts
Expand Up @@ -11,8 +11,8 @@ interface Props {
*/
export const SharpFluidImage = styled(Image)`
margin: 0 auto;
max-width: ${({$maxWidth = NaN}: Props) =>
Number.isNaN($maxWidth) ? '' : `${$maxWidth}px`};
${({$maxWidth = NaN}: Props) =>
Number.isNaN($maxWidth) ? '' : `max-width: ${$maxWidth}px`};
`

/**
Expand Down
47 changes: 47 additions & 0 deletions src/gatsby/components/image/test.tsx
@@ -0,0 +1,47 @@
import test from 'ava'
import React from 'react'
import {create} from 'react-test-renderer'

test('render with fixed Sharp image', async t => {
const {GatsbyImage} = await import('.')
const data = {
childImageSharp: {
fixed: {
height: 100,
src: '/some/url',
srcSet: '/some/url 100w, /another/url 200w',
width: 100,
},
},
url: '/some/url',
}
const component = create(<GatsbyImage data={data} />)
t.snapshot(component.toJSON())
})

test('render with fluid Sharp image', async t => {
const {GatsbyImage} = await import('.')
const data = {
childImageSharp: {
fluid: {
aspectRatio: 1,
presentationWidth: 100,
sizes: '(max-width: 50px) 50vw, 100px',
src: '/some/url',
srcSet: '/some/url 100w, /another/url 200w',
},
},
url: '/some/url',
}
const component = create(<GatsbyImage data={data} />)
t.snapshot(component.toJSON())
})

test('render with no Sharp image', async t => {
const {GatsbyImage} = await import('.')
const data = {
url: '/some/url',
}
const component = create(<GatsbyImage data={data} />)
t.snapshot(component.toJSON())
})

0 comments on commit 99fdc4a

Please sign in to comment.