Skip to content

Instantly share code, notes, and snippets.

@JoelCodes
Created April 4, 2019 22:53
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save JoelCodes/b9db8e16859f047848e2a8718945c240 to your computer and use it in GitHub Desktop.
import React, {Component, useState} from 'react';
import {render} from 'react-dom';
import IncrementerPresenter from './IncrementerPresenter'
function useIncrementer(){
const [count, setCount] = useState(0);
function increment(){
setCount(currCount => currCount + 1);
}
return {count, increment};
}
function IncrementerContainer(){
const {count, increment} = useIncrementer();
return <IncrementerPresenter
count={count}
increment={increment}/>;
}
const root = document.getElementById('react-root');
render(<IncrementerContainer/>, root);
module.exports = {
presets: ['@babel/preset-env']
}
import React, {Component} from 'react';
import IncrementerPresenter from './IncrementerPresenter';
export default class IncrementerContainer extends Component {
constructor(props){
super(props);
this.state = {count: 0};
this.increment = this.increment.bind(this)
}
increment(){
this.setState((currState) => ({count: currState.count + 1}));
}
render(){
return <IncrementerPresenter count={this.state.count} increment={this.increment}/>;
}
}
import React from 'react';
import useEmojiSwitcher from './useEmojiSwitcher';
function EmojiDisplay(){
const {currentEmoji} = useEmojiSwitcher(['😠', '😡', '🤬', '😡', '😠', '😤']);
return currentEmoji;
}
export default function IncrementerPresenter({count, increment}){
return (<div>
<p><button onClick={increment}>The Button</button></p>
<p>The button was clicked {count} times</p>
{count < 10 && <EmojiDisplay/>}
</div>);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">
<style>
body, * {
font-family: 'Montserrat';
font-size: 40px;
}
</style>
</head>
<body>
<div id="react-root"></div>
<script src="./app.jsx"></script>
</body>
</html>
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
module.exports = {
// All imported modules in your tests should be mocked automatically
// automock: false,
// Stop running tests after `n` failures
// bail: 0,
// Respect "browser" field in package.json when resolving modules
// browser: false,
// The directory where Jest should store its cached dependency information
// cacheDirectory: "/private/var/folders/62/361bd7k122q_sd3sf6q022q80000gn/T/jest_dx",
// Automatically clear mock calls and instances between every test
clearMocks: true,
// Indicates whether the coverage information should be collected while executing the test
// collectCoverage: false,
// An array of glob patterns indicating a set of files for which coverage information should be collected
// collectCoverageFrom: null,
// The directory where Jest should output its coverage files
coverageDirectory: "coverage",
// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "/node_modules/"
// ],
// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],
// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: null,
// A path to a custom dependency extractor
// dependencyExtractor: null,
// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,
// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],
// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: null,
// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: null,
// A set of global variables that need to be available in all test environments
// globals: {},
// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
// An array of file extensions your modules use
// moduleFileExtensions: [
// "js",
// "json",
// "jsx",
// "ts",
// "tsx",
// "node"
// ],
// A map from regular expressions to module names that allow to stub out resources with a single module
// moduleNameMapper: {},
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
// Activates notifications for test results
// notify: false,
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",
// A preset that is used as a base for Jest's configuration
// preset: null,
// Run tests from one or more projects
// projects: null,
// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
// Automatically reset mock state between every test
// resetMocks: false,
// Reset the module registry before running each individual test
// resetModules: false,
// A path to a custom resolver
// resolver: null,
// Automatically restore mock state between every test
// restoreMocks: false,
// The root directory that Jest should scan for tests and modules within
// rootDir: null,
// A list of paths to directories that Jest should use to search for files in
// roots: [
// "<rootDir>"
// ],
// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",
// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],
// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],
// The test environment that will be used for testing
// testEnvironment: "jest-environment-jsdom",
// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
// Adds a location field to test results
// testLocationInResults: false,
// The glob patterns Jest uses to detect test files
// testMatch: [
// "**/__tests__/**/*.[jt]s?(x)",
// "**/?(*.)+(spec|test).[tj]s?(x)"
// ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "/node_modules/"
// ],
// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],
// This option allows the use of a custom results processor
// testResultsProcessor: null,
// This option allows use of a custom test runner
// testRunner: "jasmine2",
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
// testURL: "http://localhost",
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
// timers: "real",
// A map from regular expressions to paths to transformers
// transform: null,
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "/node_modules/"
// ],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
// Indicates whether each individual test should be reported during the run
// verbose: null,
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],
// Whether to use watchman for file crawling
// watchman: true,
};
{
"name": "react-hooks",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"keywords": [],
"author": "Joel Shinness <me@joelshinness.com> (http://joelshinness.com)",
"license": "ISC",
"dependencies": {
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"babel-jest": "^24.7.1",
"jest": "^24.7.1",
"react-hooks-testing-library": "^0.4.0"
}
}
import {useState, useEffect} from 'react';
export default function useEmojiSwitcher(emoji){
const [currentEmojiIndex, setCurrentEmojiIndex] = useState(0)
useEffect(() => {
const intervalId = setInterval(() => {
console.log('Im intervalling here');
setCurrentEmojiIndex(cei => (cei + 1) % emoji.length);
}, 500);
return () => clearInterval(intervalId);
}, [])
return {currentEmoji: emoji[currentEmojiIndex]}
}
import {useState, useEffect} from 'react';
function getCount(){
return Promise.resolve(3);
}
export default function useIncrementer(){
const [count, setCount] = useState(0);
const [canCount, setCanCount] = useState(false);
function increment(){
setCount(currCount => currCount + 1);
}
useEffect(() => {
getCount()
.then(count => {
setCount(count);
setCanCount(true);
});
}, []);
return {canCount, count, increment};
}
import {renderHook, act} from 'react-hooks-testing-library';
import useIncrementer from './useIncrementer';
describe('useIncrementer', () => {
it('starts with canCount false, and waits for count', () => {
const {result, waitForNextUpdate} = renderHook(useIncrementer);
expect(result.current.canCount).toBe(false);
return waitForNextUpdate()
.then(() => {
expect(result.current.canCount).toBe(true);
expect(result.current.count).toBe(3);
})
});
it('permits incrementing the count by 1', () => {
const {result} = renderHook(useIncrementer);
act(result.current.increment);
expect(result.current.count).toBe(1);
act(result.current.increment)
expect(result.current.count).toBe(2);
});
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment