1
1
mirror of https://github.com/c8r/x0.git synced 2024-07-07 10:16:18 +03:00

Add tests for components

This commit is contained in:
Brent Jackson 2018-06-22 11:13:15 -04:00
parent 5e37afd7a1
commit 453b0f8b2f
11 changed files with 689 additions and 38 deletions

10
.babelrc Normal file
View File

@ -0,0 +1,10 @@
{
"presets": [
"env",
"stage-0",
"react"
],
"plugins": [
"transform-runtime"
]
}

View File

@ -8,3 +8,4 @@ examples
demo
dist
.travis.yml
.babelrc

View File

@ -10,6 +10,7 @@
"start": "./cli.js docs -p 8888",
"build": "./cli.js build docs",
"test": "nyc ava -T 20s",
"test:components": "nyc ava test/components.js",
"cover": "nyc report --reporter=html --reporter=lcov"
},
"keywords": [
@ -40,6 +41,7 @@
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"browser-env": "^3.2.5",
"chalk": "^2.4.1",
"clipboardy": "^1.2.3",
"connect-history-api-fallback": "^1.5.0",
@ -83,8 +85,10 @@
"ava": "^0.25.0",
"isomorphic-fetch": "^2.2.1",
"nyc": "^12.0.1",
"react-test-renderer": "^16.4.1",
"refunk": "^3.0.1",
"rimraf": "^2.6.2",
"sinon": "^6.0.0",
"styled-components": "^3.3.2"
},
"peerDependencies": {
@ -129,16 +133,7 @@
"require": [
"babel-register"
],
"babel": {
"presets": [
"env",
"stage-0",
"react"
],
"plugins": [
"transform-runtime"
]
}
"babel": "inherit"
},
"engines": {
"node": ">=8.0"

View File

@ -1,11 +1,6 @@
import React from 'react'
export default class Catch extends React.Component {
static getDerivedStateFromProps (props, state) {
if (!state.err) return null
return { err: null }
}
state = {
err: null
}
@ -14,27 +9,30 @@ export default class Catch extends React.Component {
this.setState({ err })
}
componentWillReceiveProps (next) {
if (!this.state.err) return
this.setState({ err: null })
}
render () {
const { err } = this.state
if (err) {
return (
<pre
children={err.toString()}
style={{
color: 'white',
backgroundColor: 'red',
fontFamily: 'Menlo, monospace',
fontSize: '14px',
margin: 0,
padding: '16px',
minHeight: '128px',
whiteSpace: 'prewrap'
}}
/>
)
}
if (!err) return this.props.children
return this.props.children
return (
<pre
children={err.toString()}
style={{
color: 'white',
backgroundColor: 'red',
fontFamily: 'Menlo, monospace',
fontSize: '14px',
margin: 0,
padding: '16px',
minHeight: '128px',
whiteSpace: 'prewrap'
}}
/>
)
}
}

View File

@ -255,7 +255,6 @@ export default class Layout extends React.Component {
routes = [],
children,
route,
location,
title = 'x0',
logo,
} = this.props

View File

@ -1,9 +1,10 @@
export { Link, NavLink } from 'react-router-dom'
export { default as ScopeProvider } from './ScopeProvider'
export { default as Catch } from './Catch'
export { default as CenteredLayout } from './CenteredLayout'
export { default as FileList } from './FileList'
export { default as LiveEditor } from './LiveEditor'
export { default as LivePreview } from './LivePreview'
export { default as FileList } from './FileList'
export { default as Catch } from './Catch'
export { default as ScopeProvider } from './ScopeProvider'
export { default as ScrollTop } from './ScrollTop'
export { default as scope } from './scope'

View File

@ -11,7 +11,7 @@ const cleanHREF = href => href
.replace(/\.jsx?$/, '')
export const link = withRouter(({
href,
href = '',
match,
location,
children,

260
test/components.js Normal file
View File

@ -0,0 +1,260 @@
import test from 'ava'
import React from 'react'
import { create as render } from 'react-test-renderer'
import { StaticRouter } from 'react-router-dom'
import sinon from 'sinon'
import browserEnv from 'browser-env'
import {
Catch,
CenteredLayout,
FileList,
Library,
LiveEditor,
LivePreview,
ScopeProvider,
ScrollTop,
SidebarLayout,
scope
} from '../src'
browserEnv()
// make sure this doesn't conflict with webpack tests
global.DIRNAME = __dirname
const renderJSON = el => render(el).toJSON()
test('CenteredLayout renders with active prop', t => {
const json = renderJSON(
<CenteredLayout active>
Hello
</CenteredLayout>
)
t.snapshot(json)
})
test('CenteredLayout does not render without active prop', t => {
const json = renderJSON(
<CenteredLayout>
Hello
</CenteredLayout>
)
t.is(json, 'Hello')
})
test('Catch renders', t => {
const json = renderJSON(
<Catch>Catch</Catch>
)
t.snapshot(json)
})
test('Catch renders error', t => {
const Throws = props => {
throw new Error('nope')
return false
}
const json = renderJSON(
<Catch>
<Throws />
</Catch>
)
t.is(json.type, 'pre')
t.is(json.children[0], 'Error: nope')
t.snapshot(json)
})
test('FileList renders', t => {
const json = renderJSON(
<StaticRouter location='/' context={{}}>
<FileList
routes={[
{
path: '/',
key: '/',
name: 'Home'
}
]}
/>
</StaticRouter>
)
t.snapshot(json)
})
// doesn't seem to render correctly with refs
test.skip('LiveEditor renders', t => {
const json = renderJSON(
<LiveEditor
code='<h1>Hello</h1>'
/>
)
t.snapshot(json)
})
test('LivePreview renders', t => {
const json = renderJSON(
<LivePreview code='<h1>Hello</h1>' />
)
t.snapshot(json)
})
test('ScopeProvider renders', t => {
const json = renderJSON(
<ScopeProvider>
Hello
</ScopeProvider>
)
t.snapshot(json)
})
test('ScrollTop renders', t => {
const json = renderJSON(
<StaticRouter location='/' context={{}}>
<ScrollTop />
</StaticRouter>
)
t.is(json, null)
})
test('ScrollTop scrolls window on location change', t => {
sinon.stub(window, 'scrollTo')
const instance = render(
<StaticRouter location='/' context={{}}>
<ScrollTop />
</StaticRouter>
)
instance.update(
<StaticRouter location='/hello' context={{}}>
<ScrollTop />
</StaticRouter>
)
t.true(window.scrollTo.calledOnce)
window.scrollTo.restore()
})
test('ScrollTop scrolls to hash', t => {
const el = document.body.appendChild(
document.createElement('div')
)
el.id = 'hello'
el.scrollIntoView = sinon.spy()
const instance = render(
<StaticRouter location='/' context={{}}>
<ScrollTop />
</StaticRouter>
)
instance.update(
<StaticRouter location='/#hello' context={{}}>
<ScrollTop />
</StaticRouter>
)
t.true(el.scrollIntoView.calledOnce)
})
test('ScrollTop does not scroll to hash when there is no element', t => {
const el = document.body.appendChild(
document.createElement('div')
)
el.scrollIntoView = sinon.spy()
const instance = render(
<StaticRouter location='/' context={{}}>
<ScrollTop />
</StaticRouter>
)
instance.update(
<StaticRouter location='/#hello' context={{}}>
<ScrollTop />
</StaticRouter>
)
t.false(el.scrollIntoView.calledOnce)
})
test('Library renders', t => {
const json = renderJSON(
<StaticRouter location='/' context={{}}>
<Library
route={{ dirname: '/examples', path: '/examples' }}
routes={[
{
dirname: '/examples',
key: 'hello',
path: '/examples/hello',
name: 'hello',
Component: () => <pre>Hello</pre>
},
]}
/>
</StaticRouter>
)
t.snapshot(json)
})
test('SidebarLayout renders', t => {
const home = {
key: '/',
path: '/',
name: 'index',
props: {},
Component: () => <h1>Home</h1>
}
const json = renderJSON(
<StaticRouter location='/' context={{}}>
<SidebarLayout
children='Content'
route={home}
routes={[
home,
{
key: '/about',
path: '/about',
name: 'about',
Component: () => <h1>About</h1>
}
]}
/>
</StaticRouter>
)
t.snapshot(json)
})
// console.log(require('util').inspect(json, { depth: null }))
const blacklist = {
pre: true
}
Object.keys(scope)
.filter(key => !blacklist[key])
.forEach(key => {
test(`scope.${key} renders`, t => {
const Component = scope[key]
const json = renderJSON(
<StaticRouter context={{}}>
<Component />
</StaticRouter>
)
t.snapshot(json)
})
})
test('scope.pre renders children only', t => {
const json = renderJSON(
React.createElement(scope.pre, null, 'Hello')
)
t.is(json, 'Hello')
})
test('scope.a renders a plain link for absolute URLs', t => {
const Link = scope.a
const json = renderJSON(
<StaticRouter context={{}}>
<Link href='http://example.com'>Hello</Link>
</StaticRouter>
)
t.is(json.props.href, 'http://example.com')
t.snapshot(json)
})

Binary file not shown.

View File

@ -0,0 +1,387 @@
# Snapshot report for `test/components.js`
The actual snapshot is saved in `components.js.snap`.
Generated by [AVA](https://ava.li).
## Catch renders
> Snapshot 1
'Catch'
## CenteredLayout renders with active prop
> Snapshot 1
<div
className="sc-jAaTju esAkYv sc-bdVaJa iHZvIS"
>
Hello
</div>
## FileList renders
> Snapshot 1
[
<pre>
/Users/bjackson/repos/x0/test
</pre>,
<ul>
<li>
<a
href="/"
onClick={Function {}}
>
Home
</a>
</li>
</ul>,
## LivePreview renders
> Snapshot 1
<div
className="sc-bdVaJa kdjLZs"
>
<div
className="react-live"
>
<div
className="react-live-preview"
>
<h1>
Hello
</h1>
</div>
</div>
</div
## ScopeProvider renders
> Snapshot 1
'Hello
## Library renders
> Snapshot 1
<div
className="sc-bbmXgH hCNAIb"
height={192}
width="256px"
>
<a
borderColor="gray"
className="sc-gGBfsJ eBksKh"
href="/examples/hello"
onClick={Function {}}
>
<pre>
Hello
</pre>
<pre>
hello
</pre>
</a>
</div
## SidebarLayout renders
> Snapshot 1
[
<div
className="sc-hEsumM dahmKO"
>
<div
className="sc-fMiknA jgVkvN sc-bwzfXH pjOvZ"
>
<button
className="sc-gzVnrw ghjHJc sc-ifAKCX fFPXoq"
onClick={Function onClick {}}
title="Toggle Menu"
>
<svg
fill="currentcolor"
height={24}
viewBox="0 0 24 24"
width={24}
>
<path
d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"
/>
</svg>
</button>
<h2
className="sc-VigVT dTivBW"
>
x0
</h2>
<div
className="sc-bdVaJa hAzohM"
/>
</div>
<hr
className="sc-kgoBCf eSqAOl"
/>
</div>,
<div
className="sc-jnlKLf fQRDBU sc-bwzfXH pjOvZ"
>
<div
className="sc-fYxtnH bIntzd"
onClick={Function onClick {}}
open={false}
>
<div
className="sc-fMiknA fVCXKt sc-bwzfXH pjOvZ"
>
<h2
className="sc-VigVT gPiNJC"
>
x0
</h2>
<div
className="sc-bdVaJa LbkC"
/>
</div>
<hr
className="sc-kgoBCf eSqAOl"
/>
<ul
className="sc-cIShpX hSGVzQ"
>
<li
className="sc-kafWEX dNChzQ"
>
<a
"aria-current"="page"
className="sc-feJyhm jUiESA sc-dnqmqq iUcnAA active"
href="/"
onClick={Function {}}
style={{}}
>
Index
</a>
</li>
<li
className="sc-kafWEX dNChzQ"
>
<a
'aria-current'={null}
className="sc-feJyhm jUiESA sc-dnqmqq iUcnAA"
href="/about"
onClick={Function {}}
style={undefined}
>
About
</a>
</li>
</ul>
</div>
<main
className="sc-bdVaJa ioTXyJ"
tabIndex={undefined}
>
<div
className="sc-jAaTju jHRdEk sc-bdVaJa iHZvIS"
>
<div
className="sc-ktHwxA dvWgCn sc-bdVaJa iHZvIS"
>
Content
</div>
<div
className="sc-bwzfXH deiOzS"
>
<div
className="sc-bdVaJa LbkC"
/>
<a
className="sc-iwsKbI leRHZB"
href="/about"
onClick={Function {}}
>
<div
className="sc-gqjmRU emCKSy"
>
Next:
</div>
<div
className="sc-gqjmRU entfAd"
>
About
</div>
</a>
</div>
</div>
</main>
</div>,
## scope.blockquote renders
> Snapshot 1
<blockquote
className="sc-chPdSV gReYnD sc-gqjmRU cbBDfA"
/>
## scope.code renders
> Snapshot 1
<pre
className="sc-kGXeez YhsQM"
/>
## scope.h1 renders
> Snapshot 1
<h1
className="sc-VigVT giyuVg"
/>
## scope.h2 renders
> Snapshot 1
<h2
className="sc-VigVT hvHavN"
/>
## scope.h3 renders
> Snapshot 1
<h3
className="sc-VigVT cdnBzZ"
/>
## scope.h4 renders
> Snapshot 1
<h4
className="sc-VigVT bFQvfC"
/>
## scope.h5 renders
> Snapshot 1
<h5
className="sc-VigVT cmwWQF"
/>
## scope.h6 renders
> Snapshot 1
<h6
className="sc-VigVT hUIvmu"
/>
## scope.hr renders
> Snapshot 1
<hr
className="sc-kgoBCf hVsSJm"
/>
## scope.img renders
> Snapshot 1
<img
className="sc-cvbbAY exTuBk"
/>
## scope.inlineCode renders
> Snapshot 1
<code
className="sc-kpOJdX eABHTa"
/>
## scope.li renders
> Snapshot 1
<li
className="sc-gqjmRU bxHISe"
/>
## scope.p renders
> Snapshot 1
<p
className="sc-gqjmRU jWPlsU"
/>
## scope.table renders
> Snapshot 1
<table
className="sc-htpNat jBAZTS"
/>
## scope.ul renders
> Snapshot 1
<ul
className="sc-htpNat houaHu"
/
## scope.a renders
> Snapshot 1
<a
className="sc-htoDjs gLCdRU"
href="/"
onClick={Function {}}
/
## Catch renders error
> Snapshot 1
<pre
style={
{
backgroundColor: 'red',
color: 'white',
fontFamily: 'Menlo, monospace',
fontSize: '14px',
margin: 0,
minHeight: '128px',
padding: '16px',
whiteSpace: 'prewrap',
}
}
>
Error: nope
</pre
## scope.a renders a plain link for absolute URLs
> Snapshot 1
<a
className="sc-htoDjs gLCdRU"
href="http://example.com"
>
Hello
</a>

Binary file not shown.