An easy-to-use platform for EEG experimentation in the classroom
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

scripts and test

+498 -101
-3
internals/flow/CSSModule.js.flow
··· 1 - // @flow 2 - 3 - declare export default { [key: string]: string }
-2
internals/flow/WebpackAsset.js.flow
··· 1 - // @flow 2 - declare export default string
internals/img/eslint-padded-90.png

This is a binary file and will not be displayed.

internals/img/eslint-padded.png

This is a binary file and will not be displayed.

internals/img/eslint.png

This is a binary file and will not be displayed.

internals/img/flow-padded-90.png

This is a binary file and will not be displayed.

internals/img/flow-padded.png

This is a binary file and will not be displayed.

internals/img/flow.png

This is a binary file and will not be displayed.

internals/img/jest-padded-90.png

This is a binary file and will not be displayed.

internals/img/jest-padded.png

This is a binary file and will not be displayed.

internals/img/jest.png

This is a binary file and will not be displayed.

internals/img/js-padded.png

This is a binary file and will not be displayed.

internals/img/js.png

This is a binary file and will not be displayed.

internals/img/npm.png

This is a binary file and will not be displayed.

internals/img/react-padded-90.png

This is a binary file and will not be displayed.

internals/img/react-padded.png

This is a binary file and will not be displayed.

internals/img/react-router-padded-90.png

This is a binary file and will not be displayed.

internals/img/react-router-padded.png

This is a binary file and will not be displayed.

internals/img/react-router.png

This is a binary file and will not be displayed.

internals/img/react.png

This is a binary file and will not be displayed.

internals/img/redux-padded-90.png

This is a binary file and will not be displayed.

internals/img/redux-padded.png

This is a binary file and will not be displayed.

internals/img/redux.png

This is a binary file and will not be displayed.

internals/img/webpack-padded-90.png

This is a binary file and will not be displayed.

internals/img/webpack-padded.png

This is a binary file and will not be displayed.

internals/img/webpack.png

This is a binary file and will not be displayed.

internals/img/yarn-padded-90.png

This is a binary file and will not be displayed.

internals/img/yarn-padded.png

This is a binary file and will not be displayed.

internals/img/yarn.png

This is a binary file and will not be displayed.

