Skip to content

Commit

Permalink
test: set up component snapshot testing (Uniswap#2102)
Browse files Browse the repository at this point in the history
* set up snapshot testing

* improvements

* add tests for TextInput as an example

* Fix code style issues with ESLint

* add comment to custom-test-env file

* only set up needed providers

* include style rules in snapshots

* disable redux storage warning

* added setupTests to avoid boilerplate

Co-authored-by: Lint Action <[email protected]>
  • Loading branch information
Justin Domingue and lint-action authored Jul 26, 2021
1 parent 718003b commit 8dfd143
Show file tree
Hide file tree
Showing 8 changed files with 384 additions and 4 deletions.
16 changes: 16 additions & 0 deletions custom-test-env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Custom test environment to provide `TextEncoder`/`TextDecoder`

// eslint-disable-next-line @typescript-eslint/no-var-requires
const Environment = require('jest-environment-jsdom')

module.exports = class CustomTestEnvironment extends Environment {
async setup() {
await super.setup()
if (typeof this.global.TextEncoder === 'undefined') {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { TextEncoder, TextDecoder } = require('util')
this.global.TextEncoder = TextEncoder
this.global.TextDecoder = TextDecoder
}
}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"@reach/portal": "^0.10.3",
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.6.1",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@typechain/ethers-v5": "^7.0.0",
"@types/d3": "^6.7.1",
"@types/jest": "^25.2.1",
Expand Down Expand Up @@ -77,6 +79,7 @@
"graphql": "^15.5.0",
"graphql-request": "^3.4.0",
"inter-ui": "^3.13.1",
"jest-styled-components": "^7.0.5",
"lodash.flatmap": "^4.5.0",
"luxon": "^1.25.0",
"ms.macro": "^2.0.0",
Expand Down Expand Up @@ -134,7 +137,7 @@
"graphql:generate": "graphql-codegen --config codegen.yml",
"postinstall": "yarn compile-contract-types",
"start": "yarn compile-contract-types && react-scripts start",
"test": "react-scripts test --env=jsdom",
"test": "react-scripts test --env=./custom-test-env.js",
"prestart": "yarn graphql:generate && touch src/locales/en-US.po"
},
"eslintConfig": {
Expand Down
130 changes: 130 additions & 0 deletions src/components/TextInput/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ResizableTextArea renders correctly 1`] = `
<DocumentFragment>
.c0 {
font-size: 12;
outline: none;
border: none;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
width: 0;
resize: none;
background-color: #F7F8FA;
-webkit-transition: color 300ms step-start;
transition: color 300ms step-start;
color: #000000;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
width: 100%;
line-height: 1.2;
padding: 0px;
-webkit-appearance: textfield;
}
.c0::-webkit-search-decoration {
-webkit-appearance: none;
}
.c0::-webkit-outer-spin-button,
.c0::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.c0::-webkit-input-placeholder {
color: #C3C5CB;
}
.c0::-moz-placeholder {
color: #C3C5CB;
}
.c0:-ms-input-placeholder {
color: #C3C5CB;
}
.c0::placeholder {
color: #C3C5CB;
}
<textarea
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="c0 testing"
font-size="12"
placeholder="Test Placeholder"
spellcheck="false"
style="height: auto; min-height: 500px;"
>
My test input
</textarea>
</DocumentFragment>
`;

exports[`TextInput renders correctly 1`] = `
<DocumentFragment>
.c0 {
font-size: 12;
outline: none;
border: none;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
width: 0;
background-color: #F7F8FA;
-webkit-transition: color 300ms step-start;
transition: color 300ms step-start;
color: #000000;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
width: 100%;
padding: 0px;
-webkit-appearance: textfield;
}
.c0::-webkit-search-decoration {
-webkit-appearance: none;
}
.c0::-webkit-outer-spin-button,
.c0::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.c0::-webkit-input-placeholder {
color: #C3C5CB;
}
.c0::-moz-placeholder {
color: #C3C5CB;
}
.c0:-ms-input-placeholder {
color: #C3C5CB;
}
.c0::placeholder {
color: #C3C5CB;
}
<div
class="testing"
>
<input
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="c0"
font-size="12"
placeholder="Test Placeholder"
spellcheck="false"
type="text"
value="My test input"
/>
</div>
</DocumentFragment>
`;
68 changes: 68 additions & 0 deletions src/components/TextInput/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { TextInput, ResizingTextArea } from './'
import { render, screen, fireEvent } from 'test-utils'

describe('TextInput', () => {
it('renders correctly', () => {
const { asFragment } = render(
<TextInput
className="testing"
value="My test input"
onUserInput={() => null}
placeholder="Test Placeholder"
fontSize="12"
/>
)
expect(asFragment()).toMatchSnapshot()
})

it('calls the handler on user input', () => {
const onUserInputSpy = jest.fn()
render(
<TextInput
className="testing"
value=""
onUserInput={onUserInputSpy}
placeholder="Test Placeholder"
fontSize="12"
/>
)

fireEvent.change(screen.getByPlaceholderText('Test Placeholder'), { target: { value: 'New value' } })

expect(onUserInputSpy).toHaveBeenCalledWith('New value')
expect(onUserInputSpy).toHaveBeenCalledTimes(1)
})
})

describe('ResizableTextArea', () => {
it('renders correctly', () => {
const { asFragment } = render(
<ResizingTextArea
className="testing"
value="My test input"
onUserInput={() => null}
placeholder="Test Placeholder"
fontSize="12"
/>
)
expect(asFragment()).toMatchSnapshot()
})

it('calls the handler on user input', () => {
const onUserInputSpy = jest.fn()
render(
<ResizingTextArea
className="testing"
value=""
onUserInput={onUserInputSpy}
placeholder="Test Placeholder"
fontSize="12"
/>
)

fireEvent.change(screen.getByPlaceholderText('Test Placeholder'), { target: { value: 'New value' } })

expect(onUserInputSpy).toHaveBeenCalledWith('New value')
expect(onUserInputSpy).toHaveBeenCalledTimes(1)
})
})
5 changes: 5 additions & 0 deletions src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// jest custom assertions
import '@testing-library/jest-dom'

// include style rules in snapshots
import 'jest-styled-components'
2 changes: 1 addition & 1 deletion src/state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const store = configureStore({
.concat(dataApi.middleware)
.concat(routingApi.middleware)
.concat(save({ states: PERSISTED_KEYS, debounce: 1000 })),
preloadedState: load({ states: PERSISTED_KEYS }),
preloadedState: load({ states: PERSISTED_KEYS, disableWarnings: process.env.NODE_ENV === 'test' }),
})

store.dispatch(updateVersion())
Expand Down
19 changes: 19 additions & 0 deletions src/test-utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { FC, ReactElement, ReactNode } from 'react'
import { render, RenderOptions } from '@testing-library/react'
import ThemeProvider from 'theme'
import store from 'state'
import { Provider } from 'react-redux'

const WithProviders: FC = ({ children }: { children?: ReactNode }) => {
return (
<Provider store={store}>
<ThemeProvider>{children}</ThemeProvider>
</Provider>
)
}

const customRender = (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) =>
render(ui, { wrapper: WithProviders, ...options })

export * from '@testing-library/react'
export { customRender as render }
Loading

0 comments on commit 8dfd143

Please sign in to comment.