New Jest Example (#10396)
* New Jest Example * add missing zeit logo * Revert zeit.svg * remove old jest examples * Update jest.config.js
This commit is contained in:
parent
1db77143f6
commit
9a8c3100d2
58 changed files with 373 additions and 932 deletions
|
@ -21,6 +21,7 @@
|
|||
}
|
||||
},
|
||||
"overrides": [
|
||||
{ "files": ["**/__tests__/**"], "env": { "jest": true } },
|
||||
{
|
||||
"files": ["**/*.ts", "**/*.tsx"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
"next/babel"
|
||||
],
|
||||
"plugins": [
|
||||
"transform-flow-strip-types"
|
||||
]
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"parser": "babel-eslint"
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[ignore]
|
||||
.*/node_modules/*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
|
@ -1,42 +0,0 @@
|
|||
# Example app with Jest tests and [Flow](https://flowtype.org/)
|
||||
|
||||
This example features an app with jest tests and the [Flow](https://flowtype.org/) static type checker, with the transform-flow-strip-types babel plugin stripping flow type annotations from your output code.
|
||||
|
||||
## How to use
|
||||
|
||||
### Using `create-next-app`
|
||||
|
||||
Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
|
||||
|
||||
```bash
|
||||
npm init next-app --example with-jest-flow with-jest-flow-app
|
||||
# or
|
||||
yarn create next-app --example with-jest-flow with-jest-flow-app
|
||||
```
|
||||
|
||||
### Download manually
|
||||
|
||||
Download the example:
|
||||
|
||||
```bash
|
||||
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-jest-flow
|
||||
cd with-jest-flow
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
# or
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
## Run Jest tests
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
# or
|
||||
yarn test
|
||||
```
|
|
@ -1,9 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`With Snapshot Testing App shows "Hello World" 1`] = `
|
||||
<section>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</section>
|
||||
`;
|
|
@ -1,23 +0,0 @@
|
|||
/* eslint-env jest */
|
||||
|
||||
import { shallow } from 'enzyme'
|
||||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
|
||||
import App from '../pages/index.js'
|
||||
|
||||
describe('With Enzyme', () => {
|
||||
it('App shows "Hello World"', () => {
|
||||
const app = shallow(<App />)
|
||||
|
||||
expect(app.find('div').text()).toEqual('Hello World')
|
||||
})
|
||||
})
|
||||
|
||||
describe('With Snapshot Testing', () => {
|
||||
it('App shows "Hello World"', () => {
|
||||
const component = renderer.create(<App />)
|
||||
const tree = component.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
})
|
|
@ -1,17 +0,0 @@
|
|||
// @flow
|
||||
import React, { type Node } from 'react'
|
||||
import Head from 'next/head'
|
||||
|
||||
type Props = {
|
||||
children: Node,
|
||||
title?: string,
|
||||
}
|
||||
|
||||
export default ({ children, title = 'This is the default title' }: Props) => (
|
||||
<section>
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
</Head>
|
||||
{children}
|
||||
</section>
|
||||
)
|
|
@ -1,35 +0,0 @@
|
|||
// @flow
|
||||
|
||||
declare module "next" {
|
||||
declare type NextApp = {
|
||||
prepare(): Promise<void>;
|
||||
getRequestHandler(): any;
|
||||
render(req: any, res: any, pathname: string, query: any): any;
|
||||
renderToHTML(req: any, res: any, pathname: string, query: string): string;
|
||||
renderError(err: Error, req: any, res: any, pathname: any, query: any): any;
|
||||
renderErrorToHTML(err: Error, req: any, res: any, pathname: string, query: any): string;
|
||||
};
|
||||
declare module.exports: (...opts: any) => NextApp
|
||||
}
|
||||
|
||||
declare module "next/head" {
|
||||
declare module.exports: Class<React$Component<any, any>>;
|
||||
}
|
||||
|
||||
declare module "next/link" {
|
||||
declare module.exports: Class<React$Component<{href: string, prefetch?: bool}, any>>;
|
||||
}
|
||||
|
||||
declare module "next/error" {
|
||||
declare module.exports: Class<React$Component<{statusCode: number}, any>>;
|
||||
}
|
||||
|
||||
declare module "next/document" {
|
||||
declare export var Head: Class<React$Component<any, any>>;
|
||||
declare export var Main: Class<React$Component<any, any>>;
|
||||
declare export var NextScript: Class<React$Component<any, any>>;
|
||||
declare export default Class<React$Component<any, any>> & {
|
||||
getInitialProps: (ctx: {pathname: string, query: any, req?: any, res?: any, err?: any}) => Promise<any>;
|
||||
renderPage(cb: Function): void;
|
||||
};
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
module.exports = {
|
||||
setupFiles: ['<rootDir>/jest.setup.js'],
|
||||
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
import { configure } from 'enzyme'
|
||||
import Adapter from 'enzyme-adapter-react-16'
|
||||
|
||||
configure({ adapter: new Adapter() })
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"name": "with-jest-flow",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
"flow": "flow",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"react": "latest",
|
||||
"react-dom": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "latest",
|
||||
"babel-eslint": "latest",
|
||||
"babel-jest": "latest",
|
||||
"babel-plugin-transform-flow-strip-types": "latest",
|
||||
"enzyme": "latest",
|
||||
"enzyme-adapter-react-16": "latest",
|
||||
"eslint": "latest",
|
||||
"flow-bin": "latest",
|
||||
"jest": "latest",
|
||||
"react-addons-test-utils": "latest",
|
||||
"react-test-renderer": "latest"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
import Page from '../components/Page'
|
||||
|
||||
export default () => (
|
||||
<Page>
|
||||
<div>Hello World</div>
|
||||
</Page>
|
||||
)
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"presets": ["next/babel"]
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
# Example app with React Testing Library and Jest
|
||||
|
||||
This example features an app with [react testing library](https://github.com/kentcdodds/react-testing-library) by [Kent Dodds](https://github.com/kentcdodds/). This library encourages your applications to be more accessible and allows you to get your tests closer to using your components the way a user will, which allows your tests to give you more confidence that your application will work when a real user uses it. And also, is a replacement for enzyme.
|
||||
|
||||
## How to use
|
||||
|
||||
### Using `create-next-app`
|
||||
|
||||
Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
|
||||
|
||||
```bash
|
||||
npm init next-app --example with-jest-react-testing-library with-rtl-app
|
||||
# or
|
||||
yarn create next-app --example with-jest-react-testing-library with-rtl-app
|
||||
```
|
||||
|
||||
### Download manually
|
||||
|
||||
Download the example:
|
||||
|
||||
```bash
|
||||
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-jest-react-testing-library
|
||||
cd with-jest-react-testing-library
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
# or
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
## Run Tests
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
# or
|
||||
yarn test
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`With React Testing Library Snapshot Should match Snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<p>
|
||||
Hello World!
|
||||
</p>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
|
@ -1,22 +0,0 @@
|
|||
/* eslint-env jest */
|
||||
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
|
||||
import App from '../pages/index.js'
|
||||
|
||||
describe('With React Testing Library', () => {
|
||||
it('Shows "Hello world!"', () => {
|
||||
const { getByText } = render(<App />)
|
||||
|
||||
expect(getByText('Hello World!')).not.toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('With React Testing Library Snapshot', () => {
|
||||
it('Should match Snapshot', () => {
|
||||
const { asFragment } = render(<App />)
|
||||
|
||||
expect(asFragment()).toMatchSnapshot()
|
||||
})
|
||||
})
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "with-jest-react-testing-library",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "^16.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.6.4",
|
||||
"@testing-library/react": "9.3.2",
|
||||
"babel-jest": "24.9.0",
|
||||
"jest": "24.9.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export default () => (
|
||||
<div>
|
||||
<p>Hello World!</p>
|
||||
</div>
|
||||
)
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"presets": ["next/babel"]
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
# Example app with Jest tests inside a NextJS TypeScript app
|
||||
|
||||
This example shows a configuration and several examples for a running Jest tests in a NextJS TypeScript app.
|
||||
|
||||
## How to use
|
||||
|
||||
### Using `create-next-app`
|
||||
|
||||
Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
|
||||
|
||||
```bash
|
||||
npm init next-app --example with-jest-typescript with-jest-typescript-app
|
||||
# or
|
||||
yarn create next-app --example with-jest-typescript with-jest-typescript-app
|
||||
```
|
||||
|
||||
### Download manually
|
||||
|
||||
Download the example:
|
||||
|
||||
```bash
|
||||
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-jest-typescript
|
||||
cd with-jest-typescript
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
# or
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
## Run Jest tests
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
# or
|
||||
yarn test
|
||||
```
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
setupFiles: ['<rootDir>/jest.setup.js'],
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
const Enzyme = require('enzyme')
|
||||
const Adapter = require('enzyme-adapter-react-16')
|
||||
|
||||
Enzyme.configure({ adapter: new Adapter() })
|
2
examples/with-jest-typescript/next-env.d.ts
vendored
2
examples/with-jest-typescript/next-env.d.ts
vendored
|
@ -1,2 +0,0 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"name": "with-jest-typescript",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"react": "^16.8.4",
|
||||
"react-dom": "^16.8.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.23",
|
||||
"@types/react": "^16.8.8",
|
||||
"@types/react-dom": "^16.8.2",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-jest": "^24.9.0",
|
||||
"enzyme": "^3.9.0",
|
||||
"enzyme-adapter-react-16": "^1.11.2",
|
||||
"jest": "^24.9.0",
|
||||
"react-addons-test-utils": "^15.6.2",
|
||||
"react-test-renderer": "^16.8.4",
|
||||
"typescript": "^3.3.3333"
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import CarsOverview from '../src/modules/cars/Overview'
|
||||
|
||||
const CarsPage = () => <CarsOverview />
|
||||
|
||||
export default CarsPage
|
|
@ -1,5 +0,0 @@
|
|||
const IndexPage = () => (
|
||||
<h1>Testing Next.js App written in TypeScript with Jest</h1>
|
||||
)
|
||||
|
||||
export default IndexPage
|
|
@ -1,5 +0,0 @@
|
|||
import Login from '../src/modules/auth/Login'
|
||||
|
||||
const LoginPage = () => <Login />
|
||||
|
||||
export default LoginPage
|
|
@ -1,27 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
interface NiceCheckboxProps {
|
||||
rootID: string
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
label: string
|
||||
}
|
||||
|
||||
const NiceCheckbox: React.SFC<NiceCheckboxProps> = (
|
||||
props: NiceCheckboxProps
|
||||
): JSX.Element => {
|
||||
return (
|
||||
<div className="NiceCheckbox" id={props.rootID}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={props.id}
|
||||
name={props.name}
|
||||
value={props.value}
|
||||
/>
|
||||
<label htmlFor={props.id}>{props.label}</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default NiceCheckbox
|
|
@ -1,25 +0,0 @@
|
|||
/* eslint-env jest */
|
||||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
|
||||
import NiceCheckbox from './index'
|
||||
|
||||
describe('NiceCheckbox', () => {
|
||||
it('renders the checkbox with correct label', () => {
|
||||
const wrapper = shallow(
|
||||
<NiceCheckbox
|
||||
rootID="NiceCarCheckbox"
|
||||
id="CarAvailability"
|
||||
name="is_available"
|
||||
value="yes"
|
||||
label="Is this car available?"
|
||||
/>
|
||||
)
|
||||
expect(
|
||||
wrapper
|
||||
.find('#NiceCarCheckbox')
|
||||
.find('label')
|
||||
.text()
|
||||
).toEqual('Is this car available?')
|
||||
})
|
||||
})
|
|
@ -1,71 +0,0 @@
|
|||
import React, { ChangeEvent } from 'react'
|
||||
import Router from 'next/router'
|
||||
|
||||
import * as T from './types'
|
||||
|
||||
export interface LoginProps {}
|
||||
|
||||
export interface LoginState {
|
||||
credentials: T.LoginCredentials
|
||||
isLoginLoading: boolean
|
||||
}
|
||||
|
||||
export default class Login extends React.Component<LoginProps, LoginState> {
|
||||
constructor(props: LoginProps) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
isLoginLoading: false,
|
||||
credentials: {
|
||||
email: null,
|
||||
password: null,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
handleCredentialsChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
let { credentials } = this.state
|
||||
credentials[e.target.name] = e.target.value
|
||||
|
||||
this.setState({ credentials })
|
||||
}
|
||||
|
||||
handleLoginSubmit = (e: React.MouseEvent<HTMLElement>) => {
|
||||
e.preventDefault()
|
||||
this.setState({ isLoginLoading: true })
|
||||
|
||||
setTimeout(() => {
|
||||
this.setState({ isLoginLoading: false })
|
||||
Router.replace('/cars')
|
||||
}, 500)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { credentials } = this.state
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
<form>
|
||||
<input
|
||||
id="formEmail"
|
||||
name="email"
|
||||
type="text"
|
||||
value={credentials.email}
|
||||
onChange={this.handleCredentialsChange}
|
||||
/>
|
||||
<input
|
||||
name="password"
|
||||
type="password"
|
||||
value={credentials.password}
|
||||
onChange={this.handleCredentialsChange}
|
||||
/>
|
||||
|
||||
<button id="loginSubmit" onClick={this.handleLoginSubmit}>
|
||||
{this.state.isLoginLoading ? 'Logging in...' : 'Log in'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/* eslint-env jest */
|
||||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
|
||||
import Login from './../Login'
|
||||
|
||||
describe('Login', () => {
|
||||
it('renders the h1 title', () => {
|
||||
const login = shallow(<Login />)
|
||||
expect(login.find('h1').text()).toEqual('Login')
|
||||
})
|
||||
|
||||
it('renders the form', () => {
|
||||
const login = shallow(<Login />)
|
||||
expect(login.find('form')).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('changes the text of email', () => {
|
||||
const login = shallow(<Login />)
|
||||
login.find('#formEmail').simulate('change', {
|
||||
target: {
|
||||
name: 'email',
|
||||
value: 'some@test.com',
|
||||
},
|
||||
})
|
||||
expect(
|
||||
login
|
||||
.update()
|
||||
.find('#formEmail')
|
||||
.props().value
|
||||
).toEqual('some@test.com')
|
||||
})
|
||||
|
||||
it('changes the text of login button after clicking it', () => {
|
||||
const login = shallow(<Login />)
|
||||
login.find('#loginSubmit').simulate('click', { preventDefault() {} })
|
||||
expect(
|
||||
login
|
||||
.update()
|
||||
.find('#loginSubmit')
|
||||
.text()
|
||||
).toEqual('Logging in...')
|
||||
})
|
||||
})
|
|
@ -1,4 +0,0 @@
|
|||
export interface LoginCredentials {
|
||||
email: string
|
||||
password: string
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import * as T from './types'
|
||||
|
||||
interface DetailProps {
|
||||
car: T.Car
|
||||
}
|
||||
|
||||
const Detail: React.SFC<DetailProps> = ({ car }: DetailProps) => {
|
||||
return (
|
||||
<div className="CarDetail">
|
||||
<h1>{`${car.make} ${car.model}`}</h1>
|
||||
<p>Engine : {car.engine}</p>
|
||||
<p>Year : {car.year}</p>
|
||||
<p>Mileage : {car.mileage}</p>
|
||||
<p>Equipment :</p>
|
||||
<ul>
|
||||
{car.equipment &&
|
||||
car.equipment.map((e: string, index: number) => (
|
||||
<li key={index}>{e}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Detail
|
|
@ -1,71 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import * as T from './types'
|
||||
|
||||
export interface CarsOverviewProps {
|
||||
cars?: T.CarList
|
||||
}
|
||||
|
||||
export interface CarsOverviewState {
|
||||
selectedCar: T.Car
|
||||
}
|
||||
|
||||
export default class CarsOverview extends React.Component<
|
||||
CarsOverviewProps,
|
||||
CarsOverviewState
|
||||
> {
|
||||
constructor(props: CarsOverviewProps) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
selectedCar: null,
|
||||
}
|
||||
}
|
||||
|
||||
handleSelectCar = (car: T.Car): void => {
|
||||
this.setState({ selectedCar: car })
|
||||
}
|
||||
|
||||
renderCarsList = (cars?: T.CarList): JSX.Element => {
|
||||
if (!cars || cars.length === 0) {
|
||||
return <p>No cars</p>
|
||||
}
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{cars.map(
|
||||
(car: T.Car, index: number): JSX.Element => (
|
||||
<li key={index} onClick={() => this.handleSelectCar(car)}>
|
||||
{car.make} {car.model}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
renderCarInfo = (car: T.Car): JSX.Element => {
|
||||
if (!car) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="CarInfo">
|
||||
<h2>{`${car.make} ${car.model}`}</h2>
|
||||
<section>{car.engine}</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Cars Overview</h1>
|
||||
|
||||
<div className="Cars__List">{this.renderCarsList(this.props.cars)}</div>
|
||||
|
||||
{this.renderCarInfo(this.state.selectedCar)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/* eslint-env jest */
|
||||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
|
||||
import Detail from './../Detail'
|
||||
|
||||
const __CAR__ = {
|
||||
make: 'Volvo',
|
||||
model: 'XC60',
|
||||
engine: 'T5',
|
||||
year: 2018,
|
||||
mileage: 123,
|
||||
equipment: ['Leather', 'Seat heating', 'City Safety'],
|
||||
}
|
||||
|
||||
describe('Car detail', () => {
|
||||
it('renders correct title', () => {
|
||||
const detail = shallow(<Detail car={__CAR__} />)
|
||||
expect(detail.find('h1').text()).toEqual('Volvo XC60')
|
||||
})
|
||||
|
||||
it('renders correct list item', () => {
|
||||
const detail = shallow(<Detail car={__CAR__} />)
|
||||
expect(detail.childAt(1).text()).toEqual('Engine : T5')
|
||||
})
|
||||
|
||||
it('renders correct equipment list item', () => {
|
||||
const detail = shallow(<Detail car={__CAR__} />)
|
||||
expect(
|
||||
detail
|
||||
.children()
|
||||
.find('ul')
|
||||
.childAt(1)
|
||||
.text()
|
||||
).toEqual('Seat heating')
|
||||
})
|
||||
})
|
|
@ -1,91 +0,0 @@
|
|||
/* eslint-env jest */
|
||||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
|
||||
import Overview from './../Overview'
|
||||
|
||||
const __CARS__ = [
|
||||
{
|
||||
make: 'Volvo',
|
||||
model: 'C30',
|
||||
engine: 'T5',
|
||||
year: 2018,
|
||||
mileage: 123,
|
||||
equipment: ['Leather', 'Seat heating', 'City Safety'],
|
||||
},
|
||||
{
|
||||
make: 'Volvo',
|
||||
model: 'XC60',
|
||||
engine: 'D5',
|
||||
year: 2018,
|
||||
mileage: 456,
|
||||
equipment: ['Leather', 'Seat heating', 'City Safety'],
|
||||
},
|
||||
{
|
||||
make: 'Volvo',
|
||||
model: 'XC90',
|
||||
engine: 'T6',
|
||||
year: 2018,
|
||||
mileage: 789,
|
||||
equipment: ['Leather', 'Seat heating', 'City Safety'],
|
||||
},
|
||||
]
|
||||
|
||||
describe('Cars overview', () => {
|
||||
it('renders the h1 title', () => {
|
||||
const overview = shallow(<Overview cars={[]} />)
|
||||
expect(overview.find('h1').text()).toEqual('Cars Overview')
|
||||
})
|
||||
|
||||
it('renders empty cars list when no cars are provided', () => {
|
||||
const overview = shallow(<Overview cars={[]} />)
|
||||
expect(
|
||||
overview
|
||||
.find('.Cars__List')
|
||||
.children()
|
||||
.find('p')
|
||||
.text()
|
||||
).toEqual('No cars')
|
||||
})
|
||||
|
||||
it('renders cars list with 3 items when 3 cars are provided', () => {
|
||||
const overview = shallow(<Overview cars={__CARS__} />)
|
||||
expect(
|
||||
overview
|
||||
.find('.Cars__List')
|
||||
.children()
|
||||
.find('ul')
|
||||
.children()
|
||||
).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('renders cars list with the expected item on third place', () => {
|
||||
const overview = shallow(<Overview cars={__CARS__} />)
|
||||
expect(
|
||||
overview
|
||||
.find('.Cars__List')
|
||||
.children()
|
||||
.find('ul')
|
||||
.childAt(2)
|
||||
.text()
|
||||
).toEqual('Volvo XC90')
|
||||
})
|
||||
|
||||
it('renders car detail after clicking on an item in cars list', () => {
|
||||
const overview = shallow(<Overview cars={__CARS__} />)
|
||||
overview
|
||||
.find('.Cars__List')
|
||||
.children()
|
||||
.find('ul')
|
||||
.childAt(1)
|
||||
.simulate('click', { preventDefault() {} })
|
||||
|
||||
expect(
|
||||
overview
|
||||
.update()
|
||||
.find('.CarInfo')
|
||||
.find('h2')
|
||||
.text()
|
||||
).toEqual('Volvo XC60')
|
||||
})
|
||||
})
|
|
@ -1,10 +0,0 @@
|
|||
export interface Car {
|
||||
make: string
|
||||
model: string
|
||||
engine: string
|
||||
year: number
|
||||
mileage: number
|
||||
equipment: string[]
|
||||
}
|
||||
|
||||
export type CarList = Array<Car>
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"jsx": "preserve",
|
||||
"allowJs": true,
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": true,
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"lib": ["dom", "es2015", "es2016"],
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx"
|
||||
],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
|
@ -1,42 +1,21 @@
|
|||
# Example app with Jest tests
|
||||
# Next.js + Jest
|
||||
|
||||
This example features an app with jest tests.
|
||||
This example shows how to configure Jest to work with Next.js.
|
||||
|
||||
## How to use
|
||||
This includes Next.js' built-in support for Global CSS, CSS Modules, and TypeScript!
|
||||
|
||||
### Using `create-next-app`
|
||||
## How to Use
|
||||
|
||||
Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
|
||||
Quickly get started using [Create Next App](https://github.com/zeit/next.js/tree/canary/packages/create-next-app#readme)!
|
||||
|
||||
In your terminal, run the following command:
|
||||
|
||||
```bash
|
||||
npm init next-app --example with-jest with-jest-app
|
||||
# or
|
||||
yarn create next-app --example with-jest with-jest-app
|
||||
npx create-next-app --example with-jest
|
||||
```
|
||||
|
||||
### Download manually
|
||||
|
||||
Download the example:
|
||||
## Run Jest Tests
|
||||
|
||||
```bash
|
||||
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-jest
|
||||
cd with-jest
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
# or
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
## Run Jest tests
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
# or
|
||||
yarn test
|
||||
npm test
|
||||
```
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`With Snapshot Testing App shows "Hello world!" 1`] = `
|
||||
<div
|
||||
className="jsx-2982525546"
|
||||
>
|
||||
<p
|
||||
className="jsx-2982525546"
|
||||
>
|
||||
Hello World!
|
||||
</p>
|
||||
</div>
|
||||
`;
|
89
examples/with-jest/__tests__/__snapshots__/snapshot.js.snap
Normal file
89
examples/with-jest/__tests__/__snapshots__/snapshot.js.snap
Normal file
|
@ -0,0 +1,89 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders homepage unchanged 1`] = `
|
||||
<div
|
||||
className="container"
|
||||
>
|
||||
<main>
|
||||
<h1
|
||||
className="title"
|
||||
>
|
||||
Welcome to
|
||||
<a
|
||||
href="https://nextjs.org"
|
||||
>
|
||||
Next.js!
|
||||
</a>
|
||||
</h1>
|
||||
<p
|
||||
className="description"
|
||||
>
|
||||
Get started by editing
|
||||
<code>
|
||||
pages/index.js
|
||||
</code>
|
||||
</p>
|
||||
<div
|
||||
className="grid"
|
||||
>
|
||||
<a
|
||||
className="card"
|
||||
href="https://nextjs.org/docs"
|
||||
>
|
||||
<h3>
|
||||
Documentation →
|
||||
</h3>
|
||||
<p>
|
||||
Find in-depth information about Next.js features and API.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
className="card"
|
||||
href="https://nextjs.org/learn"
|
||||
>
|
||||
<h3>
|
||||
Learn →
|
||||
</h3>
|
||||
<p>
|
||||
Learn about Next.js in an interactive course with quizzes!
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
className="card"
|
||||
href="https://github.com/zeit/next.js/tree/master/examples"
|
||||
>
|
||||
<h3>
|
||||
Examples →
|
||||
</h3>
|
||||
<p>
|
||||
Discover and deploy boilerplate example Next.js projects.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
className="card"
|
||||
href="https://zeit.co/new/nextjs"
|
||||
>
|
||||
<h3>
|
||||
Deploy →
|
||||
</h3>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with ZEIT Now.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<a
|
||||
href="https://zeit.co"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Powered by
|
||||
<img
|
||||
alt="ZEIT Logo"
|
||||
src="/zeit.svg"
|
||||
/>
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
|
@ -1,21 +0,0 @@
|
|||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
import renderer from 'react-test-renderer'
|
||||
|
||||
import App from '../pages/index'
|
||||
|
||||
describe('With Enzyme', () => {
|
||||
it('App shows "Hello world!"', () => {
|
||||
const app = shallow(<App />)
|
||||
|
||||
expect(app.find('p').text()).toEqual('Hello World!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('With Snapshot Testing', () => {
|
||||
it('App shows "Hello world!"', () => {
|
||||
const component = renderer.create(<App />)
|
||||
const tree = component.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
})
|
8
examples/with-jest/__tests__/snapshot.js
Normal file
8
examples/with-jest/__tests__/snapshot.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import Index from '../pages/index'
|
||||
|
||||
it('renders homepage unchanged', () => {
|
||||
const tree = renderer.create(<Index />).toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
11
examples/with-jest/__tests__/testing-library.js
Normal file
11
examples/with-jest/__tests__/testing-library.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import Index from '../pages/index'
|
||||
|
||||
test('renders deploy link', () => {
|
||||
const { getByText } = render(<Index />)
|
||||
const linkElement = getByText(
|
||||
/Instantly deploy your Next\.js site to a public URL with ZEIT Now\./
|
||||
)
|
||||
expect(linkElement).toBeInTheDocument()
|
||||
})
|
8
examples/with-jest/config/jest/cssTransform.js
Normal file
8
examples/with-jest/config/jest/cssTransform.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
process() {
|
||||
return 'module.exports = {};'
|
||||
},
|
||||
getCacheKey() {
|
||||
return 'cssTransform'
|
||||
},
|
||||
}
|
|
@ -1,4 +1,20 @@
|
|||
module.exports = {
|
||||
setupFiles: ['<rootDir>/jest.setup.js'],
|
||||
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
|
||||
collectCoverageFrom: [
|
||||
'**/*.{js,jsx,ts,tsx}',
|
||||
'!**/*.d.ts',
|
||||
'!**/node_modules/**',
|
||||
],
|
||||
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
|
||||
testPathIgnorePatterns: ['/node_modules/', '/.next/'],
|
||||
transform: {
|
||||
'^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/babel-jest',
|
||||
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
'^.+\\.module\\.(css|sass|scss)$',
|
||||
],
|
||||
moduleNameMapper: {
|
||||
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
import { configure } from 'enzyme'
|
||||
import Adapter from 'enzyme-adapter-react-16'
|
||||
|
||||
configure({ adapter: new Adapter() })
|
|
@ -1,21 +1,24 @@
|
|||
{
|
||||
"name": "with-jest",
|
||||
"version": "1.0.0",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"test": "jest --watch",
|
||||
"test:ci": "jest --ci"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "9.1.4",
|
||||
"next": "latest",
|
||||
"react": "16.12.0",
|
||||
"react-dom": "16.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"enzyme": "3.10.0",
|
||||
"enzyme-adapter-react-16": "1.15.1",
|
||||
"jest": "24.9.0",
|
||||
"react-test-renderer": "16.12.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
"@testing-library/jest-dom": "^5.1.0",
|
||||
"@testing-library/react": "^9.4.0",
|
||||
"babel-jest": "^25.1.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^25.1.0",
|
||||
"react-test-renderer": "^16.12.0"
|
||||
}
|
||||
}
|
||||
|
|
6
examples/with-jest/pages/_app.js
Normal file
6
examples/with-jest/pages/_app.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import '../styles/global.css'
|
||||
|
||||
// This default export is required in a new `pages/_app.js` file.
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
|
@ -1,10 +1,57 @@
|
|||
export default () => (
|
||||
<div>
|
||||
<style jsx>{`
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
`}</style>
|
||||
<p>Hello World!</p>
|
||||
import Head from 'next/head'
|
||||
import React from 'react'
|
||||
import styles from './index.module.css'
|
||||
|
||||
const Home = () => (
|
||||
<div className={styles.container}>
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<main>
|
||||
<h1 className={styles.title}>
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
Get started by editing <code>pages/index.js</code>
|
||||
</p>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<a href="https://nextjs.org/docs" className={styles.card}>
|
||||
<h3>Documentation →</h3>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
|
||||
<a href="https://nextjs.org/learn" className={styles.card}>
|
||||
<h3>Learn →</h3>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://github.com/zeit/next.js/tree/master/examples"
|
||||
className={styles.card}
|
||||
>
|
||||
<h3>Examples →</h3>
|
||||
<p>Discover and deploy boilerplate example Next.js projects.</p>
|
||||
</a>
|
||||
|
||||
<a href="https://zeit.co/new/nextjs" className={styles.card}>
|
||||
<h3>Deploy →</h3>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with ZEIT Now.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<a href="https://zeit.co" target="_blank" rel="noopener noreferrer">
|
||||
Powered by <img src="/zeit.svg" alt="ZEIT Logo" />
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default Home
|
||||
|
|
82
examples/with-jest/pages/index.module.css
Normal file
82
examples/with-jest/pages/index.module.css
Normal file
|
@ -0,0 +1,82 @@
|
|||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a:hover,
|
||||
.title a:focus,
|
||||
.title a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
line-height: 1.15;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.5;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 1rem;
|
||||
flex-basis: 45%;
|
||||
padding: 1.5rem;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 10px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.card:hover,
|
||||
.card:focus,
|
||||
.card:active {
|
||||
color: #0070f3;
|
||||
border-color: #0070f3;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
BIN
examples/with-jest/public/favicon.ico
Normal file
BIN
examples/with-jest/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
11
examples/with-jest/public/zeit.svg
Normal file
11
examples/with-jest/public/zeit.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg width="82" height="16" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="url(#prefix__paint0_linear)" d="M9.018 0l9.019 16H0L9.018 0z"/>
|
||||
<path fill="#333" fill-rule="evenodd" d="M51.634 12.028h-6.492V2.052h6.492v1.256H46.61v3.007h4.37V7.57h-4.37v3.202h5.024v1.255zm-14.063 0h-7.235v-1.096l5.342-7.624h-5.253V2.052h7.058v1.097l-5.342 7.623h5.43v1.256zm21.88 0h6.333v-1.256h-2.423V3.308h2.423V2.052h-6.332v1.256h2.441v7.465h-2.441v1.255zm18.22 0h-1.468v-8.72h-3.36V2.052h8.225v1.256H77.67v8.72z" clip-rule="evenodd"/>
|
||||
<defs>
|
||||
<linearGradient id="prefix__paint0_linear" x1="28.022" x2="16.189" y1="22.991" y2="8.569" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#fff"/>
|
||||
<stop offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 768 B |
6
examples/with-jest/setupTests.js
Normal file
6
examples/with-jest/setupTests.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
// optional: configure or set up a testing framework before each test
|
||||
// if you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`
|
||||
|
||||
// used for __tests__/testing-library.js
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect'
|
53
examples/with-jest/styles/global.css
Normal file
53
examples/with-jest/styles/global.css
Normal file
|
@ -0,0 +1,53 @@
|
|||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
footer img {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
Loading…
Reference in a new issue