Add inferno in todoapp benchmark
This commit is contained in:
parent
02e7b40c07
commit
d571dd2e56
26 changed files with 8148 additions and 5 deletions
3248
bench/implementations/inferno/dist/bundle.js
vendored
Normal file
3248
bench/implementations/inferno/dist/bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
20
bench/implementations/inferno/index.html
Normal file
20
bench/implementations/inferno/index.html
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en" data-framework="inferno">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Inferno • TodoMVC</title>
|
||||||
|
<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
|
||||||
|
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section id="app" class="todoapp"></section>
|
||||||
|
<footer class="info">
|
||||||
|
<p>Double-click to edit a todo</p>
|
||||||
|
<p>Created by <a href="http://github.com/lukeed/">Luke Edwards</a></p>
|
||||||
|
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="node_modules/todomvc-common/base.js"></script>
|
||||||
|
<script src="dist/bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
bench/implementations/inferno/package.json
Normal file
24
bench/implementations/inferno/package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "webpack-dev-server",
|
||||||
|
"build": "webpack -p",
|
||||||
|
"test": "cd test && npm test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"inferno": "beta32",
|
||||||
|
"inferno-component": "beta32",
|
||||||
|
"todomvc-app-css": "^2.0.0",
|
||||||
|
"todomvc-common": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.5.2",
|
||||||
|
"babel-loader": "^6.2.1",
|
||||||
|
"babel-plugin-inferno": "beta13",
|
||||||
|
"babel-preset-es2015": "^6.5.0",
|
||||||
|
"babel-preset-es2015-loose": "^7.0.0",
|
||||||
|
"babel-preset-stage-0": "^6.5.0",
|
||||||
|
"webpack": "^1.12.14",
|
||||||
|
"webpack-dev-server": "^1.14.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
49
bench/implementations/inferno/src/base.js
Normal file
49
bench/implementations/inferno/src/base.js
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import Inferno from 'inferno';
|
||||||
|
import { states } from './share';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stateless Header component
|
||||||
|
*/
|
||||||
|
export function Head({onEnter}) {
|
||||||
|
return (
|
||||||
|
<header className="header">
|
||||||
|
<h1>todos</h1>
|
||||||
|
<input className="new-todo" autofocus onkeydown={ onEnter }
|
||||||
|
autocomplete="off" placeholder="What needs to be done?"
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const links = [
|
||||||
|
{hash: '#/', name: 'All'},
|
||||||
|
{hash: '#/active', name: 'Active'},
|
||||||
|
{hash: '#/completed', name: 'Completed'}
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stateless Footer component
|
||||||
|
*/
|
||||||
|
export function Foot({left, done, route, onClear}) {
|
||||||
|
return (
|
||||||
|
<footer className="footer">
|
||||||
|
<span className="todo-count">
|
||||||
|
<strong>{ left }</strong> { left > 1 ? 'items' : 'item' } left
|
||||||
|
</span>
|
||||||
|
<ul className="filters">
|
||||||
|
{
|
||||||
|
links.map(({hash, name}) => (
|
||||||
|
<li>
|
||||||
|
<a href={ hash } className={ name.toLowerCase() === route ? 'selected' : '' }>
|
||||||
|
{ name }
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
{ done > 0 ? (
|
||||||
|
<button className="clear-completed" onClick={ onClear }>Clear completed</button>
|
||||||
|
) : null }
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
112
bench/implementations/inferno/src/index.js
Normal file
112
bench/implementations/inferno/src/index.js
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
import Inferno from 'inferno';
|
||||||
|
import Component from 'inferno-component';
|
||||||
|
import { ENTER, filters, read } from './share';
|
||||||
|
import { Head, Foot } from './base';
|
||||||
|
import Model from './model';
|
||||||
|
import Item from './item';
|
||||||
|
|
||||||
|
const { render } = Inferno;
|
||||||
|
const model = new Model();
|
||||||
|
|
||||||
|
class App extends Component {
|
||||||
|
state = {
|
||||||
|
route: read(),
|
||||||
|
todos: model.get()
|
||||||
|
};
|
||||||
|
|
||||||
|
update = arr => this.setState({todos: arr});
|
||||||
|
|
||||||
|
componentWillMount = () => {
|
||||||
|
window.onhashchange = () => this.setState({route: read()});
|
||||||
|
};
|
||||||
|
|
||||||
|
add = e => {
|
||||||
|
if (e.which !== ENTER) return;
|
||||||
|
|
||||||
|
const val = e.target.value.trim();
|
||||||
|
if (!val) return;
|
||||||
|
|
||||||
|
e.target.value = '';
|
||||||
|
this.update(
|
||||||
|
model.add(val)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
edit = (todo, val) => {
|
||||||
|
val = val.trim();
|
||||||
|
if (val.length) {
|
||||||
|
this.update(
|
||||||
|
model.put(todo, {title: val, editing: 0})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.remove(todo);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
focus = todo => this.update(
|
||||||
|
model.put(todo, {editing: 1})
|
||||||
|
);
|
||||||
|
|
||||||
|
blur = todo => this.update(
|
||||||
|
model.put(todo, {editing: 0})
|
||||||
|
);
|
||||||
|
|
||||||
|
remove = todo => this.update(
|
||||||
|
model.del(todo)
|
||||||
|
);
|
||||||
|
|
||||||
|
toggleOne = todo => this.update(
|
||||||
|
model.toggle(todo)
|
||||||
|
);
|
||||||
|
|
||||||
|
toggleAll = ev => this.update(
|
||||||
|
model.toggleAll(ev.target.checked)
|
||||||
|
);
|
||||||
|
|
||||||
|
clearCompleted = () => this.update(
|
||||||
|
model.clearCompleted()
|
||||||
|
);
|
||||||
|
|
||||||
|
render(_, {todos, route}) {
|
||||||
|
const num = todos.length;
|
||||||
|
const shown = todos.filter(filters[route]);
|
||||||
|
const numDone = todos.filter(filters.completed).length;
|
||||||
|
const numAct = num - numDone;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Head onEnter={ this.add } />
|
||||||
|
|
||||||
|
{ num ? (
|
||||||
|
<section className="main">
|
||||||
|
<input className="toggle-all" type="checkbox"
|
||||||
|
onClick={ this.toggleAll } checked={ numAct === 0 }
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ul className="todo-list">
|
||||||
|
{
|
||||||
|
shown.map(t =>
|
||||||
|
<Item data={t}
|
||||||
|
onBlur={ () => this.blur(t) }
|
||||||
|
onFocus={ () => this.focus(t) }
|
||||||
|
doDelete={ () => this.remove(t) }
|
||||||
|
doSave={ val => this.edit(t, val) }
|
||||||
|
doToggle={ () => this.toggleOne(t) }
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
) : null }
|
||||||
|
|
||||||
|
{ (numAct || numDone) ? (
|
||||||
|
<Foot onClear={ this.clearCompleted }
|
||||||
|
left={numAct} done={numDone} route={route}
|
||||||
|
/>
|
||||||
|
) : null }
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(<App />, document.getElementById('app'));
|
||||||
58
bench/implementations/inferno/src/item.js
Normal file
58
bench/implementations/inferno/src/item.js
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import Inferno from 'inferno';
|
||||||
|
import Component from 'inferno-component';
|
||||||
|
import { ESCAPE, ENTER, isEqual } from './share';
|
||||||
|
|
||||||
|
export default class Item extends Component {
|
||||||
|
constructor({data, ...props}) {
|
||||||
|
super(props);
|
||||||
|
this.todo = data;
|
||||||
|
this.state = {text: data.title};
|
||||||
|
this.editor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps = ({data}) => this.setText(data.title);
|
||||||
|
shouldComponentUpdate = ({data}, {text}) => !(isEqual(data, this.todo) && text === this.state.text);
|
||||||
|
componentWillUpdate = ({data}) => (this.todo = data);
|
||||||
|
componentDidUpdate = () => this.editor.focus();
|
||||||
|
|
||||||
|
setText = text => this.setState({text});
|
||||||
|
|
||||||
|
render({doToggle, doDelete, doSave, onBlur, onFocus}, {text}) {
|
||||||
|
const {title, completed, editing} = this.todo;
|
||||||
|
|
||||||
|
const cls = [];
|
||||||
|
editing && cls.push('editing');
|
||||||
|
completed && cls.push('completed');
|
||||||
|
|
||||||
|
const handleKeydown = e => {
|
||||||
|
if (e.which === ESCAPE) return onBlur();
|
||||||
|
if (e.which === ENTER) return doSave(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
// tmp fix
|
||||||
|
const handleBlur = () => doSave(text);
|
||||||
|
const handleInput = e => this.setText(e.target.value);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className={ cls.join(' ') }>
|
||||||
|
<div className="view">
|
||||||
|
<input className="toggle" type="checkbox"
|
||||||
|
checked={ completed } onClick={ doToggle }
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label ondblclick={ onFocus }>{ title }</label>
|
||||||
|
|
||||||
|
<button className="destroy" onClick={ doDelete }></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input className="edit"
|
||||||
|
ref={el => { this.editor = el }}
|
||||||
|
value={ editing && text }
|
||||||
|
onblur={ handleBlur }
|
||||||
|
oninput={ handleInput }
|
||||||
|
onkeydown={ handleKeydown }
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
bench/implementations/inferno/src/model.js
Normal file
36
bench/implementations/inferno/src/model.js
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { assign, isEqual } from './share';
|
||||||
|
|
||||||
|
const STOR = window.localStorage;
|
||||||
|
const STOR_ID = 'todos-inferno';
|
||||||
|
|
||||||
|
export default class Model {
|
||||||
|
get = () => (this.data = JSON.parse(STOR.getItem(STOR_ID) || '[]'))
|
||||||
|
|
||||||
|
set = arr => {
|
||||||
|
this.data = arr || this.data || [];
|
||||||
|
STOR.setItem(STOR_ID, JSON.stringify(this.data));
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
add = str => this.set(
|
||||||
|
this.data.concat({title: str, completed: false})
|
||||||
|
)
|
||||||
|
|
||||||
|
put = (todo, obj) => this.set(
|
||||||
|
this.data.map(t => isEqual(t, todo) ? assign(todo, obj) : t)
|
||||||
|
)
|
||||||
|
|
||||||
|
del = todo => this.set(
|
||||||
|
this.data.filter(t => !isEqual(t, todo))
|
||||||
|
)
|
||||||
|
|
||||||
|
toggle = todo => this.put(todo, {completed: !todo.completed})
|
||||||
|
|
||||||
|
toggleAll = completed => this.set(
|
||||||
|
this.data.map(t => ({...t, completed}))
|
||||||
|
)
|
||||||
|
|
||||||
|
clearCompleted = () => this.set(
|
||||||
|
this.data.filter(t => !t.completed)
|
||||||
|
)
|
||||||
|
}
|
||||||
58
bench/implementations/inferno/src/share.js
Normal file
58
bench/implementations/inferno/src/share.js
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* Shared funcs/values
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const ENTER = 13;
|
||||||
|
export const ESCAPE = 27;
|
||||||
|
|
||||||
|
export const filters = {
|
||||||
|
all: t => true,
|
||||||
|
active: t => !t.completed,
|
||||||
|
completed: t => t.completed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the `location.hash` value
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
export function read() {
|
||||||
|
return location.hash.replace('#/', '') || 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modified `Object.assign` shim
|
||||||
|
* - always writes to new object
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
export function assign() {
|
||||||
|
let src;
|
||||||
|
let tar = {};
|
||||||
|
for (let s = 0; s < arguments.length; s++) {
|
||||||
|
src = Object(arguments[s]);
|
||||||
|
for (const k in src) {
|
||||||
|
tar[k] = src[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are two Objects equal values?
|
||||||
|
* @param {Object} a
|
||||||
|
* @param {Object} b
|
||||||
|
* @return {Boolean}
|
||||||
|
*/
|
||||||
|
export function isEqual(a, b) {
|
||||||
|
// Create arrays of property names
|
||||||
|
const aProps = Object.getOwnPropertyNames(a);
|
||||||
|
const bProps = Object.getOwnPropertyNames(b);
|
||||||
|
|
||||||
|
if (aProps.length !== bProps.length) return false;
|
||||||
|
|
||||||
|
for (let i = 0; i < aProps.length; i++) {
|
||||||
|
const k = aProps[i];
|
||||||
|
if (a[k] !== b[k]) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
2
bench/implementations/inferno/test/.gitignore
vendored
Normal file
2
bench/implementations/inferno/test/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
189
bench/implementations/inferno/test/README.md
Normal file
189
bench/implementations/inferno/test/README.md
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
# TodoMVC Browser Tests
|
||||||
|
|
||||||
|
The TodoMVC project has a great many implementations of exactly the same app using different MV* frameworks. Each app should be functionally identical. The goal of these tests is to provide a fully automated browser-based test that can be used to ensure that the specification is being followed by each and every TodoMVC app.
|
||||||
|
|
||||||
|
|
||||||
|
## Todo
|
||||||
|
|
||||||
|
- [ ] Complete the test implementation (27 out of 28 are now complete). The only test that I am struggling with is to test that the delete button becomes visible on hover.
|
||||||
|
- [ ] Make it work with PhantomJS. In practice, Phantom is only a little bit faster, but it should work. Currently there are a few Phantom specific failures.
|
||||||
|
- [ ] Allow testing of apps that require a server (see: https://github.com/tastejs/todomvc/pull/821/files#r9377070)
|
||||||
|
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
These tests use Selenium 2 (WebDriver), via the JavaScript API (WebdriverJS). In order to run the tests, you will need to install the dependencies. npm must be version 2.0.0 or greater, so upgrade it first with `npm install -g npm` if `npm --version` outputs anything less than 2.0.0. Run the following command from within the `tests` folder:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
If you haven't already run `npm install` in the root directory, execute `npm install` there as well.
|
||||||
|
|
||||||
|
You need to run a local server for the tests. Start the test server using:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ gulp test-server
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the tests for all TodoMVC implementations, run the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to run tests for a single TodoMVC implementation, supply a framework argument as follows:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test -- --framework=angularjs
|
||||||
|
```
|
||||||
|
|
||||||
|
N.B. Remember the extra -- to separate the script arguments from the npm arguments.
|
||||||
|
|
||||||
|
In order to run a specific test, use the mocha 'grep' function. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run test -- --framework=jquery --grep 'should trim entered text'
|
||||||
|
|
||||||
|
TodoMVC - jquery
|
||||||
|
Editing
|
||||||
|
✓ should trim entered text (1115ms)
|
||||||
|
|
||||||
|
|
||||||
|
1 passing (3s)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specifying the browser
|
||||||
|
|
||||||
|
You can also specify the browser that will be used to execute the tests via the `---browser` argument. The tests default to using Chrome. For example, to run against phantomjs, use the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test -- --browser=phantomjs
|
||||||
|
```
|
||||||
|
|
||||||
|
You must install phantomjs first of course!
|
||||||
|
|
||||||
|
Valid browser names can be found within webdriver via the `webdriver.Browser` enumeration.
|
||||||
|
|
||||||
|
|
||||||
|
## Reporting against known issues
|
||||||
|
|
||||||
|
The `knownIssues.js` file details the currently known issues with the TodoMVC implementations. You can run the tests and compare against these issues using the `mocha-known-issues-reporter`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test -- --reporter=mocha-known-issues-reporter
|
||||||
|
```
|
||||||
|
|
||||||
|
When run via grunt the suite supports exactly the same command line arguments.
|
||||||
|
|
||||||
|
An example output with the known issues reporter is shown below:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run test -- --reporter=mocha-known-issues-reporter --framework=jquery
|
||||||
|
...
|
||||||
|
Running "simplemocha:files" (simplemocha) task
|
||||||
|
(1 of 27) pass: TodoMVC - jquery, No Todos, should hide #main and #footer
|
||||||
|
[...]
|
||||||
|
(17 of 27) pass: TodoMVC - jquery, Editing, should remove the item if an empty text string was entered
|
||||||
|
(18 of 27) known issue: TodoMVC - jquery, Editing, should cancel edits on escape -- error: undefined
|
||||||
|
(19 of 27) pass: TodoMVC - jquery, Counter, should display the current number of todo items
|
||||||
|
(20 of 27) pass: TodoMVC - jquery, Clear completed button, should display the number of completed items
|
||||||
|
(21 of 27) pass: TodoMVC - jquery, Clear completed button, should remove completed items when clicked
|
||||||
|
(22 of 27) pass: TodoMVC - jquery, Clear completed button, should be hidden when there are no items that are completed
|
||||||
|
(23 of 27) pass: TodoMVC - jquery, Persistence, should persist its data
|
||||||
|
(24 of 27) known issue: TodoMVC - jquery, Routing, should allow me to display active items -- error: Cannot call method 'click' of undefined
|
||||||
|
(25 of 27) known issue: TodoMVC - jquery, Routing, should allow me to display completed items -- error: Cannot call method 'click' of undefined
|
||||||
|
(26 of 27) known issue: TodoMVC - jquery, Routing, should allow me to display all items -- error: Cannot call method 'click' of undefined
|
||||||
|
(27 of 27) known issue: TodoMVC - jquery, Routing, should highlight the currently applied filter -- error: Cannot call method 'getAttribute' of undefined
|
||||||
|
|
||||||
|
passed: 22/27
|
||||||
|
failed: 5/27
|
||||||
|
new issues: 0
|
||||||
|
resolved issues: 0
|
||||||
|
```
|
||||||
|
|
||||||
|
The reporter indicates the number of passes, failed, new and resolved issues. This makes it ideal for regression testing.
|
||||||
|
|
||||||
|
### Example output
|
||||||
|
|
||||||
|
A test run with the 'spec' reporter looks something like the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run test -- --framework=angularjs
|
||||||
|
|
||||||
|
angularjs
|
||||||
|
TodoMVC
|
||||||
|
No Todos
|
||||||
|
✓ should hide #main and #footer (201ms)
|
||||||
|
New Todo
|
||||||
|
✓ should allow me to add todo items (548ms)
|
||||||
|
✓ should clear text input field when an item is added (306ms)
|
||||||
|
✓ should trim text input (569ms)
|
||||||
|
✓ should show #main and #footer when items added (405ms)
|
||||||
|
Mark all as completed
|
||||||
|
✓ should allow me to mark all items as completed (1040ms)
|
||||||
|
✓ should allow me to clear the completion state of all items (1014ms)
|
||||||
|
✓ complete all checkbox should update state when items are completed (1413ms)
|
||||||
|
Item
|
||||||
|
✓ should allow me to mark items as complete (843ms)
|
||||||
|
✓ should allow me to un-mark items as complete (978ms)
|
||||||
|
✓ should allow me to edit an item (1155ms)
|
||||||
|
✓ should show the remove button on hover
|
||||||
|
Editing
|
||||||
|
✓ should hide other controls when editing (718ms)
|
||||||
|
✓ should save edits on enter (1093ms)
|
||||||
|
✓ should save edits on blur (1256ms)
|
||||||
|
✓ should trim entered text (1163ms)
|
||||||
|
✓ should remove the item if an empty text string was entered (1033ms)
|
||||||
|
✓ should cancel edits on escape (1115ms)
|
||||||
|
Counter
|
||||||
|
✓ should display the current number of todo items (462ms)
|
||||||
|
Clear completed button
|
||||||
|
✓ should display the number of completed items (873ms)
|
||||||
|
✓ should remove completed items when clicked (898ms)
|
||||||
|
✓ should be hidden when there are no items that are completed (893ms)
|
||||||
|
Persistence
|
||||||
|
✓ should persist its data (3832ms)
|
||||||
|
Routing
|
||||||
|
✓ should allow me to display active items (871ms)
|
||||||
|
✓ should allow me to display completed items (960ms)
|
||||||
|
✓ should allow me to display all items (1192ms)
|
||||||
|
✓ should highlight the currently applied filter (1095ms)
|
||||||
|
|
||||||
|
|
||||||
|
27 passing (1m)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Speed mode
|
||||||
|
|
||||||
|
In order to keep each test case fully isolated, the browser is closed then re-opened in between each test. This does mean that the tests can take quite a long time to run. If you don't mind the risk of side-effects you can run the tests in speed mode by adding the `--speedMode` argument.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test -- --speedMode
|
||||||
|
```
|
||||||
|
|
||||||
|
Before each test, all the todo items are checked as completed and the 'clear complete' button pressed. This makes the tests run in around half the time, but with the obvious risk that the tear-down code may fail.
|
||||||
|
|
||||||
|
|
||||||
|
## Lax mode
|
||||||
|
|
||||||
|
There are certain implementations (e.g. GWT and Dojo) where the constraints of the framework mean that it is not possible to match exactly the HTML specification for TodoMVC. In these cases, the tests can be run in a 'lax' mode where the XPath queries used to locate DOM elements are more general. For example, rather than looking for a checkbox `input` element with a class of `toggle`, in lax mode it simply looks for any `input` elements of type `checkbox`. To run the tests in lax mode, simply use the `--laxMode` argument:
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test -- --laxMode
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Test design
|
||||||
|
|
||||||
|
Very briefly, the tests are designed as follows:
|
||||||
|
|
||||||
|
- `page.js` - provides an abstraction layer for the HTML template. All the code required to access elements from the DOM is found within this file. The XPaths used to locate elements are based on the TodoMVC specification, using the required element classes / ids.
|
||||||
|
- `pageLaxMode.js` - extends the above in order to relax the XPath constraints.
|
||||||
|
- `testOperations.js` - provides common assertions and operations.
|
||||||
|
- `test.js` - Erm … the tests! These are written to closely match the TodoMVC spec.
|
||||||
|
- `allTest.js` - A simple file that locates all of the framework examples, and runs the tests for each.
|
||||||
|
|
||||||
|
**NOTE:** All of the WebdriverJS methods return promises and are executed asynchronously. However, you do not have to 'chain' them using `then`, they are instead automagically added to a queue, then executed. This means that if you add non-WebdriverJS operations (asserts, log messages) these will not be executed at the point you might expect. This is why `TestOperations.js` uses an explicit `then` each time it asserts.
|
||||||
414
bench/implementations/inferno/test/index.js
Normal file
414
bench/implementations/inferno/test/index.js
Normal file
|
|
@ -0,0 +1,414 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var webdriver = require('selenium-webdriver');
|
||||||
|
var chrome = require('selenium-webdriver/chrome');
|
||||||
|
var test = require('selenium-webdriver/testing');
|
||||||
|
var Page = require('./page');
|
||||||
|
var PageLaxMode = require('./pageLaxMode');
|
||||||
|
var TestOperations = require('./testOperations');
|
||||||
|
|
||||||
|
var argv = require('optimist').default('laxMode', false).default('browser', 'chrome').argv;
|
||||||
|
|
||||||
|
function todoMVCTest(baseUrl, speedMode, laxMode, browserName) {
|
||||||
|
test.describe('TodoMVC: ', function () {
|
||||||
|
|
||||||
|
var TODO_ITEM_ONE = 'buy some cheese';
|
||||||
|
var TODO_ITEM_TWO = 'feed the cat';
|
||||||
|
var TODO_ITEM_THREE = 'book a doctors appointment';
|
||||||
|
var browser, testOps, page;
|
||||||
|
|
||||||
|
// a number of tests use this set of ToDo items.
|
||||||
|
function createStandardItems(done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
page.enterItem(TODO_ITEM_TWO);
|
||||||
|
return page.enterItem(TODO_ITEM_THREE)
|
||||||
|
.then(function () {
|
||||||
|
if (done instanceof Function) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function launchBrowser(done) {
|
||||||
|
var chromeOptions = new chrome.Options();
|
||||||
|
chromeOptions.addArguments('no-sandbox');
|
||||||
|
|
||||||
|
if (process.env.CHROME_PATH !== undefined) {
|
||||||
|
chromeOptions.setChromeBinaryPath(process.env.CHROME_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
browser = new webdriver.Builder()
|
||||||
|
.withCapabilities({browserName: browserName})
|
||||||
|
.setChromeOptions(chromeOptions)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
browser.get(baseUrl);
|
||||||
|
|
||||||
|
page = laxMode ? new PageLaxMode(browser) : new Page(browser);
|
||||||
|
testOps = new TestOperations(page);
|
||||||
|
|
||||||
|
return page.ensureAppIsVisibleAndLoaded()
|
||||||
|
.then(function () {
|
||||||
|
if (done instanceof Function) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function printCapturedLogs() {
|
||||||
|
var logs = browser.manage().logs();
|
||||||
|
|
||||||
|
return logs.get('browser')
|
||||||
|
.then(function (entries) {
|
||||||
|
if (entries && entries.length) {
|
||||||
|
console.log(entries);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeBrowser(done) {
|
||||||
|
return browser
|
||||||
|
.quit()
|
||||||
|
.then(function () {
|
||||||
|
if (done instanceof Function) { done(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speedMode) {
|
||||||
|
test.before(launchBrowser);
|
||||||
|
test.after(closeBrowser);
|
||||||
|
test.afterEach(function (done) {
|
||||||
|
return browser.executeScript('window.localStorage && localStorage.clear(); location.reload(true);')
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
test.beforeEach(launchBrowser);
|
||||||
|
test.afterEach(function (done) {
|
||||||
|
printCapturedLogs()
|
||||||
|
.then(function () {
|
||||||
|
return closeBrowser(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test.describe('When page is initially opened', function () {
|
||||||
|
|
||||||
|
test.it('should focus on the todo input field', function (done) {
|
||||||
|
testOps.assertNewInputFocused()
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('No Todos', function () {
|
||||||
|
|
||||||
|
test.it('should hide #main and #footer', function (done) {
|
||||||
|
testOps.assertItemCount(0);
|
||||||
|
testOps.assertMainSectionVisibility(false);
|
||||||
|
testOps.assertFooterVisibility(false)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('New Todo', function () {
|
||||||
|
|
||||||
|
test.it('should allow me to add todo items', function (done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE]);
|
||||||
|
page.enterItem(TODO_ITEM_TWO);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should clear text input field when an item is added', function (done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
testOps.assertNewItemInputFieldText('')
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should append new items to the bottom of the list', function (done) {
|
||||||
|
createStandardItems();
|
||||||
|
testOps.assertItemCount(3);
|
||||||
|
testOps.assertItemText(0, TODO_ITEM_ONE);
|
||||||
|
testOps.assertItemText(1, TODO_ITEM_TWO);
|
||||||
|
testOps.assertItemText(2, TODO_ITEM_THREE)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should trim text input', function (done) {
|
||||||
|
page.enterItem(' ' + TODO_ITEM_ONE + ' ');
|
||||||
|
testOps.assertItemText(0, TODO_ITEM_ONE)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should show #main and #footer when items added', function (done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
testOps.assertMainSectionVisibility(true);
|
||||||
|
testOps.assertFooterVisibility(true)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Mark all as completed', function () {
|
||||||
|
|
||||||
|
test.beforeEach(createStandardItems);
|
||||||
|
|
||||||
|
test.it('should allow me to mark all items as completed', function (done) {
|
||||||
|
page.clickMarkAllCompletedCheckBox();
|
||||||
|
testOps.assertItemCompletedStates([true, true, true])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should correctly update the complete all checked state', function (done) {
|
||||||
|
// manually check all items
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
page.toggleItemAtIndex(2);
|
||||||
|
|
||||||
|
// ensure checkall is in the correct state
|
||||||
|
testOps.assertCompleteAllCheckedStatus(true)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should allow me to clear the completion state of all items', function (done) {
|
||||||
|
page.clickMarkAllCompletedCheckBox();
|
||||||
|
page.clickMarkAllCompletedCheckBox();
|
||||||
|
|
||||||
|
testOps.assertItemCompletedStates([false, false, false])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('complete all checkbox should update state when items are completed / cleared', function (done) {
|
||||||
|
page.clickMarkAllCompletedCheckBox();
|
||||||
|
testOps.assertCompleteAllCheckedStatus(true);
|
||||||
|
|
||||||
|
// all items are complete, now mark one as not-complete
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
testOps.assertCompleteAllCheckedStatus(false);
|
||||||
|
|
||||||
|
// now mark as complete, so that once again all items are completed
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
testOps.assertCompleteAllCheckedStatus(true)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Item', function () {
|
||||||
|
|
||||||
|
test.it('should allow me to mark items as complete', function (done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
page.enterItem(TODO_ITEM_TWO);
|
||||||
|
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
testOps.assertItemCompletedStates([true, false]);
|
||||||
|
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
testOps.assertItemCompletedStates([true, true])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should allow me to un-mark items as complete', function (done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
page.enterItem(TODO_ITEM_TWO);
|
||||||
|
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
testOps.assertItemCompletedStates([true, false]);
|
||||||
|
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
testOps.assertItemCompletedStates([false, false])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Editing', function () {
|
||||||
|
|
||||||
|
test.beforeEach(function (done) {
|
||||||
|
createStandardItems();
|
||||||
|
page.doubleClickItemAtIndex(1)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should focus the input', function (done) {
|
||||||
|
testOps.assertItemInputFocused();
|
||||||
|
testOps.assertNewInputBlurred() // Unnecessary? The HTML spec dictates that only one element can be focused.
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should hide other controls when editing', function (done) {
|
||||||
|
testOps.assertItemToggleIsHidden(1);
|
||||||
|
testOps.assertItemLabelIsHidden(1)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should save edits on enter', function (done) {
|
||||||
|
page.editItemAtIndex(1, 'buy some sausages' + webdriver.Key.ENTER);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should save edits on blur', function (done) {
|
||||||
|
page.editItemAtIndex(1, 'buy some sausages');
|
||||||
|
// click a toggle button so that the blur() event is fired
|
||||||
|
page.toggleItemAtIndex(0);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should trim entered text', function (done) {
|
||||||
|
page.editItemAtIndex(1, ' buy some sausages ' + webdriver.Key.ENTER);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, 'buy some sausages', TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should remove the item if an empty text string was entered', function (done) {
|
||||||
|
page.editItemAtIndex(1, webdriver.Key.ENTER);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should cancel edits on escape', function (done) {
|
||||||
|
page.editItemAtIndex(1, 'foo' + webdriver.Key.ESCAPE);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Counter', function () {
|
||||||
|
|
||||||
|
test.it('should display the current number of todo items', function (done) {
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
testOps.assertItemCountText('1 item left');
|
||||||
|
page.enterItem(TODO_ITEM_TWO);
|
||||||
|
testOps.assertItemCountText('2 items left')
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Clear completed button', function () {
|
||||||
|
|
||||||
|
test.beforeEach(createStandardItems);
|
||||||
|
|
||||||
|
test.it('should display the correct text', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
testOps.assertClearCompleteButtonText('Clear completed')
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should remove completed items when clicked', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
page.clickClearCompleteButton();
|
||||||
|
testOps.assertItemCount(2);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should be hidden when there are no items that are completed', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
testOps.assertClearCompleteButtonVisibility(true);
|
||||||
|
page.clickClearCompleteButton();
|
||||||
|
testOps.assertClearCompleteButtonVisibility(false)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Persistence', function () {
|
||||||
|
|
||||||
|
test.it('should persist its data', function (done) {
|
||||||
|
function stateTest() {
|
||||||
|
testOps.assertItemCount(2);
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO]);
|
||||||
|
return testOps.assertItemCompletedStates([false, true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up state
|
||||||
|
page.enterItem(TODO_ITEM_ONE);
|
||||||
|
page.enterItem(TODO_ITEM_TWO);
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
stateTest();
|
||||||
|
|
||||||
|
// navigate away and back again
|
||||||
|
browser.get('about:blank');
|
||||||
|
browser.get(baseUrl);
|
||||||
|
|
||||||
|
// repeat the state test
|
||||||
|
stateTest()
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Routing', function () {
|
||||||
|
|
||||||
|
test.beforeEach(createStandardItems);
|
||||||
|
|
||||||
|
test.it('should allow me to display active items', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
page.filterByActiveItems();
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_THREE])
|
||||||
|
.then(function () { return done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should respect the back button', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
page.filterByActiveItems();
|
||||||
|
page.filterByCompletedItems();
|
||||||
|
testOps.assertItems([page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_TWO]); // should show completed items
|
||||||
|
page.back(); // then active items
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_THREE]);
|
||||||
|
page.back(); // then all items
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should allow me to display completed items', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
page.filterByCompletedItems();
|
||||||
|
testOps.assertItems([page.ITEM_HIDDEN_OR_REMOVED, TODO_ITEM_TWO]);
|
||||||
|
page.filterByAllItems() // TODO: why
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should allow me to display all items', function (done) {
|
||||||
|
page.toggleItemAtIndex(1);
|
||||||
|
|
||||||
|
// apply the other filters first, before returning to the 'all' state
|
||||||
|
page.filterByActiveItems();
|
||||||
|
page.filterByCompletedItems();
|
||||||
|
page.filterByAllItems();
|
||||||
|
testOps.assertItems([TODO_ITEM_ONE, TODO_ITEM_TWO, TODO_ITEM_THREE])
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.it('should highlight the currently applied filter', function (done) {
|
||||||
|
// initially 'all' should be selected
|
||||||
|
testOps.assertFilterAtIndexIsSelected(0);
|
||||||
|
page.filterByActiveItems();
|
||||||
|
testOps.assertFilterAtIndexIsSelected(1);
|
||||||
|
page.filterByCompletedItems();
|
||||||
|
testOps.assertFilterAtIndexIsSelected(2)
|
||||||
|
.then(function () { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init test
|
||||||
|
*/
|
||||||
|
todoMVCTest(
|
||||||
|
'http://localhost:8000/index.html',
|
||||||
|
argv.speedMode,
|
||||||
|
argv.laxMode,
|
||||||
|
argv.browser
|
||||||
|
);
|
||||||
131
bench/implementations/inferno/test/knownIssues.js
Normal file
131
bench/implementations/inferno/test/knownIssues.js
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
module.exports = [
|
||||||
|
|
||||||
|
// durandal routing is very very slow.
|
||||||
|
// see: https://github.com/tastejs/todomvc/issues/831
|
||||||
|
'TodoMVC - durandal, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - durandal, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - durandal, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - durandal, Routing, should highlight the currently applied filter',
|
||||||
|
|
||||||
|
// https://github.com/tastejs/todomvc/issues/828
|
||||||
|
// routing should default to all
|
||||||
|
'TodoMVC - sammyjs, Routing, should highlight the currently applied filter',
|
||||||
|
|
||||||
|
// https://github.com/tastejs/todomvc/issues/824
|
||||||
|
// this implementation has numerous edit experience issues
|
||||||
|
'TodoMVC - angularjs_require, Mark all as completed, should allow me to mark all items as completed',
|
||||||
|
'TodoMVC - angularjs_require, Mark all as completed, should allow me to clear the completion state of all items',
|
||||||
|
// jscs:disable
|
||||||
|
'TodoMVC - angularjs_require, Mark all as completed, complete all checkbox should update state when items are completed / cleared',
|
||||||
|
|
||||||
|
// jscs:enable
|
||||||
|
// https://github.com/tastejs/todomvc/issues/815
|
||||||
|
// does not hide other controls while editing
|
||||||
|
'TodoMVC - dojo, Editing, should hide other controls when editing',
|
||||||
|
|
||||||
|
// https://github.com/tastejs/todomvc/issues/816
|
||||||
|
// atma does not hide the main section, instead it hides the toggle-all checkbox
|
||||||
|
'TodoMVC - atmajs, No Todos, should hide #main and #footer',
|
||||||
|
|
||||||
|
// https://github.com/tastejs/todomvc/issues/819
|
||||||
|
// the edit experience with soma is quite broken. You can
|
||||||
|
// get multiple elements into an edit state
|
||||||
|
'TodoMVC - somajs_require, Editing, should remove the item if an empty text string was entered',
|
||||||
|
'TodoMVC - somajs_require, Editing, should cancel edits on escape',
|
||||||
|
|
||||||
|
// the following are covered by the following issue:
|
||||||
|
// https://github.com/tastejs/todomvc/issues/789
|
||||||
|
'TodoMVC - closure, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - ariatemplates, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - dermis, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - duel, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - extjs_deftjs, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - olives, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - rappidjs, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - serenadejs, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - typescript-angular, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - flight, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - backbone_require, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - dijon, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - knockoutjs_require, Editing, should cancel edits on escape',
|
||||||
|
|
||||||
|
// all the following are covered by this issue:
|
||||||
|
// https://github.com/tastejs/todomvc/issues/856
|
||||||
|
'TodoMVC - knockoutjs, Routing, should respect the back button',
|
||||||
|
'TodoMVC - spine, Routing, should respect the back button',
|
||||||
|
'TodoMVC - serenadejs, Routing, should respect the back button',
|
||||||
|
'TodoMVC - flight, Routing, should respect the back button',
|
||||||
|
'TodoMVC - lavaca_require, Routing, should respect the back button',
|
||||||
|
'TodoMVC - somajs_require, Routing, should respect the back button',
|
||||||
|
|
||||||
|
// the following implementations do not support routing
|
||||||
|
'TodoMVC - extjs_deftjs, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - extjs_deftjs, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - extjs_deftjs, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - extjs_deftjs, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - extjs_deftjs, Routing, should respect the back button',
|
||||||
|
'TodoMVC - olives, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - olives, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - olives, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - olives, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - olives, Routing, should respect the back button',
|
||||||
|
'TodoMVC - dijon, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - dijon, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - dijon, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - dijon, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - dijon, Routing, should respect the back button',
|
||||||
|
'TodoMVC - duel, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - duel, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - duel, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - duel, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - duel, Routing, should respect the back button',
|
||||||
|
'TodoMVC - knockoutjs_require, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - knockoutjs_require, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - knockoutjs_require, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - knockoutjs_require, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - knockoutjs_require, Routing, should respect the back button',
|
||||||
|
'TodoMVC - angular-dart, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - angular-dart, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - angular-dart, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - angular-dart, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - angular-dart, Routing, should respect the back button',
|
||||||
|
'TodoMVC - typescript-backbone, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - typescript-backbone, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - typescript-backbone, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - typescript-backbone, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - typescript-backbone, Routing, should respect the back button',
|
||||||
|
|
||||||
|
// EXTJS is not spec compliant (by a long way!)
|
||||||
|
'TodoMVC - extjs, New Todo, should show #main and #footer when items added',
|
||||||
|
'TodoMVC - extjs, Mark all as completed, should allow me to mark all items as completed',
|
||||||
|
'TodoMVC - extjs, Mark all as completed, complete all checkbox should update state when items are completed / cleared',
|
||||||
|
'TodoMVC - extjs, Item, should allow me to mark items as complete',
|
||||||
|
'TodoMVC - extjs, Item, should allow me to un-mark items as complete',
|
||||||
|
'TodoMVC - extjs, Editing, should save edits on blur',
|
||||||
|
'TodoMVC - extjs, Editing, should cancel edits on escape',
|
||||||
|
'TodoMVC - extjs, Counter, should display the current number of todo items',
|
||||||
|
'TodoMVC - extjs, Clear completed button, should display the number of completed items',
|
||||||
|
'TodoMVC - extjs, Clear completed button, should remove completed items when clicked',
|
||||||
|
'TodoMVC - extjs, Clear completed button, should be hidden when there are no items that are completed',
|
||||||
|
'TodoMVC - extjs, Persistence, should persist its data',
|
||||||
|
'TodoMVC - extjs, Routing, should allow me to display active items',
|
||||||
|
'TodoMVC - extjs, Routing, should allow me to display completed items',
|
||||||
|
'TodoMVC - extjs, Routing, should allow me to display all items',
|
||||||
|
'TodoMVC - extjs, Routing, should highlight the currently applied filter',
|
||||||
|
'TodoMVC - extjs, Routing, should respect the back button',
|
||||||
|
|
||||||
|
// ----------------- Test framework issues -----------
|
||||||
|
|
||||||
|
// for some reason the persistence test fails for knockout, even though persistence is working
|
||||||
|
// just fine. Perhaps there is something asynchronous going on that is causing the assert
|
||||||
|
// to be executed early?
|
||||||
|
'TodoMVC - knockoutjs, Persistence, should persist its data',
|
||||||
|
|
||||||
|
// chaplin edit tests fail with the following:
|
||||||
|
// StaleElementReferenceError: stale element reference: element is not attached to the page document
|
||||||
|
'TodoMVC - chaplin-brunch, Editing, should save edits on enter',
|
||||||
|
'TodoMVC - chaplin-brunch, Editing, should save edits on blur',
|
||||||
|
'TodoMVC - chaplin-brunch, Editing, should trim entered text',
|
||||||
|
'TodoMVC - chaplin-brunch, Editing, should remove the item if an empty text string was entered',
|
||||||
|
'TodoMVC - chaplin-brunch, Editing, should cancel edits on escape'
|
||||||
|
];
|
||||||
5
bench/implementations/inferno/test/learn.json
Normal file
5
bench/implementations/inferno/test/learn.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"templates": {
|
||||||
|
"todomvc": "<header> <h3><%= name %></h3> <span class=\"source-links\"> <% if (typeof examples !== 'undefined') { %> <% examples.forEach(function (example) { %> <h5><%= example.name %></h5> <% if (!location.href.match(example.url + '/')) { %> <a class=\"demo-link\" data-type=\"<%= example.type === 'backend' ? 'external' : 'local' %>\" href=\"<%= example.url %>\">Demo</a>, <% } if (example.type === 'backend') { %><a href=\"<%= example.source_url %>\"><% } else { %><a href=\"https://github.com/tastejs/todomvc/tree/gh-pages/<%= example.source_url ? example.source_url : example.url %>\"><% } %>Source</a> <% }); %> <% } %> </span> </header> <hr> <blockquote class=\"quote speech-bubble\"> <p><%= description %></p> <footer> <a href=\"http://<%= homepage %>\"><%= name %></a> </footer> </blockquote> <% if (typeof link_groups !== 'undefined') { %> <hr> <% link_groups.forEach(function (link_group) { %> <h4><%= link_group.heading %></h4> <ul> <% link_group.links.forEach(function (link) { %> <li> <a href=\"<%= link.url %>\"><%= link.name %></a> </li> <% }); %> </ul> <% }); %> <% } %> <footer> <hr> <em>If you have other helpful links to share, or find any of the links above no longer work, please <a href=\"https://github.com/tastejs/todomvc/issues\">let us know</a>.</em> </footer>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"humble": {
|
||||||
|
"nodes": 30,
|
||||||
|
"listeners": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
99
bench/implementations/inferno/test/memory.js
Normal file
99
bench/implementations/inferno/test/memory.js
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var drool = require('drool');
|
||||||
|
var exceptions = require('./memory-exceptions.json');
|
||||||
|
var argv = require('optimist').default('laxMode', false).default('browser', 'chrome').argv;
|
||||||
|
var driverConfig = {
|
||||||
|
chromeOptions: 'no-sandbox'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof process.env.CHROME_PATH !== 'undefined') {
|
||||||
|
driverConfig.chromeBinaryPath = process.env.CHROME_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
var driver = drool.start(driverConfig);
|
||||||
|
|
||||||
|
function idApp() {
|
||||||
|
return driver.findElement(drool.webdriver.By.css('#todoapp'))
|
||||||
|
.then(function () { return true; })
|
||||||
|
.thenCatch(function () { return false; });
|
||||||
|
}
|
||||||
|
|
||||||
|
function newTodoSelector() {
|
||||||
|
return idApp().then(function (isId) {
|
||||||
|
if (isId) {
|
||||||
|
return '#new-todo';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '.new-todo';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listSelector() {
|
||||||
|
return idApp().then(function (isId) {
|
||||||
|
if (isId) {
|
||||||
|
return '#todo-list li';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '.todo-list li';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init
|
||||||
|
*/
|
||||||
|
drool.flow({
|
||||||
|
repeatCount: 5,
|
||||||
|
setup: function () {
|
||||||
|
driver.get('http://localhost:8000/index.html');
|
||||||
|
},
|
||||||
|
action: function (name) {
|
||||||
|
driver.wait(function () {
|
||||||
|
driver.sleep(500);
|
||||||
|
return driver.findElement(drool.webdriver.By.css(newTodoSelector(name)))
|
||||||
|
.sendKeys('find magical goats', drool.webdriver.Key.ENTER)
|
||||||
|
.thenCatch(function () {
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return driver.findElement(drool.webdriver.By.css(listSelector(name))).isDisplayed()
|
||||||
|
.then(function () {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
driver.wait(function () {
|
||||||
|
return driver.findElement(drool.webdriver.By.css(listSelector(name))).click()
|
||||||
|
.thenCatch(function () {
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
driver.findElement(drool.webdriver.By.css('.destroy')).click();
|
||||||
|
}.bind(null, 'inferno'),
|
||||||
|
assert: function (after, initial) {
|
||||||
|
var nodeIncrease = (after.nodes - initial.nodes);
|
||||||
|
var listenerIncrease = (after.jsEventListeners - initial.jsEventListeners);
|
||||||
|
var memoryExceptions = exceptions['inferno'] || {};
|
||||||
|
|
||||||
|
console.log(this + ', ' + nodeIncrease + ', ' +
|
||||||
|
(after.jsHeapSizeUsed - initial.jsHeapSizeUsed) + ', ' + listenerIncrease);
|
||||||
|
|
||||||
|
//https://code.google.com/p/chromium/issues/detail?id=516153
|
||||||
|
if (nodeIncrease > memoryExceptions.nodes || 0) {
|
||||||
|
throw new Error('Node Count leak detected!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listenerIncrease > memoryExceptions.listeners || 0) {
|
||||||
|
throw new Error('Event Listener leak detected!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind('inferno')
|
||||||
|
}, driver);
|
||||||
|
|
||||||
|
driver.quit();
|
||||||
|
|
||||||
15
bench/implementations/inferno/test/package.json
Normal file
15
bench/implementations/inferno/test/package.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"chromedriver": "^2.18.0",
|
||||||
|
"drool": "0.4.0",
|
||||||
|
"express": "^4.10",
|
||||||
|
"mocha": "*",
|
||||||
|
"mocha-known-issues-reporter": "git+https://github.com/ColinEberhardt/mocha-known-issues-reporter.git#v0.0.0",
|
||||||
|
"optimist": "^0.6.1",
|
||||||
|
"selenium-webdriver": "~2.53.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "node server & mocha index.js --no-timeouts --reporter spec"
|
||||||
|
}
|
||||||
|
}
|
||||||
269
bench/implementations/inferno/test/page.js
Normal file
269
bench/implementations/inferno/test/page.js
Normal file
|
|
@ -0,0 +1,269 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var webdriver = require('selenium-webdriver');
|
||||||
|
var until = require('selenium-webdriver/lib/until');
|
||||||
|
|
||||||
|
var idSelectors = true;
|
||||||
|
var classOrId = idSelectors ? '#' : '.';
|
||||||
|
|
||||||
|
var DEFAULT_TIMEOUT = 3000;
|
||||||
|
var REMOVED_TIMEOUT = 100;
|
||||||
|
|
||||||
|
var REMOVE_TEXT_KEY_SEQ = Array(51).join(webdriver.Key.BACK_SPACE + webdriver.Key.DELETE);
|
||||||
|
|
||||||
|
// Unique symbols
|
||||||
|
var ELEMENT_MISSING = Object.freeze({});
|
||||||
|
var ITEM_HIDDEN_OR_REMOVED = Object.freeze({});
|
||||||
|
|
||||||
|
module.exports = function Page(browser) {
|
||||||
|
// CSS ELEMENT SELECTORS
|
||||||
|
|
||||||
|
this.getMainSectionCss = function () { return classOrId + 'main'; };
|
||||||
|
|
||||||
|
this.getFooterSectionCss = function () { return 'footer' + classOrId + 'footer'; };
|
||||||
|
|
||||||
|
this.getClearCompletedButtonCss = function () { return 'button' + classOrId + 'clear-completed'; };
|
||||||
|
|
||||||
|
this.getNewInputCss = function () { return 'input' + classOrId + 'new-todo'; };
|
||||||
|
|
||||||
|
this.getToggleAllCss = function () { return 'input' + classOrId + 'toggle-all'; };
|
||||||
|
|
||||||
|
this.getItemCountCss = function () { return 'span' + classOrId + 'todo-count'; };
|
||||||
|
|
||||||
|
this.getFilterCss = function (index) {
|
||||||
|
return classOrId + 'filters li:nth-of-type(' + (index + 1) + ') a, ' +
|
||||||
|
classOrId + 'filters a:nth-of-type(' + (index + 1) + ')';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getSelectedFilterCss = function (index) { return this.getFilterCss(index) + '.selected'; };
|
||||||
|
|
||||||
|
this.getFilterAllCss = function () { return this.getFilterCss(0); };
|
||||||
|
|
||||||
|
this.getFilterActiveCss = function () { return this.getFilterCss(1); };
|
||||||
|
|
||||||
|
this.getFilterCompletedCss = function () { return this.getFilterCss(2); };
|
||||||
|
|
||||||
|
this.getListCss = function (suffixCss) { return 'ul' + classOrId + 'todo-list' + (suffixCss || ''); };
|
||||||
|
|
||||||
|
this.getListItemCss = function (index, suffixCss, excludeParentSelector) {
|
||||||
|
suffixCss = (index === undefined ? '' : ':nth-of-type(' + (index + 1) + ')') + (suffixCss || '');
|
||||||
|
return excludeParentSelector ? 'li' + suffixCss : this.getListCss(' li' + suffixCss);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getListItemToggleCss = function (index) { return this.getListItemCss(index, ' input.toggle'); };
|
||||||
|
|
||||||
|
this.getListItemLabelCss = function (index) { return this.getListItemCss(index, ' label'); };
|
||||||
|
|
||||||
|
this.getLastListItemLabelCss = function (index) { return this.getListItemCss(index, ':last-of-type label'); };
|
||||||
|
|
||||||
|
this.getListItemInputCss = function (index) { return this.getListItemCss(index, ' input.edit'); };
|
||||||
|
|
||||||
|
this.getEditingListItemInputCss = function () { return this.getListItemCss(undefined, '.editing input.edit'); };
|
||||||
|
|
||||||
|
// This CSS selector returns the _last_ element of a list that exactly matches the provided list of completed states
|
||||||
|
// It is used as a boolean test of the item states
|
||||||
|
this.getListItemsWithCompletedStatesCss = function (completedStates) {
|
||||||
|
var suffixCss = ' ' + completedStates.map(function (completed, i) {
|
||||||
|
return this.getListItemCss(i, completed ? '.completed' : ':not(.completed)', true);
|
||||||
|
}, this).join(' + ');
|
||||||
|
return this.getListCss(suffixCss);
|
||||||
|
};
|
||||||
|
|
||||||
|
// PUBLIC SYMBOLS
|
||||||
|
|
||||||
|
this.ITEM_HIDDEN_OR_REMOVED = ITEM_HIDDEN_OR_REMOVED;
|
||||||
|
|
||||||
|
// NAVIGATION
|
||||||
|
|
||||||
|
this.back = function () {
|
||||||
|
return browser.navigate().back();
|
||||||
|
};
|
||||||
|
|
||||||
|
// ELEMENT RETREIVAL
|
||||||
|
// wait* methods guarantees to return an element, or throw an exception
|
||||||
|
// get* methods may return nothing at all, or in the case of element lists, an older version of the list
|
||||||
|
|
||||||
|
this.getElements = function (css) {
|
||||||
|
return browser.findElements(webdriver.By.css(css));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForElement = function (css, failMsg, timeout) {
|
||||||
|
return browser.wait(until.elementLocated(webdriver.By.css(css)), timeout || DEFAULT_TIMEOUT, failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForFocusedElement = function (css, failMsg) {
|
||||||
|
return this.waitForElement(css + ':focus', failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForBlurredElement = function (css, failMsg) {
|
||||||
|
return this.waitForElement(css + ':not(:focus)', failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForListItemCount = function (count) {
|
||||||
|
var self = this;
|
||||||
|
return browser.wait(function () {
|
||||||
|
return self.waitForElement(self.getListCss())
|
||||||
|
.then(function (listElement) {
|
||||||
|
return listElement.findElements(webdriver.By.css(self.getListItemCss(undefined, undefined, true)));
|
||||||
|
})
|
||||||
|
.then(function (listItems) {
|
||||||
|
return listItems.length === count;
|
||||||
|
});
|
||||||
|
}, DEFAULT_TIMEOUT, 'Expected item list to contain ' + count + ' item' + (count === 1 ? '' : 's'));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForClearCompleteButton = function () {
|
||||||
|
return this.waitForElement(this.getClearCompletedButtonCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForToggleForItem = function (index) {
|
||||||
|
return this.waitForElement(this.getListItemToggleCss(index));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForItemLabel = function (index) {
|
||||||
|
return this.waitForElement(this.getListItemLabelCss(index));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForNewItemInputField = function () {
|
||||||
|
return this.waitForElement(this.getNewInputCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForMarkAllCompletedCheckBox = function () {
|
||||||
|
return this.waitForElement(this.getToggleAllCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getListItems = function () {
|
||||||
|
return this.getElements(this.getListItemCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForVisibility = function (shouldBeVisible, css, failMsg) {
|
||||||
|
if (shouldBeVisible) {
|
||||||
|
return this.waitForElement(css, failMsg)
|
||||||
|
.then(function (element) {
|
||||||
|
return browser.wait(until.elementIsVisible(element), DEFAULT_TIMEOUT, failMsg);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return this.waitForElement(css, undefined, REMOVED_TIMEOUT)
|
||||||
|
.catch(function () { return ELEMENT_MISSING; })
|
||||||
|
.then(function (elementOrError) {
|
||||||
|
return elementOrError === ELEMENT_MISSING ?
|
||||||
|
ELEMENT_MISSING : // Returning a value will resolve the promise
|
||||||
|
browser.wait(until.elementIsNotVisible(elementOrError), DEFAULT_TIMEOUT, failMsg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForMainSectionRemovedOrEmpty = function () {
|
||||||
|
return this.waitForElement(this.getMainSectionCss(), undefined, REMOVED_TIMEOUT)
|
||||||
|
.catch(function () { return ELEMENT_MISSING; })
|
||||||
|
.then(function (elementOrError) {
|
||||||
|
return elementOrError === ELEMENT_MISSING ? ELEMENT_MISSING : this.waitForListItemCount(0);
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForCheckedStatus = function (shouldBeChecked, failMsg, element) {
|
||||||
|
var condition = shouldBeChecked ? 'elementIsSelected' : 'elementIsNotSelected';
|
||||||
|
return browser.wait(until[condition](element), DEFAULT_TIMEOUT, failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.waitForTextContent = function (text, failMsg, element) {
|
||||||
|
return browser.wait(until.elementTextIs(element, text), DEFAULT_TIMEOUT, failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
// PAGE ACTIONS
|
||||||
|
|
||||||
|
this.ensureAppIsVisibleAndLoaded = function () {
|
||||||
|
return this.waitForVisibility(false, this.getFooterSectionCss(), 'Footer is not hidden')
|
||||||
|
.then(this.waitForElement.bind(
|
||||||
|
this, '.new-todo, #new-todo', 'Could not find new todo input field', undefined))
|
||||||
|
.then(function (newTodoElement) {
|
||||||
|
return newTodoElement.getAttribute('id');
|
||||||
|
})
|
||||||
|
.then(function (newTodoElementId) {
|
||||||
|
if (newTodoElementId === 'new-todo') { return; }
|
||||||
|
idSelectors = false;
|
||||||
|
classOrId = idSelectors ? '#' : '.';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.clickMarkAllCompletedCheckBox = function () {
|
||||||
|
return this.waitForMarkAllCompletedCheckBox().click();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.clickClearCompleteButton = function () {
|
||||||
|
return this.waitForVisibility(true, this.getClearCompletedButtonCss(),
|
||||||
|
'Expected clear completed items button to be visible')
|
||||||
|
.then(function (clearCompleteButton) {
|
||||||
|
clearCompleteButton.click();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.enterItem = function (itemText) {
|
||||||
|
var self = this;
|
||||||
|
var nItems;
|
||||||
|
return self.getListItems()
|
||||||
|
.then(function (items) {
|
||||||
|
nItems = items.length;
|
||||||
|
})
|
||||||
|
.then(this.waitForNewItemInputField.bind(this))
|
||||||
|
.then(function (newItemInput) {
|
||||||
|
return newItemInput.sendKeys(itemText).then(function () { return newItemInput; });
|
||||||
|
})
|
||||||
|
.then(function (newItemInput) {
|
||||||
|
return browser.wait(function () {
|
||||||
|
// Hit Enter repeatedly until the text goes away
|
||||||
|
return newItemInput.sendKeys(webdriver.Key.ENTER)
|
||||||
|
.then(newItemInput.getAttribute.bind(newItemInput, 'value'))
|
||||||
|
.then(function (newItemInputValue) {
|
||||||
|
return newItemInputValue.length === 0;
|
||||||
|
});
|
||||||
|
}, DEFAULT_TIMEOUT);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return self.waitForElement(self.getLastListItemLabelCss(nItems));
|
||||||
|
})
|
||||||
|
.then(this.waitForTextContent.bind(this, itemText.trim(),
|
||||||
|
'Expected new item label to read ' + itemText.trim()));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.toggleItemAtIndex = function (index) {
|
||||||
|
return this.waitForToggleForItem(index).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.editItemAtIndex = function (index, itemText) {
|
||||||
|
return this.waitForElement(this.getListItemInputCss(index))
|
||||||
|
.then(function (itemEditField) {
|
||||||
|
return itemEditField.sendKeys(REMOVE_TEXT_KEY_SEQ, itemText);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.doubleClickItemAtIndex = function (index) {
|
||||||
|
return this.waitForItemLabel(index).then(function (itemLabel) {
|
||||||
|
// double click is not 'natively' supported, so we need to send the event direct to the element, see:
|
||||||
|
// jscs:disable
|
||||||
|
// http://stackoverflow.com/questions/3982442/selenium-2-webdriver-how-to-double-click-a-table-row-which-opens-a-new-window
|
||||||
|
// jscs:enable
|
||||||
|
return browser.executeScript('var evt = document.createEvent("MouseEvents");' +
|
||||||
|
'evt.initMouseEvent("dblclick",true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);' +
|
||||||
|
'arguments[0].dispatchEvent(evt);', itemLabel);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.filterBy = function (filterCss) {
|
||||||
|
return this.waitForElement(filterCss)
|
||||||
|
.click()
|
||||||
|
.then(this.waitForElement.bind(this, filterCss + '.selected', undefined, undefined));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.filterByActiveItems = function () {
|
||||||
|
return this.filterBy(this.getFilterActiveCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.filterByCompletedItems = function () {
|
||||||
|
return this.filterBy(this.getFilterCompletedCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.filterByAllItems = function () {
|
||||||
|
return this.filterBy(this.getFilterAllCss());
|
||||||
|
};
|
||||||
|
};
|
||||||
73
bench/implementations/inferno/test/pageLaxMode.js
Normal file
73
bench/implementations/inferno/test/pageLaxMode.js
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Page = require('./page');
|
||||||
|
|
||||||
|
module.exports = function PageLaxMode() {
|
||||||
|
|
||||||
|
Page.apply(this, arguments);
|
||||||
|
|
||||||
|
this.getMainSectionCss = function () {
|
||||||
|
return 'section section';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getFooterSectionCss = function () {
|
||||||
|
return 'section footer';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getListCss = function (suffixCss) {
|
||||||
|
return [
|
||||||
|
'section > ul',
|
||||||
|
'section > div > ul',
|
||||||
|
'ul#todo-list'
|
||||||
|
].map(function (listCss) {
|
||||||
|
return listCss + (suffixCss || '');
|
||||||
|
}).join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getToggleAllCss = function () {
|
||||||
|
return [
|
||||||
|
'section > input[type="checkbox"]',
|
||||||
|
'section > * > input[type="checkbox"]',
|
||||||
|
'input#toggle-all'
|
||||||
|
].join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getClearCompletedButtonCss = function () {
|
||||||
|
return [
|
||||||
|
'footer > button',
|
||||||
|
'footer > * > button',
|
||||||
|
'button#clear-completed'
|
||||||
|
].join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getItemCountCss = function () {
|
||||||
|
return [
|
||||||
|
'footer > span',
|
||||||
|
'footer > * > span'
|
||||||
|
].join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getFilterCss = function (index) {
|
||||||
|
return 'footer ul li:nth-child(' + (index + 1) + ') a';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getNewInputCss = function () {
|
||||||
|
return [
|
||||||
|
'header > input',
|
||||||
|
'header > * > input',
|
||||||
|
'input#new-todo'
|
||||||
|
].join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getListItemToggleCss = function (index) {
|
||||||
|
return this.getListItemCss(index, ' input[type="checkbox"]');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getListItemInputCss = function (index) {
|
||||||
|
return [
|
||||||
|
this.getListItemCss(index, ' input.edit'),
|
||||||
|
this.getListItemCss(index, ' input[type="text"]')
|
||||||
|
].join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
7
bench/implementations/inferno/test/run.sh
Executable file
7
bench/implementations/inferno/test/run.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
args="$@"
|
||||||
|
|
||||||
|
npm i && \
|
||||||
|
eval "node memory.js $args" && \
|
||||||
|
eval "npm test -- $args"
|
||||||
15
bench/implementations/inferno/test/server.js
Normal file
15
bench/implementations/inferno/test/server.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const express = require('express');
|
||||||
|
const learnJson = require('./learn.json');
|
||||||
|
|
||||||
|
const learner = require.resolve('./learn.json');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const dir = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
|
app.use(express.static(dir));
|
||||||
|
app.use('/learn.json', express.static(learner));
|
||||||
|
app.use('/favicon.ico', function () {});
|
||||||
|
|
||||||
|
app.listen(8000);
|
||||||
103
bench/implementations/inferno/test/testOperations.js
Normal file
103
bench/implementations/inferno/test/testOperations.js
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function TestOperations(page) {
|
||||||
|
|
||||||
|
this.assertItemInputFocused = function () {
|
||||||
|
return page.waitForFocusedElement(page.getEditingListItemInputCss(), 'Expected the item input to be focused');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertNewInputFocused = function () {
|
||||||
|
return page.waitForFocusedElement(page.getNewInputCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertNewInputBlurred = function () {
|
||||||
|
return page.waitForBlurredElement(page.getNewInputCss());
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItemCount = function (itemCount) {
|
||||||
|
return itemCount === 0 ?
|
||||||
|
page.waitForMainSectionRemovedOrEmpty() :
|
||||||
|
page.waitForListItemCount(itemCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertClearCompleteButtonText = function (buttonText) {
|
||||||
|
return page.waitForClearCompleteButton()
|
||||||
|
.then(page.waitForTextContent.bind(page, buttonText, 'Expected clear button text to be ' + buttonText));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertClearCompleteButtonVisibility = function (shouldBeVisible) {
|
||||||
|
var failMsg = 'Expected the clear completed items button to be ' + (shouldBeVisible ? 'visible' : 'hidden');
|
||||||
|
return page.waitForVisibility(shouldBeVisible, page.getClearCompletedButtonCss(), failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertMainSectionVisibility = function (shouldBeVisible) {
|
||||||
|
var failMsg = 'Expected main section to be ' + (shouldBeVisible ? 'visible' : 'hidden');
|
||||||
|
return page.waitForVisibility(shouldBeVisible, page.getMainSectionCss(), failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertFooterVisibility = function (shouldBeVisible) {
|
||||||
|
var failMsg = 'Expected footer to be ' + (shouldBeVisible ? 'visible' : 'hidden');
|
||||||
|
return page.waitForVisibility(shouldBeVisible, page.getFooterSectionCss(), failMsg);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItemToggleIsHidden = function (index) {
|
||||||
|
return page.waitForVisibility(false, page.getListItemToggleCss(index),
|
||||||
|
'Expected the item toggle button to be hidden');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItemLabelIsHidden = function (index) {
|
||||||
|
return page.waitForVisibility(false, page.getListItemLabelCss(index), 'Expected the item label to be hidden');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertNewItemInputFieldText = function (text) {
|
||||||
|
return page.waitForNewItemInputField()
|
||||||
|
.then(page.waitForTextContent.bind(page, text,
|
||||||
|
'Expected the new item input text field contents to be ' + text));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItemText = function (itemIndex, text) {
|
||||||
|
return page.waitForItemLabel(itemIndex)
|
||||||
|
.then(page.waitForTextContent.bind(page, text, 'Expected the item label to be ' + text));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItems = function (textArray) {
|
||||||
|
return page.getListItems().then(function (items) {
|
||||||
|
if (items.length < textArray.length) {
|
||||||
|
// This means that the framework removes rather than hides list items
|
||||||
|
textArray = textArray.filter(function (item) { return item !== page.ITEM_HIDDEN_OR_REMOVED; });
|
||||||
|
}
|
||||||
|
var ret;
|
||||||
|
textArray.forEach(function (text, i) {
|
||||||
|
if (text === page.ITEM_HIDDEN_OR_REMOVED) { return; }
|
||||||
|
var promise = page.waitForTextContent(text, 'Expected item text to be ' + text, items[i]);
|
||||||
|
ret = ret ? ret.then(promise) : promise;
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItemCountText = function (text) {
|
||||||
|
return page.waitForElement(page.getItemCountCss())
|
||||||
|
.then(page.waitForTextContent.bind(page, text, 'Expected item count text to be ' + text));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertItemCompletedStates = function (completedStates) {
|
||||||
|
return page.waitForElement(
|
||||||
|
page.getListItemsWithCompletedStatesCss(completedStates),
|
||||||
|
'Item completed states were incorrect');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertFilterAtIndexIsSelected = function (selectedIndex) {
|
||||||
|
return page.waitForElement(
|
||||||
|
page.getSelectedFilterCss(selectedIndex),
|
||||||
|
'Expexted the filter / route at index ' + selectedIndex + ' to be selected');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertCompleteAllCheckedStatus = function (shouldBeChecked) {
|
||||||
|
var failMsg = 'Expected the mark-all-completed checkbox to be ' + shouldBeChecked ? 'checked' : 'unchecked';
|
||||||
|
return page.waitForMarkAllCompletedCheckBox()
|
||||||
|
.then(page.waitForCheckedStatus.bind(page, shouldBeChecked, failMsg));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TestOperations;
|
||||||
581
bench/implementations/inferno/test/yarn.lock
Normal file
581
bench/implementations/inferno/test/yarn.lock
Normal file
|
|
@ -0,0 +1,581 @@
|
||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
abbrev@1:
|
||||||
|
version "1.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
|
||||||
|
|
||||||
|
accepts@~1.3.3:
|
||||||
|
version "1.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
|
||||||
|
dependencies:
|
||||||
|
mime-types "~2.1.11"
|
||||||
|
negotiator "0.6.1"
|
||||||
|
|
||||||
|
adm-zip@0.4.4:
|
||||||
|
version "0.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.4.tgz#a61ed5ae6905c3aea58b3a657d25033091052736"
|
||||||
|
|
||||||
|
adm-zip@^0.4.7:
|
||||||
|
version "0.4.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1"
|
||||||
|
|
||||||
|
array-flatten@1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||||
|
|
||||||
|
balanced-match@^0.4.1:
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
|
||||||
|
|
||||||
|
brace-expansion@^1.0.0:
|
||||||
|
version "1.1.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
|
||||||
|
dependencies:
|
||||||
|
balanced-match "^0.4.1"
|
||||||
|
concat-map "0.0.1"
|
||||||
|
|
||||||
|
browser-stdout@1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
|
||||||
|
|
||||||
|
chromedriver@^2.18.0:
|
||||||
|
version "2.25.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-2.25.2.tgz#20bfcf1f84ede626be39abf94454a87c1a2ef0b5"
|
||||||
|
dependencies:
|
||||||
|
adm-zip "^0.4.7"
|
||||||
|
kew "^0.5.0"
|
||||||
|
mkdirp "^0.5.0"
|
||||||
|
npmconf "^2.1.1"
|
||||||
|
rimraf "^2.0.3"
|
||||||
|
|
||||||
|
commander@2.9.0:
|
||||||
|
version "2.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
||||||
|
dependencies:
|
||||||
|
graceful-readlink ">= 1.0.0"
|
||||||
|
|
||||||
|
concat-map@0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
|
|
||||||
|
config-chain@~1.1.8:
|
||||||
|
version "1.1.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2"
|
||||||
|
dependencies:
|
||||||
|
ini "^1.3.4"
|
||||||
|
proto-list "~1.2.1"
|
||||||
|
|
||||||
|
content-disposition@0.5.1:
|
||||||
|
version "0.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b"
|
||||||
|
|
||||||
|
content-type@~1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
|
||||||
|
|
||||||
|
cookie-signature@1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||||
|
|
||||||
|
cookie@0.3.1:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
||||||
|
|
||||||
|
debug@2.2.0, debug@~2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
|
||||||
|
dependencies:
|
||||||
|
ms "0.7.1"
|
||||||
|
|
||||||
|
depd@~1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
|
||||||
|
|
||||||
|
destroy@~1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||||
|
|
||||||
|
diff@1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf"
|
||||||
|
|
||||||
|
drool@0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/drool/-/drool-0.4.0.tgz#bc60d33b46a956e756d78e995f44a6b3233401dc"
|
||||||
|
dependencies:
|
||||||
|
selenium-webdriver "2.53.1"
|
||||||
|
|
||||||
|
ee-first@1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||||
|
|
||||||
|
encodeurl@~1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
|
||||||
|
|
||||||
|
escape-html@~1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||||
|
|
||||||
|
escape-string-regexp@1.0.5:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
|
|
||||||
|
etag@~1.7.0:
|
||||||
|
version "1.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8"
|
||||||
|
|
||||||
|
express@^4.10:
|
||||||
|
version "4.14.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/express/-/express-4.14.0.tgz#c1ee3f42cdc891fb3dc650a8922d51ec847d0d66"
|
||||||
|
dependencies:
|
||||||
|
accepts "~1.3.3"
|
||||||
|
array-flatten "1.1.1"
|
||||||
|
content-disposition "0.5.1"
|
||||||
|
content-type "~1.0.2"
|
||||||
|
cookie "0.3.1"
|
||||||
|
cookie-signature "1.0.6"
|
||||||
|
debug "~2.2.0"
|
||||||
|
depd "~1.1.0"
|
||||||
|
encodeurl "~1.0.1"
|
||||||
|
escape-html "~1.0.3"
|
||||||
|
etag "~1.7.0"
|
||||||
|
finalhandler "0.5.0"
|
||||||
|
fresh "0.3.0"
|
||||||
|
merge-descriptors "1.0.1"
|
||||||
|
methods "~1.1.2"
|
||||||
|
on-finished "~2.3.0"
|
||||||
|
parseurl "~1.3.1"
|
||||||
|
path-to-regexp "0.1.7"
|
||||||
|
proxy-addr "~1.1.2"
|
||||||
|
qs "6.2.0"
|
||||||
|
range-parser "~1.2.0"
|
||||||
|
send "0.14.1"
|
||||||
|
serve-static "~1.11.1"
|
||||||
|
type-is "~1.6.13"
|
||||||
|
utils-merge "1.0.0"
|
||||||
|
vary "~1.1.0"
|
||||||
|
|
||||||
|
finalhandler@0.5.0:
|
||||||
|
version "0.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.0.tgz#e9508abece9b6dba871a6942a1d7911b91911ac7"
|
||||||
|
dependencies:
|
||||||
|
debug "~2.2.0"
|
||||||
|
escape-html "~1.0.3"
|
||||||
|
on-finished "~2.3.0"
|
||||||
|
statuses "~1.3.0"
|
||||||
|
unpipe "~1.0.0"
|
||||||
|
|
||||||
|
forwarded@~0.1.0:
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363"
|
||||||
|
|
||||||
|
fresh@0.3.0:
|
||||||
|
version "0.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f"
|
||||||
|
|
||||||
|
fs.realpath@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
|
|
||||||
|
glob@7.0.5, glob@^7.0.5:
|
||||||
|
version "7.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95"
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.2"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
"graceful-readlink@>= 1.0.0":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||||
|
|
||||||
|
growl@1.9.2:
|
||||||
|
version "1.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
|
||||||
|
|
||||||
|
has-flag@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
|
||||||
|
|
||||||
|
http-errors@~1.5.0:
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750"
|
||||||
|
dependencies:
|
||||||
|
inherits "2.0.3"
|
||||||
|
setprototypeof "1.0.2"
|
||||||
|
statuses ">= 1.3.1 < 2"
|
||||||
|
|
||||||
|
inflight@^1.0.4:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
|
dependencies:
|
||||||
|
once "^1.3.0"
|
||||||
|
wrappy "1"
|
||||||
|
|
||||||
|
inherits@2, inherits@2.0.3, inherits@~2.0.0:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||||
|
|
||||||
|
ini@^1.2.0, ini@^1.3.4:
|
||||||
|
version "1.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
|
||||||
|
|
||||||
|
ipaddr.js@1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.1.1.tgz#c791d95f52b29c1247d5df80ada39b8a73647230"
|
||||||
|
|
||||||
|
json3@3.3.2:
|
||||||
|
version "3.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
||||||
|
|
||||||
|
kew@^0.5.0:
|
||||||
|
version "0.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/kew/-/kew-0.5.0.tgz#ece11cb5d8d01a81f8ce804c8d0bba06e6b25ca2"
|
||||||
|
|
||||||
|
lodash._baseassign@^3.0.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
||||||
|
dependencies:
|
||||||
|
lodash._basecopy "^3.0.0"
|
||||||
|
lodash.keys "^3.0.0"
|
||||||
|
|
||||||
|
lodash._basecopy@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
|
||||||
|
|
||||||
|
lodash._basecreate@^3.0.0:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
|
||||||
|
|
||||||
|
lodash._getnative@^3.0.0:
|
||||||
|
version "3.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||||
|
|
||||||
|
lodash._isiterateecall@^3.0.0:
|
||||||
|
version "3.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
|
||||||
|
|
||||||
|
lodash.create@3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
|
||||||
|
dependencies:
|
||||||
|
lodash._baseassign "^3.0.0"
|
||||||
|
lodash._basecreate "^3.0.0"
|
||||||
|
lodash._isiterateecall "^3.0.0"
|
||||||
|
|
||||||
|
lodash.isarguments@^3.0.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
|
||||||
|
|
||||||
|
lodash.isarray@^3.0.0:
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
|
||||||
|
|
||||||
|
lodash.keys@^3.0.0:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
|
||||||
|
dependencies:
|
||||||
|
lodash._getnative "^3.0.0"
|
||||||
|
lodash.isarguments "^3.0.0"
|
||||||
|
lodash.isarray "^3.0.0"
|
||||||
|
|
||||||
|
media-typer@0.3.0:
|
||||||
|
version "0.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||||
|
|
||||||
|
merge-descriptors@1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||||
|
|
||||||
|
methods@~1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||||
|
|
||||||
|
mime-db@~1.25.0:
|
||||||
|
version "1.25.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392"
|
||||||
|
|
||||||
|
mime-types@~2.1.11, mime-types@~2.1.13:
|
||||||
|
version "2.1.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88"
|
||||||
|
dependencies:
|
||||||
|
mime-db "~1.25.0"
|
||||||
|
|
||||||
|
mime@1.3.4:
|
||||||
|
version "1.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
|
||||||
|
|
||||||
|
minimatch@^3.0.2:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^1.0.0"
|
||||||
|
|
||||||
|
minimist@0.0.8:
|
||||||
|
version "0.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||||
|
|
||||||
|
minimist@~0.0.1:
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||||
|
|
||||||
|
mkdirp@0.5.1, mkdirp@^0.5.0:
|
||||||
|
version "0.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||||
|
dependencies:
|
||||||
|
minimist "0.0.8"
|
||||||
|
|
||||||
|
"mocha-known-issues-reporter@git+https://github.com/ColinEberhardt/mocha-known-issues-reporter.git#v0.0.0":
|
||||||
|
version "0.0.0"
|
||||||
|
resolved "git+https://github.com/ColinEberhardt/mocha-known-issues-reporter.git#8aea16b3e9596ee794295abbed8cdb95fb379e93"
|
||||||
|
|
||||||
|
mocha@*:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3"
|
||||||
|
dependencies:
|
||||||
|
browser-stdout "1.3.0"
|
||||||
|
commander "2.9.0"
|
||||||
|
debug "2.2.0"
|
||||||
|
diff "1.4.0"
|
||||||
|
escape-string-regexp "1.0.5"
|
||||||
|
glob "7.0.5"
|
||||||
|
growl "1.9.2"
|
||||||
|
json3 "3.3.2"
|
||||||
|
lodash.create "3.1.1"
|
||||||
|
mkdirp "0.5.1"
|
||||||
|
supports-color "3.1.2"
|
||||||
|
|
||||||
|
ms@0.7.1:
|
||||||
|
version "0.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
|
||||||
|
|
||||||
|
negotiator@0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
|
||||||
|
|
||||||
|
nopt@~3.0.1:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
|
||||||
|
dependencies:
|
||||||
|
abbrev "1"
|
||||||
|
|
||||||
|
npmconf@^2.1.1:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.2.tgz#66606a4a736f1e77a059aa071a79c94ab781853a"
|
||||||
|
dependencies:
|
||||||
|
config-chain "~1.1.8"
|
||||||
|
inherits "~2.0.0"
|
||||||
|
ini "^1.2.0"
|
||||||
|
mkdirp "^0.5.0"
|
||||||
|
nopt "~3.0.1"
|
||||||
|
once "~1.3.0"
|
||||||
|
osenv "^0.1.0"
|
||||||
|
semver "2 || 3 || 4"
|
||||||
|
uid-number "0.0.5"
|
||||||
|
|
||||||
|
on-finished@~2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||||
|
dependencies:
|
||||||
|
ee-first "1.1.1"
|
||||||
|
|
||||||
|
once@^1.3.0, once@~1.3.0:
|
||||||
|
version "1.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
|
||||||
|
dependencies:
|
||||||
|
wrappy "1"
|
||||||
|
|
||||||
|
optimist@^0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
|
||||||
|
dependencies:
|
||||||
|
minimist "~0.0.1"
|
||||||
|
wordwrap "~0.0.2"
|
||||||
|
|
||||||
|
options@>=0.0.5:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
|
||||||
|
|
||||||
|
os-homedir@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
|
||||||
|
|
||||||
|
os-tmpdir@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||||
|
|
||||||
|
osenv@^0.1.0:
|
||||||
|
version "0.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.3.tgz#83cf05c6d6458fc4d5ac6362ea325d92f2754217"
|
||||||
|
dependencies:
|
||||||
|
os-homedir "^1.0.0"
|
||||||
|
os-tmpdir "^1.0.0"
|
||||||
|
|
||||||
|
parseurl@~1.3.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
|
||||||
|
|
||||||
|
path-is-absolute@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
|
|
||||||
|
path-to-regexp@0.1.7:
|
||||||
|
version "0.1.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
|
|
||||||
|
proto-list@~1.2.1:
|
||||||
|
version "1.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
|
||||||
|
|
||||||
|
proxy-addr@~1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.2.tgz#b4cc5f22610d9535824c123aef9d3cf73c40ba37"
|
||||||
|
dependencies:
|
||||||
|
forwarded "~0.1.0"
|
||||||
|
ipaddr.js "1.1.1"
|
||||||
|
|
||||||
|
qs@6.2.0:
|
||||||
|
version "6.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b"
|
||||||
|
|
||||||
|
range-parser@~1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
|
||||||
|
|
||||||
|
rimraf@^2.0.3, rimraf@^2.2.8:
|
||||||
|
version "2.5.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
|
||||||
|
dependencies:
|
||||||
|
glob "^7.0.5"
|
||||||
|
|
||||||
|
sax@0.6.x:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9"
|
||||||
|
|
||||||
|
selenium-webdriver@2.53.1:
|
||||||
|
version "2.53.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.1.tgz#b50673955dc03b9164c07773a86b25ea7161dbd9"
|
||||||
|
dependencies:
|
||||||
|
adm-zip "0.4.4"
|
||||||
|
rimraf "^2.2.8"
|
||||||
|
tmp "0.0.24"
|
||||||
|
ws "^1.0.1"
|
||||||
|
xml2js "0.4.4"
|
||||||
|
|
||||||
|
selenium-webdriver@~2.53.1:
|
||||||
|
version "2.53.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz#d29ff5a957dff1a1b49dc457756e4e4bfbdce085"
|
||||||
|
dependencies:
|
||||||
|
adm-zip "0.4.4"
|
||||||
|
rimraf "^2.2.8"
|
||||||
|
tmp "0.0.24"
|
||||||
|
ws "^1.0.1"
|
||||||
|
xml2js "0.4.4"
|
||||||
|
|
||||||
|
"semver@2 || 3 || 4":
|
||||||
|
version "4.3.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
|
||||||
|
|
||||||
|
send@0.14.1:
|
||||||
|
version "0.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/send/-/send-0.14.1.tgz#a954984325392f51532a7760760e459598c89f7a"
|
||||||
|
dependencies:
|
||||||
|
debug "~2.2.0"
|
||||||
|
depd "~1.1.0"
|
||||||
|
destroy "~1.0.4"
|
||||||
|
encodeurl "~1.0.1"
|
||||||
|
escape-html "~1.0.3"
|
||||||
|
etag "~1.7.0"
|
||||||
|
fresh "0.3.0"
|
||||||
|
http-errors "~1.5.0"
|
||||||
|
mime "1.3.4"
|
||||||
|
ms "0.7.1"
|
||||||
|
on-finished "~2.3.0"
|
||||||
|
range-parser "~1.2.0"
|
||||||
|
statuses "~1.3.0"
|
||||||
|
|
||||||
|
serve-static@~1.11.1:
|
||||||
|
version "1.11.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.1.tgz#d6cce7693505f733c759de57befc1af76c0f0805"
|
||||||
|
dependencies:
|
||||||
|
encodeurl "~1.0.1"
|
||||||
|
escape-html "~1.0.3"
|
||||||
|
parseurl "~1.3.1"
|
||||||
|
send "0.14.1"
|
||||||
|
|
||||||
|
setprototypeof@1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08"
|
||||||
|
|
||||||
|
"statuses@>= 1.3.1 < 2", statuses@~1.3.0:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
|
||||||
|
|
||||||
|
supports-color@3.1.2:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
|
||||||
|
dependencies:
|
||||||
|
has-flag "^1.0.0"
|
||||||
|
|
||||||
|
tmp@0.0.24:
|
||||||
|
version "0.0.24"
|
||||||
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12"
|
||||||
|
|
||||||
|
type-is@~1.6.13:
|
||||||
|
version "1.6.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2"
|
||||||
|
dependencies:
|
||||||
|
media-typer "0.3.0"
|
||||||
|
mime-types "~2.1.13"
|
||||||
|
|
||||||
|
uid-number@0.0.5:
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.5.tgz#5a3db23ef5dbd55b81fce0ec9a2ac6fccdebb81e"
|
||||||
|
|
||||||
|
ultron@1.0.x:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
|
||||||
|
|
||||||
|
unpipe@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||||
|
|
||||||
|
utils-merge@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
|
||||||
|
|
||||||
|
vary@~1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140"
|
||||||
|
|
||||||
|
wordwrap@~0.0.2:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
|
||||||
|
|
||||||
|
wrappy@1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
|
||||||
|
ws@^1.0.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018"
|
||||||
|
dependencies:
|
||||||
|
options ">=0.0.5"
|
||||||
|
ultron "1.0.x"
|
||||||
|
|
||||||
|
xml2js@0.4.4:
|
||||||
|
version "0.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.4.tgz#3111010003008ae19240eba17497b57c729c555d"
|
||||||
|
dependencies:
|
||||||
|
sax "0.6.x"
|
||||||
|
xmlbuilder ">=1.0.0"
|
||||||
|
|
||||||
|
xmlbuilder@>=1.0.0:
|
||||||
|
version "8.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773"
|
||||||
31
bench/implementations/inferno/webpack.config.js
Normal file
31
bench/implementations/inferno/webpack.config.js
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
const webpack = require('webpack');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './src/index.js',
|
||||||
|
output: {
|
||||||
|
path: './dist',
|
||||||
|
publicPath: 'dist',
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [{
|
||||||
|
test: /\.jsx?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel',
|
||||||
|
query: {
|
||||||
|
presets: ['es2015-loose', 'stage-0'],
|
||||||
|
plugins: ['syntax-jsx', 'inferno']
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': {
|
||||||
|
'NODE_ENV': JSON.stringify('production')
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
devServer: {
|
||||||
|
port: process.env.PORT || 8000
|
||||||
|
}
|
||||||
|
};
|
||||||
2597
bench/implementations/inferno/yarn.lock
Normal file
2597
bench/implementations/inferno/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -48,9 +48,10 @@
|
||||||
impl('Angular', '2', true, 'angular-2-optimized/index.html'),
|
impl('Angular', '2', true, 'angular-2-optimized/index.html'),
|
||||||
impl('Elm', '0.16', true, 'elm-0.16-optimized/index.html'),
|
impl('Elm', '0.16', true, 'elm-0.16-optimized/index.html'),
|
||||||
impl('Elm', '0.17', true, 'elm-0.17-optimized/index.html'),
|
impl('Elm', '0.17', true, 'elm-0.17-optimized/index.html'),
|
||||||
impl('Nim-karax', '1.0', false, 'nim-karax/examples/todoapp/index.html'),
|
impl('Inferno', '', false, 'inferno/index.html'),
|
||||||
impl('Nim-karax-component', '1.0', false, 'nim-karax-comp/examples/todoapp/index.html'),
|
impl('Nim-karax', '', false, 'nim-karax/examples/todoapp/index.html'),
|
||||||
impl('Nim-karax-component-local', '1.0', false, 'nim-karax-comp-local/examples/todoapp/index.html')
|
impl('Nim-karax-component', '', false, 'nim-karax-comp/examples/todoapp/index.html'),
|
||||||
|
impl('Nim-karax-component-local', '', false, 'nim-karax-comp-local/examples/todoapp/index.html')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
picker.ports.start.subscribe(function(impls) {
|
picker.ports.start.subscribe(function(impls) {
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ function click(className, index)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getFacts: getFacts,
|
getFacts: getFacts,
|
||||||
steps: addCompleteDeleteSteps(500)
|
steps: addCompleteDeleteSteps(150)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}();
|
}();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue