Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

one-fits-all: Basic mocha + jsverify setup #16

Merged
merged 17 commits into from
Apr 8, 2017
Merged
15 changes: 12 additions & 3 deletions packages/cycle-scripts-one-fits-all/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"cycle-scripts": "./index.js"
},
"dependencies": {
"@types/mocha": "^2.2.40",
"@webpack-blocks/babel6": "^0.4.1",
"@webpack-blocks/dev-server2": "^0.4.0",
"@webpack-blocks/extract-text2": "^0.4.0",
Expand All @@ -29,18 +30,26 @@
"@webpack-blocks/typescript": "^0.4.0",
"@webpack-blocks/webpack2": "^0.4.0",
"autoprefixer": "^6.7.7",
"babel-plugin-istanbul": "^4.1.1",
"babel-plugin-transform-custom-element-classes": "^0.1.0",
"babel-plugin-transform-react-jsx": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.2.2",
"babili-webpack-plugin": "0.0.11",
"copy-webpack-plugin": "^4.0.1",
"cyclejs-test-helpers": "^1.0.1",
"html-looks-like": "^1.0.2",
"html-webpack-plugin": "^2.28.0",
"jsverify": "^0.8.2",
"mocha": "^3.2.0",
"mocha-webpack": "^0.7.0",
"nyc": "^10.2.0",
"progress-bar-webpack-plugin": "^1.9.3",
"snabbdom-pragma": "^1.8.0",
"typescript": "^2.2.1",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.2"
"snabbdom-to-html": "^3.1.1",
"typescript": "^2.2.2",
"webpack": "^2.3.2",
"webpack-dev-server": "^2.4.2",
"webpack-node-externals": "^1.5.4"
}
}
2 changes: 1 addition & 1 deletion packages/cycle-scripts-one-fits-all/scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const spawn = require('cross-spawn');
const path = require('path');

const env = Object.create( process.env );
let env = Object.create( process.env );
env.NODE_ENV = 'production';

const webpack = path.resolve(__dirname, '..', '..', '.bin', 'webpack');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const config = require('./webpack.config.js');
const nodeExternals = require('webpack-node-externals');

module.exports = Object.assign({}, config, {
target: 'node',
externals: [nodeExternals()],
plugins: config.plugins
.filter(p => !(p.options && p.options.template)) //Exclude HtmlWebpackPlugin
});
9 changes: 5 additions & 4 deletions packages/cycle-scripts-one-fits-all/scripts/eject.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const scriptsPath = path.join(process.cwd(), '.scripts')
// Declaring new scripts
const scripts = {
start: 'NODE_ENV=development webpack --config webpack.config.js',
test: 'mocha --colors --require babel-register src/**/**.test.js',
test: 'NODE_ENV=test nyc mocha-webpack --timeout=100000 --colors --webpack-config webpack.config.test.js test/**/*.test.*',
build: 'NODE_ENV=production webpack --config webpack.config.js'
}

Expand All @@ -27,9 +27,6 @@ Object.keys(appPackageJson.devDependencies)
})
devDependencies = Object.assign({}, devDependencies, ownPackageJson.dependencies)

// Delete babel config in package.json
delete appPackageJson.babel

// Write the new package.json
const newPackageJson = Object.assign({}, appPackageJson, {scripts: scripts, devDependencies: devDependencies})
fs.writeFileSync(
Expand All @@ -42,4 +39,8 @@ fs.writeFileSync(
JSON.stringify(appPackageJson.babel)
)

// Delete babel config in package.json
delete appPackageJson.babel

fs.copySync(path.join(__dirname, 'configs', 'webpack.config.js'), 'webpack.config.js')
fs.copySync(path.join(__dirname, 'configs', 'webpack.config.test.js'), 'webpack.config.test.js')
21 changes: 19 additions & 2 deletions packages/cycle-scripts-one-fits-all/scripts/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ const chalk = require('chalk')
const spawn = require('cross-spawn')

const basicDependencies = [
'@cycle/dom@16.0.0',
'@cycle/dom@17.1.0',
'@cycle/http@13.2.0',
'@cycle/run@3.0.0',
'@cycle/time@0.8.0',
'@cycle/run@3.1.0',
'cycle-onionify@3.1.0',
'xstream@10.3.0'
]

Expand Down Expand Up @@ -78,7 +80,22 @@ module.exports = function init (appPath, appName, verbose, originalDirectory) {
'eject': 'cycle-scripts eject'
}

appPackage.nyc = {
include: [
"src"
],
reporter: [
"html",
"text-summary"
]
}

appPackage.babel = {
env: {
test: {
plugins: [ 'istanbul' ]
}
},
presets: [
['env', {
'modules': false,
Expand Down
2 changes: 1 addition & 1 deletion packages/cycle-scripts-one-fits-all/scripts/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const spawn = require('cross-spawn');
const path = require('path');

const env = Object.create( process.env );
let env = Object.create( process.env );
env.NODE_ENV = 'development';

const webpack = path.resolve(__dirname, '..', '..', '.bin', 'webpack-dev-server');
Expand Down
17 changes: 10 additions & 7 deletions packages/cycle-scripts-one-fits-all/scripts/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

const path = require('path')
const spawn = require('cross-spawn')
const chalk = require('chalk')

const mocha = path.resolve(process.cwd(), 'node_modules', '.bin', 'mocha')
let env = Object.create( process.env );
env.NODE_ENV = 'test';

const mocha = path.resolve(process.cwd(), 'node_modules', '.bin', 'nyc')

const args = [
'mocha-webpack',
'--timeout=100000',
'--colors',
'--require',
'babel-register',
!process.env.CI && (console.log(chalk.green.bold('Enabling watch mode')) || '--watch'),
'src/**/*.test.js'
'--webpack-config',
path.join(__dirname, 'configs', 'webpack.config.test.js'),
'test/**/*.test.*'
].filter(Boolean)

spawn(mocha, args, {stdio: 'inherit'})
spawn.sync(mocha, args, { env: env, stdio: 'inherit' })
3 changes: 3 additions & 0 deletions packages/cycle-scripts-one-fits-all/template/gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
build/
.tmp/
node_modules/
coverage/

*.log
7 changes: 0 additions & 7 deletions packages/cycle-scripts-one-fits-all/template/src/app.test.js

This file was deleted.

39 changes: 33 additions & 6 deletions packages/cycle-scripts-one-fits-all/template/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,42 @@
import xs, { Stream } from 'xstream';
import { VNode } from '@cycle/dom';
import { VNode, DOMSource } from '@cycle/dom';

import { Sources, Sinks } from './interfaces';
import { Sources, Sinks, Reducer } from './interfaces';

export function App(sources : Sources) : Sinks
{
const vdom$ : Stream<VNode> = xs.of(
<div>My Awesome Cycle.js app</div>
);
const action$ : Stream<Reducer> = intent(sources.DOM);
const vdom$ : Stream<VNode> = view(sources.onion.state$);

return {
DOM: vdom$
DOM: vdom$,
onion: action$
};
}

function intent(DOM : DOMSource) : Stream<Reducer>
{
const init$ : Stream<Reducer> = xs.of(() => ({ count: 0 }));

const add$ : Stream<Reducer> = DOM.select('.add').events('click')
.mapTo(state => ({ ...state, count: state.count + 1 }));

const subtract$ : Stream<Reducer> = DOM.select('.subtract').events('click')
.mapTo(state => ({ ...state, count: state.count - 1 }));

return xs.merge(init$, add$, subtract$);
}

function view(state$ : Stream<any>) : Stream<VNode>
{
return state$
.map(s => s.count)
.map(count =>
<div>
<h2>My Awesome Cycle.js app</h2>
<span>{ 'Counter: ' + count }</span>
<button type='button' className='add'>Increase</button>
<button type='button' className='subtract'>Decrease</button>
</div>
);
}
3 changes: 2 additions & 1 deletion packages/cycle-scripts-one-fits-all/template/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import 'babel-polyfill'; //This will be replaced based on your babel-env config
import { run } from '@cycle/run';
import { makeDOMDriver } from '@cycle/dom';
import { makeHTTPDriver } from '@cycle/http';
import onionify from 'cycle-onionify';

import { Component } from './interfaces';
import { App } from './app';

const main : Component = App;
const main : Component = onionify(App);

const drivers : any = {
DOM: makeDOMDriver('#app'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { Stream } from 'xstream';
import { VNode, DOMSource } from '@cycle/dom';
import { HTTPSource, RequestOptions } from '@cycle/http';
import { StateSource } from 'cycle-onionify';

export type Sources = {
DOM : DOMSource;
HTTP : HTTPSource;
onion : StateSource<AppState>;
};

export type Sinks = {
DOM? : Stream<VNode>;
HTTP? : Stream<RequestOptions>;
onion? : Stream<Reducer>;
};

export type AppState = {
count : number;
};

export type Component = (s : Sources) => Sinks;
export type Reducer = (prevState : any) => any;
54 changes: 54 additions & 0 deletions packages/cycle-scripts-one-fits-all/template/test/app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { forall, assert, nat, Options } from 'jsverify';
import { diagramArbitrary } from 'cyclejs-test-helpers';
import * as htmlLooksLike from 'html-looks-like';
const toHtml = require('snabbdom-to-html'); //snabbdom-to-html's typings are broken

import xs from 'xstream';
import { mockDOMSource } from '@cycle/dom';
import { mockTimeSource } from '@cycle/time';
import onionify from 'cycle-onionify';

import { App } from '../src/app';

const testOptions : Options = {
tests: 100,
size: 200
};

describe('app tests', () => {

const expectedHTML = count => `
<div>
<h2>My Awesome Cycle.js app</h2>
<span>Counter: ${count}</span>
<button type="button" class="add">Increase</button>
<button type="button" class="subtract">Decrease</button>
</div>
`;

it('should interact correctly', () => {
const property = forall(diagramArbitrary, diagramArbitrary, (addDiagram, subtractDiagram) => {
const Time = mockTimeSource();

const add$ = Time.diagram(addDiagram);
const subtract$ = Time.diagram(subtractDiagram);

const DOM = mockDOMSource({
'.add': { click: add$ },
'.subtract': { click: subtract$ }
});

const app = onionify(App)({ DOM } as any);
const html$ = app.DOM.map(toHtml);

const expected$ = xs.merge(add$.mapTo(+1), subtract$.mapTo(-1))
.fold((acc, curr) => acc + curr, 0)
.map(expectedHTML);

Time.assertEqual(html$, expected$, htmlLooksLike);
return new Promise((resolve, reject) => Time.run(err => err ? reject(err) : resolve(true)));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Widdershin I will wait for Time.run() to return a Promise before merging this, so the tests will look nicer

});

return assert(property, testOptions);
});
});
2 changes: 1 addition & 1 deletion packages/cycle-scripts-one-fits-all/template/tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"rules": {
"member-access": true,
"no-reference": true,
"typedef": [true, "call-signature", "call-signature", "parameter", "property-declaration", "variable-declaration", "member-variable-declaration"],
"typedef": [true, "call-signature", "call-signature", "parameter", "property-declaration", "member-variable-declaration"],
"typedef-whitespace": [
true,
{
Expand Down