+8
internals/scripts/.eslintrc
··· 1 + { 2 + "rules": { 3 + "no-console": "off", 4 + "global-require": "off", 5 + "import/no-dynamic-require": "off", 6 + "import/no-extraneous-dependencies": "off" 7 + } 8 + }
+1 -1
internals/scripts/BabelRegister.js
··· 2 2 3 3 require('@babel/register')({ 4 4 extensions: ['.es6', '.es', '.jsx', '.js', '.mjs', '.ts', '.tsx'], 5 - cwd: path.join(__dirname, '..', '..'), 5 + cwd: path.join(__dirname, '..', '..') 6 6 });
+30
internals/scripts/CheckBuildsExist.js
··· 1 + // Check if the renderer and main bundles are built 2 + import path from 'path'; 3 + import chalk from 'chalk'; 4 + import fs from 'fs'; 5 + 6 + const mainPath = path.join(__dirname, '..', '..', 'app', 'main.prod.js'); 7 + const rendererPath = path.join( 8 + __dirname, 9 + '..', 10 + '..', 11 + 'app', 12 + 'dist', 13 + 'renderer.prod.js' 14 + ); 15 + 16 + if (!fs.existsSync(mainPath)) { 17 + throw new Error( 18 + chalk.whiteBright.bgRed.bold( 19 + 'The main process is not built yet. Build it by running "yarn build-main"' 20 + ) 21 + ); 22 + } 23 + 24 + if (!fs.existsSync(rendererPath)) { 25 + throw new Error( 26 + chalk.whiteBright.bgRed.bold( 27 + 'The renderer process is not built yet. Build it by running "yarn build-renderer"' 28 + ) 29 + ); 30 + }
-28
internals/scripts/CheckBuiltsExist.js
··· 1 - // @flow 2 - // Check if the renderer and main bundles are built 3 - import path from 'path'; 4 - import chalk from 'chalk'; 5 - import fs from 'fs'; 6 - 7 - function CheckBuildsExist() { 8 - const mainPath = path.join(__dirname, '..', '..', 'app', 'main.prod.js'); 9 - const rendererPath = path.join(__dirname, '..', '..', 'app', 'dist', 'renderer.prod.js'); 10 - 11 - if (!fs.existsSync(mainPath)) { 12 - throw new Error( 13 - chalk.whiteBright.bgRed.bold( 14 - 'The main process is not built yet. Build it by running "npm run build-main"' 15 - ) 16 - ); 17 - } 18 - 19 - if (!fs.existsSync(rendererPath)) { 20 - throw new Error( 21 - chalk.whiteBright.bgRed.bold( 22 - 'The renderer process is not built yet. Build it by running "npm run build-renderer"' 23 - ) 24 - ); 25 - } 26 - } 27 - 28 - CheckBuildsExist();
+20 -31
internals/scripts/CheckNativeDep.js
··· 1 - // @flow 2 1 import fs from 'fs'; 3 2 import chalk from 'chalk'; 4 3 import { execSync } from 'child_process'; 5 4 import { dependencies } from '../../package.json'; 6 5 7 - (() => { 8 - if (!dependencies) return; 9 - 6 + if (dependencies) { 10 7 const dependenciesKeys = Object.keys(dependencies); 11 8 const nativeDeps = fs 12 9 .readdirSync('node_modules') 13 - .filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`)); 14 - 10 + .filter(folder => fs.existsSync(`node_modules/${folder}/binding.gyp`)); 15 11 try { 16 12 // Find the reason for why the dependency is installed. If it is installed 17 13 // because of a devDependency then that is okay. Warn when it is installed 18 14 // because of a dependency 19 - const dependenciesObject = JSON.parse( 15 + const { dependencies: dependenciesObject } = JSON.parse( 20 16 execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString() 21 17 ); 22 - const rootDependencies = Object.keys(dependenciesObject.dependencies); 23 - const filteredRootDependencies = rootDependencies.filter((rootDependency) => 18 + const rootDependencies = Object.keys(dependenciesObject); 19 + const filteredRootDependencies = rootDependencies.filter(rootDependency => 24 20 dependenciesKeys.includes(rootDependency) 25 21 ); 26 - 27 22 if (filteredRootDependencies.length > 0) { 28 23 const plural = filteredRootDependencies.length > 1; 29 24 console.log(` 30 - 31 - ${chalk.whiteBright.bgYellow.bold('Webpack does not work with native dependencies.')} 25 + ${chalk.whiteBright.bgYellow.bold( 26 + 'Webpack does not work with native dependencies.' 27 + )} 32 28 ${chalk.bold(filteredRootDependencies.join(', '))} ${ 33 29 plural ? 'are native dependencies' : 'is a native dependency' 34 30 } and should be installed inside of the "./app" folder. 35 - 36 - 37 - First uninstall the packages from "./package.json": 38 - ${chalk.whiteBright.bgGreen.bold('npm uninstall your-package')} 39 - 40 - ${chalk.bold('Then, instead of installing the package to the root "./package.json":')} 41 - ${chalk.whiteBright.bgRed.bold('npm install your-package --save')} 42 - 43 - ${chalk.bold('Install the package to "./app/package.json"')} 44 - ${chalk.whiteBright.bgGreen.bold('cd ./app && npm install your-package --save')} 45 - 46 - 47 - Read more about native dependencies at: 31 + First, uninstall the packages from "./package.json": 32 + ${chalk.whiteBright.bgGreen.bold('yarn remove your-package')} 33 + ${chalk.bold( 34 + 'Then, instead of installing the package to the root "./package.json":' 35 + )} 36 + ${chalk.whiteBright.bgRed.bold('yarn add your-package')} 37 + ${chalk.bold('Install the package to "./app/package.json"')} 38 + ${chalk.whiteBright.bgGreen.bold('cd ./app && yarn add your-package')} 39 + Read more about native dependencies at: 48 40 ${chalk.bold( 49 - 'https://github.com/chentsulin/electron-react-boilerplate/wiki/Module-Structure----Two-package.json-Structure' 41 + 'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure' 50 42 )} 51 - 52 - 53 - `); 54 - 43 + `); 55 44 process.exit(1); 56 45 } 57 46 } catch (e) { 58 47 console.log('Native dependencies could not be checked'); 59 48 } 60 - })(); 49 + }
+1 -2
internals/scripts/CheckNodeEnv.js
··· 1 - // @flow 2 1 import chalk from 'chalk'; 3 2 4 - export default function CheckNodeEnv(expectedEnv: string) { 3 + export default function CheckNodeEnv(expectedEnv) { 5 4 if (!expectedEnv) { 6 5 throw new Error('"expectedEnv" not set'); 7 6 }
+12 -15
internals/scripts/CheckPortInUse.js
··· 1 - // @flow 2 1 import chalk from 'chalk'; 3 2 import detectPort from 'detect-port'; 4 3 5 - (function CheckPortInUse() { 6 - const port: string = process.env.PORT || '1212'; 4 + const port = process.env.PORT || '1212'; 7 5 8 - detectPort(port, (err: ?Error, availablePort: number) => { 9 - if (port !== String(availablePort)) { 10 - throw new Error( 11 - chalk.whiteBright.bgRed.bold( 12 - `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 npm run dev` 13 - ) 14 - ); 15 - } else { 16 - process.exit(0); 17 - } 18 - }); 19 - })(); 6 + detectPort(port, (err, availablePort) => { 7 + if (port !== String(availablePort)) { 8 + throw new Error( 9 + chalk.whiteBright.bgRed.bold( 10 + `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 yarn dev` 11 + ) 12 + ); 13 + } else { 14 + process.exit(0); 15 + } 16 + });
+5
internals/scripts/CheckYarn.js
··· 1 + if (!/yarn\.js$/.test(process.env.npm_execpath || '')) { 2 + console.warn( 3 + "\u001b[33mYou don't seem to be using yarn. This could produce unexpected results.\u001b[39m" 4 + ); 5 + }
+7
internals/scripts/DeleteSourceMaps.js
··· 1 + import path from 'path'; 2 + import rimraf from 'rimraf'; 3 + 4 + export default function deleteSourceMaps() { 5 + rimraf.sync(path.join(__dirname, '../../app/dist/*.js.map')); 6 + rimraf.sync(path.join(__dirname, '../../app/*.js.map')); 7 + }
+9 -6
internals/scripts/ElectronRebuild.js
··· 1 - // @flow 2 1 import path from 'path'; 3 2 import { execSync } from 'child_process'; 4 3 import fs from 'fs'; 5 - import dependencies from '../../app/package.json'; 4 + import { dependencies } from '../../app/package.json'; 6 5 7 6 const nodeModulesPath = path.join(__dirname, '..', '..', 'app', 'node_modules'); 8 7 9 - if (Object.keys(dependencies || {}).length > 0 && fs.existsSync(nodeModulesPath)) { 8 + if ( 9 + Object.keys(dependencies || {}).length > 0 && 10 + fs.existsSync(nodeModulesPath) 11 + ) { 10 12 const electronRebuildCmd = 11 13 '../node_modules/.bin/electron-rebuild --parallel --force --types prod,dev,optional --module-dir .'; 12 - 13 14 const cmd = 14 - process.platform === 'win32' ? electronRebuildCmd.replace(/\//g, '\\') : electronRebuildCmd; 15 - 15 + process.platform === 'win32' 16 + ? electronRebuildCmd.replace(/\//g, '\\') 17 + : electronRebuildCmd; 16 18 execSync(cmd, { 17 19 cwd: path.join(__dirname, '..', '..', 'app'), 20 + stdio: 'inherit' 18 21 }); 19 22 }
-13
internals/scripts/RunTests.js
··· 1 - import spawn from 'cross-spawn'; 2 - import path from 'path'; 3 - 4 - const pattern = 5 - process.argv[2] === 'e2e' ? 'test/e2e/.+\\.spec\\.js' : 'test/(?!e2e/)[^/]+/.+\\.spec\\.js$'; 6 - 7 - const result = spawn.sync( 8 - path.normalize('./node_modules/.bin/jest'), 9 - [pattern, ...process.argv.slice(2)], 10 - { stdio: 'inherit' } 11 - ); 12 - 13 - process.exit(result.status);
+13
test/.eslintrc.json
··· 1 + { 2 + "extends": "plugin:testcafe/recommended", 3 + "env": { 4 + "jest/globals": true 5 + }, 6 + "plugins": ["jest", "testcafe"], 7 + "rules": { 8 + "jest/no-disabled-tests": "warn", 9 + "jest/no-focused-tests": "error", 10 + "jest/no-identical-title": "error", 11 + "no-console": "off" 12 + } 13 + }
+13
test/actions/__snapshots__/counter.spec.ts.snap
··· 1 + // Jest Snapshot v1, https://goo.gl/fbAQLP 2 + 3 + exports[`actions should decrement should create decrement action 1`] = ` 4 + Object { 5 + "type": "DECREMENT_COUNTER", 6 + } 7 + `; 8 + 9 + exports[`actions should increment should create increment action 1`] = ` 10 + Object { 11 + "type": "INCREMENT_COUNTER", 12 + } 13 + `;
+45
test/actions/counter.spec.ts
··· 1 + import { spy } from 'sinon'; 2 + import * as actions from '../../app/actions/counter'; 3 + 4 + describe('actions', () => { 5 + it('should increment should create increment action', () => { 6 + expect(actions.increment()).toMatchSnapshot(); 7 + }); 8 + 9 + it('should decrement should create decrement action', () => { 10 + expect(actions.decrement()).toMatchSnapshot(); 11 + }); 12 + 13 + it('should incrementIfOdd should create increment action', () => { 14 + const fn = actions.incrementIfOdd(); 15 + expect(fn).toBeInstanceOf(Function); 16 + const dispatch = spy(); 17 + const getState = () => ({ counter: 1 }); 18 + fn(dispatch, getState); 19 + expect(dispatch.calledWith({ type: actions.INCREMENT_COUNTER })).toBe(true); 20 + }); 21 + 22 + it('should incrementIfOdd shouldnt create increment action if counter is even', () => { 23 + const fn = actions.incrementIfOdd(); 24 + const dispatch = spy(); 25 + const getState = () => ({ counter: 2 }); 26 + fn(dispatch, getState); 27 + expect(dispatch.called).toBe(false); 28 + }); 29 + 30 + // There's no nice way to test this at the moment... 31 + it('should incrementAsync', () => { 32 + return new Promise(resolve => { 33 + const fn = actions.incrementAsync(1); 34 + expect(fn).toBeInstanceOf(Function); 35 + const dispatch = spy(); 36 + fn(dispatch); 37 + setTimeout(() => { 38 + expect(dispatch.calledWith({ type: actions.INCREMENT_COUNTER })).toBe( 39 + true 40 + ); 41 + resolve(); 42 + }, 5); 43 + }); 44 + }); 45 + });
+71
test/components/Counter.spec.tsx
··· 1 + /* eslint react/jsx-props-no-spreading: off */ 2 + import { spy } from 'sinon'; 3 + import React from 'react'; 4 + import Enzyme, { shallow } from 'enzyme'; 5 + import Adapter from 'enzyme-adapter-react-16'; 6 + import { BrowserRouter as Router } from 'react-router-dom'; 7 + import renderer from 'react-test-renderer'; 8 + import Counter from '../../app/components/Counter'; 9 + 10 + Enzyme.configure({ adapter: new Adapter() }); 11 + 12 + function setup() { 13 + const actions = { 14 + increment: spy(), 15 + incrementIfOdd: spy(), 16 + incrementAsync: spy(), 17 + decrement: spy() 18 + }; 19 + const component = shallow(<Counter counter={1} {...actions} />); 20 + return { 21 + component, 22 + actions, 23 + buttons: component.find('button'), 24 + p: component.find('.counter') 25 + }; 26 + } 27 + 28 + describe('Counter component', () => { 29 + it('should should display count', () => { 30 + const { p } = setup(); 31 + expect(p.text()).toMatch(/^1$/); 32 + }); 33 + 34 + it('should first button should call increment', () => { 35 + const { buttons, actions } = setup(); 36 + buttons.at(0).simulate('click'); 37 + expect(actions.increment.called).toBe(true); 38 + }); 39 + 40 + it('should match exact snapshot', () => { 41 + const { actions } = setup(); 42 + const counter = ( 43 + <div> 44 + <Router> 45 + <Counter counter={1} {...actions} /> 46 + </Router> 47 + </div> 48 + ); 49 + const tree = renderer.create(counter).toJSON(); 50 + 51 + expect(tree).toMatchSnapshot(); 52 + }); 53 + 54 + it('should second button should call decrement', () => { 55 + const { buttons, actions } = setup(); 56 + buttons.at(1).simulate('click'); 57 + expect(actions.decrement.called).toBe(true); 58 + }); 59 + 60 + it('should third button should call incrementIfOdd', () => { 61 + const { buttons, actions } = setup(); 62 + buttons.at(2).simulate('click'); 63 + expect(actions.incrementIfOdd.called).toBe(true); 64 + }); 65 + 66 + it('should fourth button should call incrementAsync', () => { 67 + const { buttons, actions } = setup(); 68 + buttons.at(3).simulate('click'); 69 + expect(actions.incrementAsync.called).toBe(true); 70 + }); 71 + });
+67
test/components/__snapshots__/Counter.spec.tsx.snap
··· 1 + // Jest Snapshot v1, https://goo.gl/fbAQLP 2 + 3 + exports[`Counter component should match exact snapshot 1`] = ` 4 + <div> 5 + <div> 6 + <div 7 + className="backButton" 8 + data-tid="backButton" 9 + > 10 + <a 11 + href="/" 12 + onClick={[Function]} 13 + > 14 + <i 15 + className="fa fa-arrow-left fa-3x" 16 + /> 17 + </a> 18 + </div> 19 + <div 20 + className="counter counter" 21 + data-tid="counter" 22 + > 23 + 1 24 + </div> 25 + <div 26 + className="btnGroup" 27 + > 28 + <button 29 + className="btn" 30 + data-tclass="btn" 31 + onClick={[Function]} 32 + type="button" 33 + > 34 + <i 35 + className="fa fa-plus" 36 + /> 37 + </button> 38 + <button 39 + className="btn" 40 + data-tclass="btn" 41 + onClick={[Function]} 42 + type="button" 43 + > 44 + <i 45 + className="fa fa-minus" 46 + /> 47 + </button> 48 + <button 49 + className="btn" 50 + data-tclass="btn" 51 + onClick={[Function]} 52 + type="button" 53 + > 54 + odd 55 + </button> 56 + <button 57 + className="btn" 58 + data-tclass="btn" 59 + onClick={[Function]} 60 + type="button" 61 + > 62 + async 63 + </button> 64 + </div> 65 + </div> 66 + </div> 67 + `;
+61
test/containers/CounterPage.spec.tsx
··· 1 + import React from 'react'; 2 + import Enzyme, { mount } from 'enzyme'; 3 + import Adapter from 'enzyme-adapter-react-16'; 4 + import { Provider } from 'react-redux'; 5 + import { createBrowserHistory } from 'history'; 6 + import { ConnectedRouter } from 'connected-react-router'; 7 + import CounterPage from '../../app/containers/CounterPage'; 8 + import { configureStore } from '../../app/store/configureStore'; 9 + 10 + Enzyme.configure({ adapter: new Adapter() }); 11 + 12 + function setup(initialState = {}) { 13 + const store = configureStore(initialState); 14 + const history = createBrowserHistory(); 15 + const provider = ( 16 + <Provider store={store}> 17 + <ConnectedRouter history={history}> 18 + <CounterPage /> 19 + </ConnectedRouter> 20 + </Provider> 21 + ); 22 + const app = mount(provider); 23 + return { 24 + app, 25 + buttons: app.find('button'), 26 + p: app.find('.counter') 27 + }; 28 + } 29 + 30 + describe('containers', () => { 31 + describe('App', () => { 32 + it('should display initial count', () => { 33 + const { p } = setup(); 34 + expect(p.text()).toMatch(/^0$/); 35 + }); 36 + 37 + it('should display updated count after increment button click', () => { 38 + const { buttons, p } = setup(); 39 + buttons.at(0).simulate('click'); 40 + expect(p.text()).toMatch(/^1$/); 41 + }); 42 + 43 + it('should display updated count after decrement button click', () => { 44 + const { buttons, p } = setup(); 45 + buttons.at(1).simulate('click'); 46 + expect(p.text()).toMatch(/^-1$/); 47 + }); 48 + 49 + it('shouldnt change if even and if odd button clicked', () => { 50 + const { buttons, p } = setup(); 51 + buttons.at(2).simulate('click'); 52 + expect(p.text()).toMatch(/^0$/); 53 + }); 54 + 55 + it('should change if odd and if odd button clicked', () => { 56 + const { buttons, p } = setup({ counter: 1 }); 57 + buttons.at(2).simulate('click'); 58 + expect(p.text()).toMatch(/^2$/); 59 + }); 60 + }); 61 + });
+97
test/e2e/HomePage.e2e.ts
··· 1 + /* eslint jest/expect-expect: off, jest/no-test-callback: off */ 2 + import { ClientFunction, Selector } from 'testcafe'; 3 + import { getPageUrl } from './helpers'; 4 + 5 + const getPageTitle = ClientFunction(() => document.title); 6 + const counterSelector = Selector('[data-tid="counter"]'); 7 + const buttonsSelector = Selector('[data-tclass="btn"]'); 8 + const clickToCounterLink = t => 9 + t.click(Selector('a').withExactText('to Counter')); 10 + const incrementButton = buttonsSelector.nth(0); 11 + const decrementButton = buttonsSelector.nth(1); 12 + const oddButton = buttonsSelector.nth(2); 13 + const asyncButton = buttonsSelector.nth(3); 14 + const getCounterText = () => counterSelector().innerText; 15 + const assertNoConsoleErrors = async t => { 16 + const { error } = await t.getBrowserConsoleMessages(); 17 + await t.expect(error).eql([]); 18 + }; 19 + 20 + fixture`Home Page`.page('../../app/app.html').afterEach(assertNoConsoleErrors); 21 + 22 + test('e2e', async t => { 23 + await t.expect(getPageTitle()).eql('Hello Electron React!'); 24 + }); 25 + 26 + test('should open window and contain expected page title', async t => { 27 + await t.expect(getPageTitle()).eql('Hello Electron React!'); 28 + }); 29 + 30 + test( 31 + 'should not have any logs in console of main window', 32 + assertNoConsoleErrors 33 + ); 34 + 35 + test('should navigate to Counter with click on the "to Counter" link', async t => { 36 + await t 37 + .click('[data-tid=container] > a') 38 + .expect(getCounterText()) 39 + .eql('0'); 40 + }); 41 + 42 + test('should navigate to /counter', async t => { 43 + await t 44 + .click('a') 45 + .expect(getPageUrl()) 46 + .contains('/counter'); 47 + }); 48 + 49 + fixture`Counter Tests` 50 + .page('../../app/app.html') 51 + .beforeEach(clickToCounterLink) 52 + .afterEach(assertNoConsoleErrors); 53 + 54 + test('should display updated count after the increment button click', async t => { 55 + await t 56 + .click(incrementButton) 57 + .expect(getCounterText()) 58 + .eql('1'); 59 + }); 60 + 61 + test('should display updated count after the descrement button click', async t => { 62 + await t 63 + .click(decrementButton) 64 + .expect(getCounterText()) 65 + .eql('-1'); 66 + }); 67 + 68 + test('should not change even counter if odd button clicked', async t => { 69 + await t 70 + .click(oddButton) 71 + .expect(getCounterText()) 72 + .eql('0'); 73 + }); 74 + 75 + test('should change odd counter if odd button clicked', async t => { 76 + await t 77 + .click(incrementButton) 78 + .click(oddButton) 79 + .expect(getCounterText()) 80 + .eql('2'); 81 + }); 82 + 83 + test('should change if async button clicked and a second later', async t => { 84 + await t 85 + .click(asyncButton) 86 + .expect(getCounterText()) 87 + .eql('0') 88 + .expect(getCounterText()) 89 + .eql('1'); 90 + }); 91 + 92 + test('should back to home if back button clicked', async t => { 93 + await t 94 + .click('[data-tid="backButton"] > a') 95 + .expect(Selector('[data-tid="container"]').visible) 96 + .ok(); 97 + });
+4
test/e2e/helpers.ts
··· 1 + /* eslint import/prefer-default-export: off */ 2 + import { ClientFunction } from 'testcafe'; 3 + 4 + export const getPageUrl = ClientFunction(() => window.location.href);
+9
test/reducers/__snapshots__/counter.spec.ts.snap
··· 1 + // Jest Snapshot v1, https://goo.gl/fbAQLP 2 + 3 + exports[`reducers counter should handle DECREMENT_COUNTER 1`] = `0`; 4 + 5 + exports[`reducers counter should handle INCREMENT_COUNTER 1`] = `2`; 6 + 7 + exports[`reducers counter should handle initial state 1`] = `0`; 8 + 9 + exports[`reducers counter should handle unknown action type 1`] = `1`;
+25
test/reducers/counter.spec.ts
··· 1 + import counter from '../../app/reducers/counter'; 2 + import { 3 + INCREMENT_COUNTER, 4 + DECREMENT_COUNTER 5 + } from '../../app/actions/counter'; 6 + 7 + describe('reducers', () => { 8 + describe('counter', () => { 9 + it('should handle initial state', () => { 10 + expect(counter(undefined, {})).toMatchSnapshot(); 11 + }); 12 + 13 + it('should handle INCREMENT_COUNTER', () => { 14 + expect(counter(1, { type: INCREMENT_COUNTER })).toMatchSnapshot(); 15 + }); 16 + 17 + it('should handle DECREMENT_COUNTER', () => { 18 + expect(counter(1, { type: DECREMENT_COUNTER })).toMatchSnapshot(); 19 + }); 20 + 21 + it('should handle unknown action type', () => { 22 + expect(counter(1, { type: 'unknown' })).toMatchSnapshot(); 23 + }); 24 + }); 25 + });