Updated with latest version of react boilerplate
This commit is contained in:
27
README.md
27
README.md
@@ -4,30 +4,21 @@ Based on the architecture suggestions from Facebook, this boilerplate will help
|
|||||||
|
|
||||||
Read more about FLUX over at [Facebook Flux](http://facebook.github.io/flux/) and I wrote a post about it too: [My experiences building a FLUX application](http://christianalfoni.github.io/javascript/2014/10/27/my-experiences-building-a-flux-application.html) and [React JS and FLUX](http://christianalfoni.github.io/javascript/2014/08/20/react-js-and-flux.html)
|
Read more about FLUX over at [Facebook Flux](http://facebook.github.io/flux/) and I wrote a post about it too: [My experiences building a FLUX application](http://christianalfoni.github.io/javascript/2014/10/27/my-experiences-building-a-flux-application.html) and [React JS and FLUX](http://christianalfoni.github.io/javascript/2014/08/20/react-js-and-flux.html)
|
||||||
|
|
||||||
### How to use
|
|
||||||
|
|
||||||
* Clone the repo
|
|
||||||
* Run `npm install`
|
|
||||||
* Open `build/index.html`, run `python -m SimpleHTTPServer` in the `build` folder or set up your own server
|
|
||||||
* **Important!** When adding new libs be sure to add them to "gulpfile.js" vendors. This will keep your rebundling speed very low and you will be happy :-)
|
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
* Run `gulp`
|
* Run `gulp`
|
||||||
* Any changes to `app` folder will automatically rebuild to `build` folder
|
* Start a webservice in the `build` folder, f.ex. `python -m SimpleHTTPServer`
|
||||||
|
* Go to `localhost:8000` to display the app
|
||||||
### Run all tests with Karma
|
* Go to `localhost:8000/testrunner.html` to see your tests
|
||||||
* Run `npm test`
|
* Any changes to `app` or `styles` folder will automatically rebuild to `build` folder
|
||||||
|
* Both tests and application changes will refresh automatically in the browser
|
||||||
Karma will launch PhantomJS and run the tests once. If you need to run tests in a normal browser change karma.conf.js to use 'Chrome' as browser. You can also keep running the tests as you write them. Set `autoWatch: true` and `singleRun: false`.
|
* Run `gulp test` to run all tests with phantomJS and produce XML reports
|
||||||
|
|
||||||
### Minify the code, ready for production
|
### Minify the code, ready for production
|
||||||
* Run `gulp deploy` to deploy to `dist` folder
|
* Run `gulp deploy`
|
||||||
|
|
||||||
### Directory
|
### Directory
|
||||||
* **app/**: Where you develop the application
|
|
||||||
* **build/**: Where your automatically builds to. This is where you launch your app in development
|
* **build/**: Where your automatically builds to. This is where you launch your app in development
|
||||||
* **dist/**: Where the deployed code exists, ready for production
|
* **dist/**: Where the deployed code exists, ready for production
|
||||||
* **tests/**: Where you put your test files
|
* **styles/**: Where you put your css files
|
||||||
|
* **specs/**: Where you put your test files
|
||||||
* **gulpfile**: Gulp configuration
|
* **gulpfile**: Gulp configuration
|
||||||
* **karma.conf.js**: Karma configuration
|
|
||||||
* **test.html**: Open when running specific test files
|
|
||||||
|
|||||||
53
app/App.js
53
app/App.js
@@ -1,22 +1,55 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var Checkboxes = require('./components/Checkboxes.js');
|
var Store = require('./Store.js');
|
||||||
var NameThrower = require('./components/NameThrower.js');
|
var actions = require('./actions.js');
|
||||||
|
|
||||||
var App = React.createClass({
|
var App = React.createClass({
|
||||||
|
getInitialState: function () {
|
||||||
|
return {
|
||||||
|
messages: Store.getMessages(),
|
||||||
|
newMessage: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
componentWillMount: function () {
|
||||||
|
Store.addChangeListener(this.changeState);
|
||||||
|
},
|
||||||
|
componentWillUnmount: function () {
|
||||||
|
Store.removeChangeListener(this.changeState);
|
||||||
|
},
|
||||||
|
changeState: function () {
|
||||||
|
this.setState({
|
||||||
|
messages: Store.getMessages()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addMessage: function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var input = this.refs.newMessage.getDOMNode();
|
||||||
|
actions.addMessage(input.value);
|
||||||
|
this.setState({
|
||||||
|
newMessage: ''
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updateNewMessage: function (event) {
|
||||||
|
this.setState({
|
||||||
|
newMessage: event.target.value
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderMessages: function (message) {
|
||||||
|
return (
|
||||||
|
<div>{message}</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Hello world!</h1>
|
{this.state.messages.map(this.renderMessages)}
|
||||||
<div>
|
<form onSubmit={this.addMessage}>
|
||||||
<Checkboxes/>
|
<input ref="newMessage" type="text" value={this.state.newMessage} onChange={this.updateNewMessage}/>
|
||||||
</div>
|
</form>
|
||||||
<div>
|
</div>
|
||||||
<NameThrower/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = App;
|
module.exports = App;
|
||||||
|
|||||||
18
app/Store.js
Normal file
18
app/Store.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
var flux = require('flux-react');
|
||||||
|
var actions = require('./actions.js');
|
||||||
|
|
||||||
|
module.exports = flux.createStore({
|
||||||
|
messages: [],
|
||||||
|
actions: [
|
||||||
|
actions.addMessage
|
||||||
|
],
|
||||||
|
addMessage: function (message) {
|
||||||
|
this.messages.push(message);
|
||||||
|
this.emitChange();
|
||||||
|
},
|
||||||
|
exports: {
|
||||||
|
getMessages: function () {
|
||||||
|
return this.messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
var flux = require('flux-react');
|
||||||
|
|
||||||
module.exports = flux.createActions([
|
module.exports = flux.createActions([
|
||||||
'checkAll',
|
'addMessage'
|
||||||
'uncheckAll',
|
|
||||||
'check'
|
|
||||||
]);
|
]);
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/** @jsx React.DOM */
|
|
||||||
var React = require('react');
|
|
||||||
var flux = require('flux-react');
|
|
||||||
var actions = require('./../actions.js');
|
|
||||||
var ColoredCheckbox = require('./Checkboxes/ColoredCheckbox.js');
|
|
||||||
var CheckboxStore = require('../stores/CheckboxStore.js');
|
|
||||||
|
|
||||||
var Checkboxes = React.createClass({
|
|
||||||
stores: [CheckboxStore],
|
|
||||||
getInitialState: function () {
|
|
||||||
return {
|
|
||||||
checkboxes: CheckboxStore.getCheckboxes()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
componentWillMount: function () {
|
|
||||||
CheckboxStore.addChangeListener(this.update);
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
CheckboxStore.removeChangeListener(this.update);
|
|
||||||
},
|
|
||||||
update: function () {
|
|
||||||
this.setState({
|
|
||||||
checkboxes: CheckboxStore.getCheckboxes()
|
|
||||||
});
|
|
||||||
},
|
|
||||||
check: function (color) {
|
|
||||||
actions.check(color);
|
|
||||||
},
|
|
||||||
checkAll: function () {
|
|
||||||
actions.checkAll();
|
|
||||||
},
|
|
||||||
uncheckAll: function () {
|
|
||||||
actions.uncheckAll();
|
|
||||||
},
|
|
||||||
renderCheckbox: function (checkbox, index) {
|
|
||||||
return <ColoredCheckbox
|
|
||||||
key={index}
|
|
||||||
color={checkbox.color}
|
|
||||||
checked={checkbox.checked}
|
|
||||||
onChange={this.check}/>
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var checkboxes = this.state.checkboxes.map(this.renderCheckbox);
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
{checkboxes}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button onClick={this.checkAll}>Check all</button>
|
|
||||||
<button onClick={this.uncheckAll}>Uncheck all</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = Checkboxes;
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/** @jsx React.DOM */
|
|
||||||
var React = require('react');
|
|
||||||
|
|
||||||
var ColoredCheckbox = React.createClass({
|
|
||||||
changeColor: function () {
|
|
||||||
this.props.onChange(this.props.color);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var style = {
|
|
||||||
backgroundColor: this.props.color,
|
|
||||||
padding: '5px'
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<span key={this.props.key} style={style}>
|
|
||||||
<input type="checkbox"
|
|
||||||
onChange={this.changeColor}
|
|
||||||
checked={this.props.checked}/>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = ColoredCheckbox;
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/** @jsx React.DOM */
|
|
||||||
var React = require('react');
|
|
||||||
var CheckboxStore = require('../stores/CheckboxStore.js');
|
|
||||||
|
|
||||||
var NameThrower = React.createClass({
|
|
||||||
getInitialState: function () {
|
|
||||||
return {
|
|
||||||
name: '',
|
|
||||||
colors: CheckboxStore.getColors()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
componentWillMount: function () {
|
|
||||||
CheckboxStore.addChangeListener(this.update);
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
CheckboxStore.removeChangeListener(this.update);
|
|
||||||
},
|
|
||||||
update: function () {
|
|
||||||
this.setState({
|
|
||||||
colors: CheckboxStore.getColors()
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateName: function (event) {
|
|
||||||
this.setState({
|
|
||||||
name: event.target.value
|
|
||||||
});
|
|
||||||
},
|
|
||||||
renderColors: function (color, index) {
|
|
||||||
var style = {color: color};
|
|
||||||
return <div key={index} style={style}>{this.state.name}</div>
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var names = this.state.colors.map(this.renderColors);
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<input type="text" value={this.state.name} onChange={this.updateName}/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{names}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = NameThrower;
|
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var flux = require('flux-react');
|
|
||||||
var App = require('./App.js');
|
var App = require('./App.js');
|
||||||
|
React.render(<App/>, document.body);
|
||||||
flux.debug();
|
|
||||||
|
|
||||||
React.renderComponent(<App/>, document.body);
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
var flux = require('flux-react');
|
|
||||||
var actions = require('./../actions.js');
|
|
||||||
|
|
||||||
var CheckboxStore = flux.createStore({
|
|
||||||
getInitialState: function () {
|
|
||||||
return {
|
|
||||||
checkboxes: [{
|
|
||||||
color: 'red',
|
|
||||||
checked: false
|
|
||||||
}, {
|
|
||||||
color: 'blue',
|
|
||||||
checked: false
|
|
||||||
}, {
|
|
||||||
color: 'green',
|
|
||||||
checked: false
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
},
|
|
||||||
actions: [
|
|
||||||
actions.checkAll,
|
|
||||||
actions.uncheckAll,
|
|
||||||
actions.check
|
|
||||||
],
|
|
||||||
checkAll: function () {
|
|
||||||
this.state.checkboxes.forEach(function (checkbox) {
|
|
||||||
checkbox.checked = true;
|
|
||||||
});
|
|
||||||
this.emitChange();
|
|
||||||
},
|
|
||||||
uncheckAll: function () {
|
|
||||||
this.state.checkboxes.forEach(function (checkbox) {
|
|
||||||
checkbox.checked = false;
|
|
||||||
});
|
|
||||||
this.emitChange();
|
|
||||||
},
|
|
||||||
check: function (color) {
|
|
||||||
this.state.checkboxes.forEach(function (checkbox) {
|
|
||||||
if (checkbox.color === color) {
|
|
||||||
checkbox.checked = !checkbox.checked;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.emitChange();
|
|
||||||
},
|
|
||||||
exports: {
|
|
||||||
getCheckboxes: function () {
|
|
||||||
return this.checkboxes;
|
|
||||||
},
|
|
||||||
getColors: function () {
|
|
||||||
return this.checkboxes.map(function (checkbox) {
|
|
||||||
if (checkbox.checked) {
|
|
||||||
return checkbox.color;
|
|
||||||
} else {
|
|
||||||
return 'black';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = CheckboxStore;
|
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<link rel="stylesheet" href="main.css"/>
|
||||||
<style>
|
|
||||||
div {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<script>document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>')</script>
|
||||||
<script src="vendors.js"></script>
|
<script src="vendors.js"></script>
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
BIN
build/jasmine/.DS_Store
vendored
Normal file
BIN
build/jasmine/.DS_Store
vendored
Normal file
Binary file not shown.
20
build/jasmine/MIT.LICENSE
Executable file
20
build/jasmine/MIT.LICENSE
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2008-2014 Pivotal Labs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
26
build/jasmine/SpecRunner.html
Executable file
26
build/jasmine/SpecRunner.html
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Jasmine Spec Runner v2.0.3</title>
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.3/jasmine_favicon.png">
|
||||||
|
<link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.3/jasmine.css">
|
||||||
|
|
||||||
|
<script type="text/javascript" src="lib/jasmine-2.0.3/jasmine.js"></script>
|
||||||
|
<script type="text/javascript" src="lib/jasmine-2.0.3/jasmine-html.js"></script>
|
||||||
|
<script type="text/javascript" src="lib/jasmine-2.0.3/boot.js"></script>
|
||||||
|
|
||||||
|
<!-- include source files here... -->
|
||||||
|
<script type="text/javascript" src="src/Player.js"></script>
|
||||||
|
<script type="text/javascript" src="src/Song.js"></script>
|
||||||
|
|
||||||
|
<!-- include spec files here... -->
|
||||||
|
<script type="text/javascript" src="spec/SpecHelper.js"></script>
|
||||||
|
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
build/jasmine/lib/.DS_Store
vendored
Normal file
BIN
build/jasmine/lib/.DS_Store
vendored
Normal file
Binary file not shown.
120
build/jasmine/lib/jasmine-2.0.3/boot.js
Executable file
120
build/jasmine/lib/jasmine-2.0.3/boot.js
Executable file
@@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
|
||||||
|
|
||||||
|
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
|
||||||
|
|
||||||
|
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
|
||||||
|
|
||||||
|
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Require & Instantiate
|
||||||
|
*
|
||||||
|
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
|
||||||
|
*/
|
||||||
|
window.jasmine = jasmineRequire.core(jasmineRequire);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
|
||||||
|
*/
|
||||||
|
jasmineRequire.html(jasmine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the Jasmine environment. This is used to run all specs in a project.
|
||||||
|
*/
|
||||||
|
var env = jasmine.getEnv();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## The Global Interface
|
||||||
|
*
|
||||||
|
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
|
||||||
|
*/
|
||||||
|
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
|
||||||
|
*/
|
||||||
|
if (typeof window == "undefined" && typeof exports == "object") {
|
||||||
|
extend(exports, jasmineInterface);
|
||||||
|
} else {
|
||||||
|
extend(window, jasmineInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Runner Parameters
|
||||||
|
*
|
||||||
|
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var queryString = new jasmine.QueryString({
|
||||||
|
getWindowLocation: function() { return window.location; }
|
||||||
|
});
|
||||||
|
|
||||||
|
var catchingExceptions = queryString.getParam("catch");
|
||||||
|
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Reporters
|
||||||
|
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
|
||||||
|
*/
|
||||||
|
var htmlReporter = new jasmine.HtmlReporter({
|
||||||
|
env: env,
|
||||||
|
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
|
||||||
|
getContainer: function() { return document.body; },
|
||||||
|
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||||
|
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||||
|
timer: new jasmine.Timer()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
|
||||||
|
*/
|
||||||
|
env.addReporter(jasmineInterface.jsApiReporter);
|
||||||
|
env.addReporter(htmlReporter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
|
||||||
|
*/
|
||||||
|
var specFilter = new jasmine.HtmlSpecFilter({
|
||||||
|
filterString: function() { return queryString.getParam("spec"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
env.specFilter = function(spec) {
|
||||||
|
return specFilter.matches(spec.getFullName());
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
|
||||||
|
*/
|
||||||
|
window.setTimeout = window.setTimeout;
|
||||||
|
window.setInterval = window.setInterval;
|
||||||
|
window.clearTimeout = window.clearTimeout;
|
||||||
|
window.clearInterval = window.clearInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Execution
|
||||||
|
*
|
||||||
|
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
|
||||||
|
*/
|
||||||
|
var currentWindowOnload = window.onload;
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
if (currentWindowOnload) {
|
||||||
|
currentWindowOnload();
|
||||||
|
}
|
||||||
|
htmlReporter.initialize();
|
||||||
|
env.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for readability above.
|
||||||
|
*/
|
||||||
|
function extend(destination, source) {
|
||||||
|
for (var property in source) destination[property] = source[property];
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
}());
|
||||||
166
build/jasmine/lib/jasmine-2.0.3/console.js
Executable file
166
build/jasmine/lib/jasmine-2.0.3/console.js
Executable file
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2008-2014 Pivotal Labs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
function getJasmineRequireObj() {
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
return exports;
|
||||||
|
} else {
|
||||||
|
window.jasmineRequire = window.jasmineRequire || {};
|
||||||
|
return window.jasmineRequire;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getJasmineRequireObj().console = function(jRequire, j$) {
|
||||||
|
j$.ConsoleReporter = jRequire.ConsoleReporter();
|
||||||
|
};
|
||||||
|
|
||||||
|
getJasmineRequireObj().ConsoleReporter = function() {
|
||||||
|
|
||||||
|
var noopTimer = {
|
||||||
|
start: function(){},
|
||||||
|
elapsed: function(){ return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
function ConsoleReporter(options) {
|
||||||
|
var print = options.print,
|
||||||
|
showColors = options.showColors || false,
|
||||||
|
onComplete = options.onComplete || function() {},
|
||||||
|
timer = options.timer || noopTimer,
|
||||||
|
specCount,
|
||||||
|
failureCount,
|
||||||
|
failedSpecs = [],
|
||||||
|
pendingCount,
|
||||||
|
ansi = {
|
||||||
|
green: '\x1B[32m',
|
||||||
|
red: '\x1B[31m',
|
||||||
|
yellow: '\x1B[33m',
|
||||||
|
none: '\x1B[0m'
|
||||||
|
};
|
||||||
|
|
||||||
|
this.jasmineStarted = function() {
|
||||||
|
specCount = 0;
|
||||||
|
failureCount = 0;
|
||||||
|
pendingCount = 0;
|
||||||
|
print('Started');
|
||||||
|
printNewline();
|
||||||
|
timer.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.jasmineDone = function() {
|
||||||
|
printNewline();
|
||||||
|
for (var i = 0; i < failedSpecs.length; i++) {
|
||||||
|
specFailureDetails(failedSpecs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(specCount > 0) {
|
||||||
|
printNewline();
|
||||||
|
|
||||||
|
var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
|
||||||
|
failureCount + ' ' + plural('failure', failureCount);
|
||||||
|
|
||||||
|
if (pendingCount) {
|
||||||
|
specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(specCounts);
|
||||||
|
} else {
|
||||||
|
print('No specs found');
|
||||||
|
}
|
||||||
|
|
||||||
|
printNewline();
|
||||||
|
var seconds = timer.elapsed() / 1000;
|
||||||
|
print('Finished in ' + seconds + ' ' + plural('second', seconds));
|
||||||
|
|
||||||
|
printNewline();
|
||||||
|
|
||||||
|
onComplete(failureCount === 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specDone = function(result) {
|
||||||
|
specCount++;
|
||||||
|
|
||||||
|
if (result.status == 'pending') {
|
||||||
|
pendingCount++;
|
||||||
|
print(colored('yellow', '*'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status == 'passed') {
|
||||||
|
print(colored('green', '.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status == 'failed') {
|
||||||
|
failureCount++;
|
||||||
|
failedSpecs.push(result);
|
||||||
|
print(colored('red', 'F'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
function printNewline() {
|
||||||
|
print('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function colored(color, str) {
|
||||||
|
return showColors ? (ansi[color] + str + ansi.none) : str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function plural(str, count) {
|
||||||
|
return count == 1 ? str : str + 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
function repeat(thing, times) {
|
||||||
|
var arr = [];
|
||||||
|
for (var i = 0; i < times; i++) {
|
||||||
|
arr.push(thing);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function indent(str, spaces) {
|
||||||
|
var lines = (str || '').split('\n');
|
||||||
|
var newArr = [];
|
||||||
|
for (var i = 0; i < lines.length; i++) {
|
||||||
|
newArr.push(repeat(' ', spaces).join('') + lines[i]);
|
||||||
|
}
|
||||||
|
return newArr.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function specFailureDetails(result) {
|
||||||
|
printNewline();
|
||||||
|
print(result.fullName);
|
||||||
|
|
||||||
|
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||||
|
var failedExpectation = result.failedExpectations[i];
|
||||||
|
printNewline();
|
||||||
|
print(indent(failedExpectation.message, 2));
|
||||||
|
print(indent(failedExpectation.stack, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
printNewline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConsoleReporter;
|
||||||
|
};
|
||||||
390
build/jasmine/lib/jasmine-2.0.3/jasmine-html.js
Executable file
390
build/jasmine/lib/jasmine-2.0.3/jasmine-html.js
Executable file
@@ -0,0 +1,390 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2008-2014 Pivotal Labs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
jasmineRequire.html = function(j$) {
|
||||||
|
j$.ResultsNode = jasmineRequire.ResultsNode();
|
||||||
|
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||||
|
j$.QueryString = jasmineRequire.QueryString();
|
||||||
|
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmineRequire.HtmlReporter = function(j$) {
|
||||||
|
|
||||||
|
var noopTimer = {
|
||||||
|
start: function() {},
|
||||||
|
elapsed: function() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
function HtmlReporter(options) {
|
||||||
|
var env = options.env || {},
|
||||||
|
getContainer = options.getContainer,
|
||||||
|
createElement = options.createElement,
|
||||||
|
createTextNode = options.createTextNode,
|
||||||
|
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
|
||||||
|
timer = options.timer || noopTimer,
|
||||||
|
results = [],
|
||||||
|
specsExecuted = 0,
|
||||||
|
failureCount = 0,
|
||||||
|
pendingSpecCount = 0,
|
||||||
|
htmlReporterMain,
|
||||||
|
symbols;
|
||||||
|
|
||||||
|
this.initialize = function() {
|
||||||
|
clearPrior();
|
||||||
|
htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'},
|
||||||
|
createDom('div', {className: 'banner'},
|
||||||
|
createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}),
|
||||||
|
createDom('span', {className: 'version'}, j$.version)
|
||||||
|
),
|
||||||
|
createDom('ul', {className: 'symbol-summary'}),
|
||||||
|
createDom('div', {className: 'alert'}),
|
||||||
|
createDom('div', {className: 'results'},
|
||||||
|
createDom('div', {className: 'failures'})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
getContainer().appendChild(htmlReporterMain);
|
||||||
|
|
||||||
|
symbols = find('.symbol-summary');
|
||||||
|
};
|
||||||
|
|
||||||
|
var totalSpecsDefined;
|
||||||
|
this.jasmineStarted = function(options) {
|
||||||
|
totalSpecsDefined = options.totalSpecsDefined || 0;
|
||||||
|
timer.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
var summary = createDom('div', {className: 'summary'});
|
||||||
|
|
||||||
|
var topResults = new j$.ResultsNode({}, '', null),
|
||||||
|
currentParent = topResults;
|
||||||
|
|
||||||
|
this.suiteStarted = function(result) {
|
||||||
|
currentParent.addChild(result, 'suite');
|
||||||
|
currentParent = currentParent.last();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.suiteDone = function(result) {
|
||||||
|
if (currentParent == topResults) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentParent = currentParent.parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specStarted = function(result) {
|
||||||
|
currentParent.addChild(result, 'spec');
|
||||||
|
};
|
||||||
|
|
||||||
|
var failures = [];
|
||||||
|
this.specDone = function(result) {
|
||||||
|
if(noExpectations(result) && console && console.error) {
|
||||||
|
console.error('Spec \'' + result.fullName + '\' has no expectations.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status != 'disabled') {
|
||||||
|
specsExecuted++;
|
||||||
|
}
|
||||||
|
|
||||||
|
symbols.appendChild(createDom('li', {
|
||||||
|
className: noExpectations(result) ? 'empty' : result.status,
|
||||||
|
id: 'spec_' + result.id,
|
||||||
|
title: result.fullName
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
if (result.status == 'failed') {
|
||||||
|
failureCount++;
|
||||||
|
|
||||||
|
var failure =
|
||||||
|
createDom('div', {className: 'spec-detail failed'},
|
||||||
|
createDom('div', {className: 'description'},
|
||||||
|
createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
|
||||||
|
),
|
||||||
|
createDom('div', {className: 'messages'})
|
||||||
|
);
|
||||||
|
var messages = failure.childNodes[1];
|
||||||
|
|
||||||
|
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||||
|
var expectation = result.failedExpectations[i];
|
||||||
|
messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message));
|
||||||
|
messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
failures.push(failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status == 'pending') {
|
||||||
|
pendingSpecCount++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.jasmineDone = function() {
|
||||||
|
var banner = find('.banner');
|
||||||
|
banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
|
||||||
|
|
||||||
|
var alert = find('.alert');
|
||||||
|
|
||||||
|
alert.appendChild(createDom('span', { className: 'exceptions' },
|
||||||
|
createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'),
|
||||||
|
createDom('input', {
|
||||||
|
className: 'raise',
|
||||||
|
id: 'raise-exceptions',
|
||||||
|
type: 'checkbox'
|
||||||
|
})
|
||||||
|
));
|
||||||
|
var checkbox = find('#raise-exceptions');
|
||||||
|
|
||||||
|
checkbox.checked = !env.catchingExceptions();
|
||||||
|
checkbox.onclick = onRaiseExceptionsClick;
|
||||||
|
|
||||||
|
if (specsExecuted < totalSpecsDefined) {
|
||||||
|
var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||||
|
alert.appendChild(
|
||||||
|
createDom('span', {className: 'bar skipped'},
|
||||||
|
createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var statusBarMessage = '';
|
||||||
|
var statusBarClassName = 'bar ';
|
||||||
|
|
||||||
|
if (totalSpecsDefined > 0) {
|
||||||
|
statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
|
||||||
|
if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
|
||||||
|
statusBarClassName += (failureCount > 0) ? 'failed' : 'passed';
|
||||||
|
} else {
|
||||||
|
statusBarClassName += 'skipped';
|
||||||
|
statusBarMessage += 'No specs found';
|
||||||
|
}
|
||||||
|
|
||||||
|
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
|
||||||
|
|
||||||
|
var results = find('.results');
|
||||||
|
results.appendChild(summary);
|
||||||
|
|
||||||
|
summaryList(topResults, summary);
|
||||||
|
|
||||||
|
function summaryList(resultsTree, domParent) {
|
||||||
|
var specListNode;
|
||||||
|
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||||
|
var resultNode = resultsTree.children[i];
|
||||||
|
if (resultNode.type == 'suite') {
|
||||||
|
var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id},
|
||||||
|
createDom('li', {className: 'suite-detail'},
|
||||||
|
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
summaryList(resultNode, suiteListNode);
|
||||||
|
domParent.appendChild(suiteListNode);
|
||||||
|
}
|
||||||
|
if (resultNode.type == 'spec') {
|
||||||
|
if (domParent.getAttribute('class') != 'specs') {
|
||||||
|
specListNode = createDom('ul', {className: 'specs'});
|
||||||
|
domParent.appendChild(specListNode);
|
||||||
|
}
|
||||||
|
var specDescription = resultNode.result.description;
|
||||||
|
if(noExpectations(resultNode.result)) {
|
||||||
|
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
|
||||||
|
}
|
||||||
|
specListNode.appendChild(
|
||||||
|
createDom('li', {
|
||||||
|
className: resultNode.result.status,
|
||||||
|
id: 'spec-' + resultNode.result.id
|
||||||
|
},
|
||||||
|
createDom('a', {href: specHref(resultNode.result)}, specDescription)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failures.length) {
|
||||||
|
alert.appendChild(
|
||||||
|
createDom('span', {className: 'menu bar spec-list'},
|
||||||
|
createDom('span', {}, 'Spec List | '),
|
||||||
|
createDom('a', {className: 'failures-menu', href: '#'}, 'Failures')));
|
||||||
|
alert.appendChild(
|
||||||
|
createDom('span', {className: 'menu bar failure-list'},
|
||||||
|
createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'),
|
||||||
|
createDom('span', {}, ' | Failures ')));
|
||||||
|
|
||||||
|
find('.failures-menu').onclick = function() {
|
||||||
|
setMenuModeTo('failure-list');
|
||||||
|
};
|
||||||
|
find('.spec-list-menu').onclick = function() {
|
||||||
|
setMenuModeTo('spec-list');
|
||||||
|
};
|
||||||
|
|
||||||
|
setMenuModeTo('failure-list');
|
||||||
|
|
||||||
|
var failureNode = find('.failures');
|
||||||
|
for (var i = 0; i < failures.length; i++) {
|
||||||
|
failureNode.appendChild(failures[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
function find(selector) {
|
||||||
|
return getContainer().querySelector('.jasmine_html-reporter ' + selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearPrior() {
|
||||||
|
// return the reporter
|
||||||
|
var oldReporter = find('');
|
||||||
|
|
||||||
|
if(oldReporter) {
|
||||||
|
getContainer().removeChild(oldReporter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDom(type, attrs, childrenVarArgs) {
|
||||||
|
var el = createElement(type);
|
||||||
|
|
||||||
|
for (var i = 2; i < arguments.length; i++) {
|
||||||
|
var child = arguments[i];
|
||||||
|
|
||||||
|
if (typeof child === 'string') {
|
||||||
|
el.appendChild(createTextNode(child));
|
||||||
|
} else {
|
||||||
|
if (child) {
|
||||||
|
el.appendChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var attr in attrs) {
|
||||||
|
if (attr == 'className') {
|
||||||
|
el[attr] = attrs[attr];
|
||||||
|
} else {
|
||||||
|
el.setAttribute(attr, attrs[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pluralize(singular, count) {
|
||||||
|
var word = (count == 1 ? singular : singular + 's');
|
||||||
|
|
||||||
|
return '' + count + ' ' + word;
|
||||||
|
}
|
||||||
|
|
||||||
|
function specHref(result) {
|
||||||
|
return '?spec=' + encodeURIComponent(result.fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMenuModeTo(mode) {
|
||||||
|
htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function noExpectations(result) {
|
||||||
|
return (result.failedExpectations.length + result.passedExpectations.length) === 0 &&
|
||||||
|
result.status === 'passed';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HtmlReporter;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmineRequire.HtmlSpecFilter = function() {
|
||||||
|
function HtmlSpecFilter(options) {
|
||||||
|
var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||||
|
var filterPattern = new RegExp(filterString);
|
||||||
|
|
||||||
|
this.matches = function(specName) {
|
||||||
|
return filterPattern.test(specName);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return HtmlSpecFilter;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmineRequire.ResultsNode = function() {
|
||||||
|
function ResultsNode(result, type, parent) {
|
||||||
|
this.result = result;
|
||||||
|
this.type = type;
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
this.children = [];
|
||||||
|
|
||||||
|
this.addChild = function(result, type) {
|
||||||
|
this.children.push(new ResultsNode(result, type, this));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.last = function() {
|
||||||
|
return this.children[this.children.length - 1];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultsNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmineRequire.QueryString = function() {
|
||||||
|
function QueryString(options) {
|
||||||
|
|
||||||
|
this.setParam = function(key, value) {
|
||||||
|
var paramMap = queryStringToParamMap();
|
||||||
|
paramMap[key] = value;
|
||||||
|
options.getWindowLocation().search = toQueryString(paramMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getParam = function(key) {
|
||||||
|
return queryStringToParamMap()[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
function toQueryString(paramMap) {
|
||||||
|
var qStrPairs = [];
|
||||||
|
for (var prop in paramMap) {
|
||||||
|
qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop]));
|
||||||
|
}
|
||||||
|
return '?' + qStrPairs.join('&');
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryStringToParamMap() {
|
||||||
|
var paramStr = options.getWindowLocation().search.substring(1),
|
||||||
|
params = [],
|
||||||
|
paramMap = {};
|
||||||
|
|
||||||
|
if (paramStr.length > 0) {
|
||||||
|
params = paramStr.split('&');
|
||||||
|
for (var i = 0; i < params.length; i++) {
|
||||||
|
var p = params[i].split('=');
|
||||||
|
var value = decodeURIComponent(p[1]);
|
||||||
|
if (value === 'true' || value === 'false') {
|
||||||
|
value = JSON.parse(value);
|
||||||
|
}
|
||||||
|
paramMap[decodeURIComponent(p[0])] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paramMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return QueryString;
|
||||||
|
};
|
||||||
61
build/jasmine/lib/jasmine-2.0.3/jasmine.css
Executable file
61
build/jasmine/lib/jasmine-2.0.3/jasmine.css
Executable file
File diff suppressed because one or more lines are too long
2593
build/jasmine/lib/jasmine-2.0.3/jasmine.js
Executable file
2593
build/jasmine/lib/jasmine-2.0.3/jasmine.js
Executable file
File diff suppressed because it is too large
Load Diff
BIN
build/jasmine/lib/jasmine-2.0.3/jasmine_favicon.png
Executable file
BIN
build/jasmine/lib/jasmine-2.0.3/jasmine_favicon.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
58
build/jasmine/spec/PlayerSpec.js
Executable file
58
build/jasmine/spec/PlayerSpec.js
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
describe("Player", function() {
|
||||||
|
var player;
|
||||||
|
var song;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
player = new Player();
|
||||||
|
song = new Song();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to play a Song", function() {
|
||||||
|
player.play(song);
|
||||||
|
expect(player.currentlyPlayingSong).toEqual(song);
|
||||||
|
|
||||||
|
//demonstrates use of custom matcher
|
||||||
|
expect(player).toBePlaying(song);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when song has been paused", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
player.play(song);
|
||||||
|
player.pause();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should indicate that the song is currently paused", function() {
|
||||||
|
expect(player.isPlaying).toBeFalsy();
|
||||||
|
|
||||||
|
// demonstrates use of 'not' with a custom matcher
|
||||||
|
expect(player).not.toBePlaying(song);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be possible to resume", function() {
|
||||||
|
player.resume();
|
||||||
|
expect(player.isPlaying).toBeTruthy();
|
||||||
|
expect(player.currentlyPlayingSong).toEqual(song);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// demonstrates use of spies to intercept and test method calls
|
||||||
|
it("tells the current song if the user has made it a favorite", function() {
|
||||||
|
spyOn(song, 'persistFavoriteStatus');
|
||||||
|
|
||||||
|
player.play(song);
|
||||||
|
player.makeFavorite();
|
||||||
|
|
||||||
|
expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
//demonstrates use of expected exceptions
|
||||||
|
describe("#resume", function() {
|
||||||
|
it("should throw an exception if song is already playing", function() {
|
||||||
|
player.play(song);
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
player.resume();
|
||||||
|
}).toThrowError("song is already playing");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
15
build/jasmine/spec/SpecHelper.js
Executable file
15
build/jasmine/spec/SpecHelper.js
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
beforeEach(function () {
|
||||||
|
jasmine.addMatchers({
|
||||||
|
toBePlaying: function () {
|
||||||
|
return {
|
||||||
|
compare: function (actual, expected) {
|
||||||
|
var player = actual;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pass: player.currentlyPlayingSong === expected && player.isPlaying
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
22
build/jasmine/src/Player.js
Executable file
22
build/jasmine/src/Player.js
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
function Player() {
|
||||||
|
}
|
||||||
|
Player.prototype.play = function(song) {
|
||||||
|
this.currentlyPlayingSong = song;
|
||||||
|
this.isPlaying = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Player.prototype.pause = function() {
|
||||||
|
this.isPlaying = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Player.prototype.resume = function() {
|
||||||
|
if (this.isPlaying) {
|
||||||
|
throw new Error("song is already playing");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isPlaying = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Player.prototype.makeFavorite = function() {
|
||||||
|
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
||||||
|
};
|
||||||
7
build/jasmine/src/Song.js
Executable file
7
build/jasmine/src/Song.js
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
function Song() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Song.prototype.persistFavoriteStatus = function(value) {
|
||||||
|
// something complicated
|
||||||
|
throw new Error("not yet implemented");
|
||||||
|
};
|
||||||
183
build/jasmine2-junit/boot.js
Normal file
183
build/jasmine2-junit/boot.js
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/**
|
||||||
|
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
|
||||||
|
|
||||||
|
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
|
||||||
|
|
||||||
|
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
|
||||||
|
|
||||||
|
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Require & Instantiate
|
||||||
|
*
|
||||||
|
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
|
||||||
|
*/
|
||||||
|
window.jasmine = jasmineRequire.core(jasmineRequire);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
|
||||||
|
*/
|
||||||
|
jasmineRequire.html(jasmine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the Jasmine environment. This is used to run all specs in a project.
|
||||||
|
*/
|
||||||
|
var env = jasmine.getEnv();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## The Global Interface
|
||||||
|
*
|
||||||
|
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
|
||||||
|
*/
|
||||||
|
var jasmineInterface = {
|
||||||
|
describe: function(description, specDefinitions) {
|
||||||
|
return env.describe(description, specDefinitions);
|
||||||
|
},
|
||||||
|
|
||||||
|
xdescribe: function(description, specDefinitions) {
|
||||||
|
return env.xdescribe(description, specDefinitions);
|
||||||
|
},
|
||||||
|
|
||||||
|
it: function(desc, func) {
|
||||||
|
return env.it(desc, func);
|
||||||
|
},
|
||||||
|
|
||||||
|
xit: function(desc, func) {
|
||||||
|
return env.xit(desc, func);
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeEach: function(beforeEachFunction) {
|
||||||
|
return env.beforeEach(beforeEachFunction);
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach: function(afterEachFunction) {
|
||||||
|
return env.afterEach(afterEachFunction);
|
||||||
|
},
|
||||||
|
|
||||||
|
expect: function(actual) {
|
||||||
|
return env.expect(actual);
|
||||||
|
},
|
||||||
|
|
||||||
|
pending: function() {
|
||||||
|
return env.pending();
|
||||||
|
},
|
||||||
|
|
||||||
|
spyOn: function(obj, methodName) {
|
||||||
|
return env.spyOn(obj, methodName);
|
||||||
|
},
|
||||||
|
|
||||||
|
jsApiReporter: new jasmine.JsApiReporter({
|
||||||
|
timer: new jasmine.Timer()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
|
||||||
|
*/
|
||||||
|
if (typeof window == "undefined" && typeof exports == "object") {
|
||||||
|
extend(exports, jasmineInterface);
|
||||||
|
} else {
|
||||||
|
extend(window, jasmineInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose the interface for adding custom equality testers.
|
||||||
|
*/
|
||||||
|
jasmine.addCustomEqualityTester = function(tester) {
|
||||||
|
env.addCustomEqualityTester(tester);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose the interface for adding custom expectation matchers
|
||||||
|
*/
|
||||||
|
jasmine.addMatchers = function(matchers) {
|
||||||
|
return env.addMatchers(matchers);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose the mock interface for the JavaScript timeout functions
|
||||||
|
*/
|
||||||
|
jasmine.clock = function() {
|
||||||
|
return env.clock;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Runner Parameters
|
||||||
|
*
|
||||||
|
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var queryString = new jasmine.QueryString({
|
||||||
|
getWindowLocation: function() { return window.location; }
|
||||||
|
});
|
||||||
|
|
||||||
|
var catchingExceptions = queryString.getParam("catch");
|
||||||
|
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Reporters
|
||||||
|
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
|
||||||
|
*/
|
||||||
|
var htmlReporter = new jasmine.HtmlReporter({
|
||||||
|
env: env,
|
||||||
|
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
|
||||||
|
getContainer: function() { return document.body; },
|
||||||
|
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||||
|
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||||
|
timer: new jasmine.Timer()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
|
||||||
|
*/
|
||||||
|
env.addReporter(jasmineInterface.jsApiReporter);
|
||||||
|
var JUnitXmlReporter = jasmineRequire.JUnitXmlReporter()
|
||||||
|
env.addReporter(new JUnitXmlReporter());
|
||||||
|
env.addReporter(htmlReporter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
|
||||||
|
*/
|
||||||
|
var specFilter = new jasmine.HtmlSpecFilter({
|
||||||
|
filterString: function() { return queryString.getParam("spec"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
env.specFilter = function(spec) {
|
||||||
|
return specFilter.matches(spec.getFullName());
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
|
||||||
|
*/
|
||||||
|
window.setTimeout = window.setTimeout;
|
||||||
|
window.setInterval = window.setInterval;
|
||||||
|
window.clearTimeout = window.clearTimeout;
|
||||||
|
window.clearInterval = window.clearInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Execution
|
||||||
|
*
|
||||||
|
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
|
||||||
|
*/
|
||||||
|
var currentWindowOnload = window.onload;
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
if (currentWindowOnload) {
|
||||||
|
currentWindowOnload();
|
||||||
|
}
|
||||||
|
htmlReporter.initialize();
|
||||||
|
env.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for readability above.
|
||||||
|
*/
|
||||||
|
function extend(destination, source) {
|
||||||
|
for (var property in source) destination[property] = source[property];
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
}());
|
||||||
198
build/jasmine2-junit/jasmine2-junit.js
Normal file
198
build/jasmine2-junit/jasmine2-junit.js
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function getJasmineRequireObj() {
|
||||||
|
if (typeof module !== "undefined" && module.exports) {
|
||||||
|
return exports;
|
||||||
|
} else {
|
||||||
|
window.jasmineRequire = window.jasmineRequire || {};
|
||||||
|
return window.jasmineRequire;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof getJasmineRequireObj() == 'undefined') {
|
||||||
|
throw new Error("jasmine 2.0 must be loaded before jasmine-junit");
|
||||||
|
}
|
||||||
|
|
||||||
|
getJasmineRequireObj().JUnitXmlReporter = function() {
|
||||||
|
|
||||||
|
|
||||||
|
function JUnitXmlReporter(options) {
|
||||||
|
var runStartTime;
|
||||||
|
var specStartTime;
|
||||||
|
var suiteLevel = -1;
|
||||||
|
var suites = []
|
||||||
|
var currentSuite;
|
||||||
|
var totalNumberOfSpecs;
|
||||||
|
var totalNumberOfFailures;
|
||||||
|
|
||||||
|
this.jasmineStarted = function(started) {
|
||||||
|
totalNumberOfSpecs = started.totalSpecsDefined;
|
||||||
|
runStartTime = new Date();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.jasmineDone = function() {
|
||||||
|
console.log('Jasmine ran in ', elapsed(runStartTime, new Date()), ' seconds')
|
||||||
|
window.done = true
|
||||||
|
};
|
||||||
|
|
||||||
|
this.suiteStarted = function(result) {
|
||||||
|
suiteLevel++;
|
||||||
|
if (suiteLevel == 0) {
|
||||||
|
totalNumberOfSpecs = 0;
|
||||||
|
totalNumberOfFailures = 0;
|
||||||
|
suites.push(result);
|
||||||
|
currentSuite = result;
|
||||||
|
currentSuite.startTime = new Date();
|
||||||
|
currentSuite.noOfSpecs = 0;
|
||||||
|
currentSuite.noOfFails = 0;
|
||||||
|
currentSuite.specs = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.suiteDone = function(result) {
|
||||||
|
if (suiteLevel == 0) {
|
||||||
|
currentSuite.endTime = new Date();
|
||||||
|
writeFile('.', descToFilename(result.description), suiteToJUnitXml(currentSuite))
|
||||||
|
}
|
||||||
|
suiteLevel--;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specStarted = function(result) {
|
||||||
|
specStartTime = new Date();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specDone = function(result) {
|
||||||
|
totalNumberOfSpecs++;
|
||||||
|
|
||||||
|
if (isFailed(result)) {
|
||||||
|
currentSuite.noOfFails++;
|
||||||
|
}
|
||||||
|
result.startTime = specStartTime;
|
||||||
|
result.endTime = new Date();
|
||||||
|
currentSuite.specs.push(result);
|
||||||
|
currentSuite.noOfSpecs++;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return JUnitXmlReporter;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isFailed(result) {
|
||||||
|
return result.status === 'failed'
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSkipped(result) {
|
||||||
|
return result.status === 'pending'
|
||||||
|
}
|
||||||
|
|
||||||
|
function suiteToJUnitXml(suite) {
|
||||||
|
var resultXml = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||||
|
resultXml += '<testsuites>\n';
|
||||||
|
resultXml += '\t<testsuite tests="' + suite.noOfSpecs + '" errors="0" failures="' + suite.noOfFails + '" time="' + elapsed(suite.startTime, suite.endTime) + '" timestamp="' + ISODateString(suite.startTime) + '">\n'
|
||||||
|
for (var i = 0; i < suite.specs.length; i++) {
|
||||||
|
resultXml += specToJUnitXml(suite.specs[i], suite.id);
|
||||||
|
}
|
||||||
|
resultXml += '\t</testsuite>\n</testsuites>\n\n'
|
||||||
|
return resultXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
function specToJUnitXml(spec, suiteId) {
|
||||||
|
var xml = '\t\t<testcase classname="' + suiteId +
|
||||||
|
'" name="' + escapeInvalidXmlChars(spec.description) + '" time="' + elapsed(spec.startTime, spec.endTime) + '">\n';
|
||||||
|
if (isSkipped(spec)) {
|
||||||
|
xml += '\t\t\t<skipped />\n';
|
||||||
|
}
|
||||||
|
if (isFailed(spec)) {
|
||||||
|
xml += failedToJUnitXml(spec.failedExpectations)
|
||||||
|
}
|
||||||
|
xml += '\t\t</testcase>\n'
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
function failedToJUnitXml(failedExpectations) {
|
||||||
|
var failure;
|
||||||
|
var failureXml = ""
|
||||||
|
for (var i = 0; i < failedExpectations.length; i++) {
|
||||||
|
failure = failedExpectations[i];
|
||||||
|
failureXml += '\t\t\t<failure type="' + failure.matcherName + '" message="' + trim(escapeInvalidXmlChars(failure.message)) + '">\n';
|
||||||
|
failureXml += escapeInvalidXmlChars(failure.stack || failure.message);
|
||||||
|
failureXml += "\t\t\t</failure>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return failureXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
function descToFilename(desc) {
|
||||||
|
return 'TEST-' + desc + '.xml';
|
||||||
|
}
|
||||||
|
|
||||||
|
function ISODateString(d) {
|
||||||
|
function pad(n) {
|
||||||
|
return n < 10 ? '0' + n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.getFullYear() + '-' +
|
||||||
|
pad(d.getMonth() + 1) + '-' +
|
||||||
|
pad(d.getDate()) + 'T' +
|
||||||
|
pad(d.getHours()) + ':' +
|
||||||
|
pad(d.getMinutes()) + ':' +
|
||||||
|
pad(d.getSeconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
function elapsed(startTime, endTime) {
|
||||||
|
return (endTime - startTime) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim(str) {
|
||||||
|
return str.replace(/^\s+/, "").replace(/\s+$/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeInvalidXmlChars(str) {
|
||||||
|
return str.replace(/</g, "<")
|
||||||
|
.replace(/\>/g, ">")
|
||||||
|
.replace(/\"/g, """)
|
||||||
|
.replace(/\'/g, "'")
|
||||||
|
.replace(/\&/g, "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeFile(path, filename, text) {
|
||||||
|
function getQualifiedFilename(separator) {
|
||||||
|
if (path && path.substr(-1) !== separator && filename.substr(0) !== separator) {
|
||||||
|
path += separator;
|
||||||
|
}
|
||||||
|
return path + filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PhantomJS
|
||||||
|
if(typeof(__phantom_writeFile) !== 'undefined') {
|
||||||
|
try {
|
||||||
|
// turn filename into a qualified path
|
||||||
|
filename = getQualifiedFilename(window.fs_path_separator);
|
||||||
|
// function injected by jasmine-runner.js
|
||||||
|
__phantom_writeFile(filename, text);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error writing file', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node.js
|
||||||
|
if(typeof(global) !== 'undefined') {
|
||||||
|
try {
|
||||||
|
var fs = require("fs");
|
||||||
|
var nodejs_path = require("path");
|
||||||
|
var fd = fs.openSync(nodejs_path.join(path, filename), "w");
|
||||||
|
fs.writeSync(fd, text, 0);
|
||||||
|
fs.closeSync(fd);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error writing file', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})()
|
||||||
3
build/main.css
Normal file
3
build/main.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
body {
|
||||||
|
background-color: #EAEAEA;
|
||||||
|
}
|
||||||
292
build/main.js
292
build/main.js
File diff suppressed because one or more lines are too long
96
build/specs.js
Executable file
96
build/specs.js
Executable file
@@ -0,0 +1,96 @@
|
|||||||
|
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"./specs/App-spec.js":[function(require,module,exports){
|
||||||
|
var App = require('./../app/App.js');
|
||||||
|
var TestUtils = require('react-addons').TestUtils;
|
||||||
|
|
||||||
|
describe("App", function() {
|
||||||
|
|
||||||
|
it("should be wrapped with a div", function() {
|
||||||
|
var app = TestUtils.renderIntoDocument(App());
|
||||||
|
expect(app.getDOMNode().tagName).toEqual('DIV');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
},{"./../app/App.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/App.js","react-addons":"react-addons"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/App.js":[function(require,module,exports){
|
||||||
|
/** @jsx React.DOM */
|
||||||
|
var React = require('react');
|
||||||
|
var Store = require('./Store.js');
|
||||||
|
var actions = require('./actions.js');
|
||||||
|
|
||||||
|
var App = React.createClass({displayName: 'App',
|
||||||
|
getInitialState: function () {
|
||||||
|
return {
|
||||||
|
messages: Store.getMessages(),
|
||||||
|
newMessage: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
componentWillMount: function () {
|
||||||
|
Store.addChangeListener(this.changeState);
|
||||||
|
},
|
||||||
|
componentWillUnmount: function () {
|
||||||
|
Store.removeChangeListener(this.changeState);
|
||||||
|
},
|
||||||
|
changeState: function () {
|
||||||
|
this.setState({
|
||||||
|
messages: Store.getMessages()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addMessage: function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var input = this.refs.newMessage.getDOMNode();
|
||||||
|
actions.addMessage(input.value);
|
||||||
|
this.setState({
|
||||||
|
newMessage: ''
|
||||||
|
});
|
||||||
|
},
|
||||||
|
updateNewMessage: function (event) {
|
||||||
|
this.setState({
|
||||||
|
newMessage: event.target.value
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderMessages: function (message) {
|
||||||
|
return (
|
||||||
|
React.createElement("div", null, message)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
React.createElement("div", null,
|
||||||
|
this.state.messages.map(this.renderMessages),
|
||||||
|
React.createElement("form", {onSubmit: this.addMessage},
|
||||||
|
React.createElement("input", {ref: "newMessage", type: "text", value: this.state.newMessage, onChange: this.updateNewMessage})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = App;
|
||||||
|
|
||||||
|
},{"./Store.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/Store.js","./actions.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/actions.js","react":"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/Store.js":[function(require,module,exports){
|
||||||
|
var flux = require('flux-react');
|
||||||
|
var actions = require('./actions.js');
|
||||||
|
|
||||||
|
module.exports = flux.createStore({
|
||||||
|
messages: [],
|
||||||
|
actions: [
|
||||||
|
actions.addMessage
|
||||||
|
],
|
||||||
|
addMessage: function (message) {
|
||||||
|
this.messages.push(message);
|
||||||
|
this.emitChange();
|
||||||
|
},
|
||||||
|
exports: {
|
||||||
|
getMessages: function () {
|
||||||
|
return this.messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},{"./actions.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/actions.js","flux-react":"flux-react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/actions.js":[function(require,module,exports){
|
||||||
|
var flux = require('flux-react');
|
||||||
|
|
||||||
|
module.exports = flux.createActions([
|
||||||
|
'addMessage'
|
||||||
|
]);
|
||||||
|
},{"flux-react":"flux-react"}]},{},["./specs/App-spec.js"])
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcGVjcy9BcHAtc3BlYy5qcyIsImFwcC9BcHAuanMiLCJhcHAvU3RvcmUuanMiLCJhcHAvYWN0aW9ucy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsInZhciBBcHAgPSByZXF1aXJlKCcuLy4uL2FwcC9BcHAuanMnKTtcbnZhciBUZXN0VXRpbHMgPSByZXF1aXJlKCdyZWFjdC1hZGRvbnMnKS5UZXN0VXRpbHM7XG5cbmRlc2NyaWJlKFwiQXBwXCIsIGZ1bmN0aW9uKCkge1xuXG4gIGl0KFwic2hvdWxkIGJlIHdyYXBwZWQgd2l0aCBhIGRpdlwiLCBmdW5jdGlvbigpIHtcbiAgICB2YXIgYXBwID0gVGVzdFV0aWxzLnJlbmRlckludG9Eb2N1bWVudChBcHAoKSk7XG4gICAgZXhwZWN0KGFwcC5nZXRET01Ob2RlKCkudGFnTmFtZSkudG9FcXVhbCgnRElWJyk7XG4gIH0pO1xuXG59KTsiLCIvKiogQGpzeCBSZWFjdC5ET00gKi9cbnZhciBSZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG52YXIgU3RvcmUgPSByZXF1aXJlKCcuL1N0b3JlLmpzJyk7XG52YXIgYWN0aW9ucyA9IHJlcXVpcmUoJy4vYWN0aW9ucy5qcycpO1xuXG52YXIgQXBwID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiAnQXBwJyxcbiAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2VzOiBTdG9yZS5nZXRNZXNzYWdlcygpLFxuICAgICAgbmV3TWVzc2FnZTogJydcbiAgICB9O1xuICB9LFxuICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICBTdG9yZS5hZGRDaGFuZ2VMaXN0ZW5lcih0aGlzLmNoYW5nZVN0YXRlKTtcbiAgfSxcbiAgY29tcG9uZW50V2lsbFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICBTdG9yZS5yZW1vdmVDaGFuZ2VMaXN0ZW5lcih0aGlzLmNoYW5nZVN0YXRlKTtcbiAgfSxcbiAgY2hhbmdlU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgIG1lc3NhZ2VzOiBTdG9yZS5nZXRNZXNzYWdlcygpXG4gICAgfSk7XG4gIH0sXG4gIGFkZE1lc3NhZ2U6IGZ1bmN0aW9uIChldmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgdmFyIGlucHV0ID0gdGhpcy5yZWZzLm5ld01lc3NhZ2UuZ2V0RE9NTm9kZSgpO1xuICAgIGFjdGlvbnMuYWRkTWVzc2FnZShpbnB1dC52YWx1ZSk7XG4gICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICBuZXdNZXNzYWdlOiAnJ1xuICAgIH0pO1xuICB9LFxuICB1cGRhdGVOZXdNZXNzYWdlOiBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgIG5ld01lc3NhZ2U6IGV2ZW50LnRhcmdldC52YWx1ZVxuICAgIH0pO1xuICB9LFxuICByZW5kZXJNZXNzYWdlczogZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gKFxuICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBtZXNzYWdlKVxuICAgICk7XG4gIH0sXG5cdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgbnVsbCwgXG4gICAgICAgIHRoaXMuc3RhdGUubWVzc2FnZXMubWFwKHRoaXMucmVuZGVyTWVzc2FnZXMpLCBcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImZvcm1cIiwge29uU3VibWl0OiB0aGlzLmFkZE1lc3NhZ2V9LCBcbiAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIiwge3JlZjogXCJuZXdNZXNzYWdlXCIsIHR5cGU6IFwidGV4dFwiLCB2YWx1ZTogdGhpcy5zdGF0ZS5uZXdNZXNzYWdlLCBvbkNoYW5nZTogdGhpcy51cGRhdGVOZXdNZXNzYWdlfSlcbiAgICAgICAgKVxuICAgICAgKVxuXHRcdCk7XG5cdH1cblx0XG59KTtcblx0XG5tb2R1bGUuZXhwb3J0cyA9IEFwcDtcbiIsInZhciBmbHV4ID0gcmVxdWlyZSgnZmx1eC1yZWFjdCcpO1xudmFyIGFjdGlvbnMgPSByZXF1aXJlKCcuL2FjdGlvbnMuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmbHV4LmNyZWF0ZVN0b3JlKHtcbiAgbWVzc2FnZXM6IFtdLFxuICBhY3Rpb25zOiBbXG4gICAgYWN0aW9ucy5hZGRNZXNzYWdlXG4gIF0sXG4gIGFkZE1lc3NhZ2U6IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHRoaXMuZW1pdENoYW5nZSgpO1xuICB9LFxuICBleHBvcnRzOiB7XG4gICAgZ2V0TWVzc2FnZXM6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICAgIH1cbiAgfVxufSk7IiwidmFyIGZsdXggPSByZXF1aXJlKCdmbHV4LXJlYWN0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZmx1eC5jcmVhdGVBY3Rpb25zKFtcbiAgJ2FkZE1lc3NhZ2UnXG5dKTsiXX0=
|
||||||
20
build/testrunner-phantomjs.html
Normal file
20
build/testrunner-phantomjs.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Jasmine Test Runner</title>
|
||||||
|
<link rel="shortcut icon" type="image/png" href="jasmine/lib/jasmine-2.0.3/jasmine_favicon.png">
|
||||||
|
<link rel="stylesheet" type="text/css" href="jasmine/lib/jasmine-2.0.3/jasmine.css">
|
||||||
|
|
||||||
|
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.3/jasmine.js"></script>
|
||||||
|
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.3/jasmine-html.js"></script>
|
||||||
|
<script type="text/javascript" src="jasmine2-junit/jasmine2-junit.js"></script>
|
||||||
|
<script type="text/javascript" src="jasmine2-junit/boot.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="vendors.js"></script>
|
||||||
|
<script type="text/javascript" src="specs.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
22
build/testrunner.html
Normal file
22
build/testrunner.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Jasmine Test Runner</title>
|
||||||
|
<link rel="shortcut icon" type="image/png" href="jasmine/lib/jasmine-2.0.3/jasmine_favicon.png">
|
||||||
|
<link rel="stylesheet" type="text/css" href="jasmine/lib/jasmine-2.0.3/jasmine.css">
|
||||||
|
|
||||||
|
<script>document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>')</script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.3/jasmine.js"></script>
|
||||||
|
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.3/jasmine-html.js"></script>
|
||||||
|
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.3/boot.js"></script>
|
||||||
|
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.3/console.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="vendors.js"></script>
|
||||||
|
<script type="text/javascript" src="specs.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
30090
build/vendors.js
30090
build/vendors.js
File diff suppressed because one or more lines are too long
19
dist/index.html
vendored
Executable file → Normal file
19
dist/index.html
vendored
Executable file → Normal file
@@ -1,15 +1,10 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<style>
|
<link rel="stylesheet" href="main.css"/>
|
||||||
div {
|
</head>
|
||||||
margin-bottom: 10px;
|
<body>
|
||||||
}
|
<script src="main.js"></script>
|
||||||
</style>
|
</body>
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="vendors.js"></script>
|
|
||||||
<script src="main.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
1
dist/main.css
vendored
Normal file
1
dist/main.css
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
body{background-color:#EAEAEA}
|
||||||
9
dist/main.js
vendored
9
dist/main.js
vendored
File diff suppressed because one or more lines are too long
6
dist/vendors.js
vendored
6
dist/vendors.js
vendored
File diff suppressed because one or more lines are too long
1431
es5-shim.js
1431
es5-shim.js
File diff suppressed because it is too large
Load Diff
226
gulpfile.js
226
gulpfile.js
@@ -1,121 +1,164 @@
|
|||||||
var gulp = require('gulp');
|
var gulp = require('gulp');
|
||||||
|
var source = require('vinyl-source-stream'); // Used to stream bundle for further handling
|
||||||
var browserify = require('browserify');
|
var browserify = require('browserify');
|
||||||
var watchify = require('watchify');
|
var watchify = require('watchify');
|
||||||
var source = require('vinyl-source-stream');
|
|
||||||
var reactify = require('reactify');
|
var reactify = require('reactify');
|
||||||
var gulpif = require('gulp-if');
|
var gulpif = require('gulp-if');
|
||||||
var uglify = require('gulp-uglify');
|
var uglify = require('gulp-uglify');
|
||||||
var streamify = require('gulp-streamify');
|
var streamify = require('gulp-streamify');
|
||||||
var notify = require('gulp-notify');
|
var notify = require('gulp-notify');
|
||||||
|
var concat = require('gulp-concat');
|
||||||
|
var cssmin = require('gulp-cssmin');
|
||||||
var gutil = require('gulp-util');
|
var gutil = require('gulp-util');
|
||||||
var shell = require('gulp-shell');
|
var shell = require('gulp-shell');
|
||||||
|
var glob = require('glob');
|
||||||
|
var livereload = require('gulp-livereload');
|
||||||
|
var jasminePhantomJs = require('gulp-jasmine2-phantomjs');
|
||||||
|
|
||||||
var appOptions = {
|
// External dependencies you do not want to rebundle while developing,
|
||||||
|
// but include in your application deployment
|
||||||
|
var dependencies = [
|
||||||
|
'react',
|
||||||
|
'react-addons',
|
||||||
|
'flux-react'
|
||||||
|
];
|
||||||
|
|
||||||
/*
|
var browserifyTask = function (options) {
|
||||||
* DIRECTORIES
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Where your app lives
|
// Our app bundler
|
||||||
appDir: './app',
|
var appBundler = browserify({
|
||||||
|
entries: [options.src], // Only need initial file, browserify finds the rest
|
||||||
|
transform: [reactify], // We want to convert JSX to normal javascript
|
||||||
|
debug: options.development, // Gives us sourcemapping
|
||||||
|
cache: {}, packageCache: {}, fullPaths: true // Requirement of watchify
|
||||||
|
});
|
||||||
|
|
||||||
// Where your production version is deployed
|
// We set our dependencies as externals on our app bundler when developing
|
||||||
distDir: './dist',
|
(options.development ? dependencies : []).forEach(function (dep) {
|
||||||
|
appBundler.external(dep);
|
||||||
// Where you bundled development version will run from
|
});
|
||||||
buildDir: './build',
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BUNDLE FILES
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The name of your main app file
|
|
||||||
entryFile: 'main.js',
|
|
||||||
|
|
||||||
// The name of your bundled vendors
|
|
||||||
vendorsFile: 'vendors.js',
|
|
||||||
|
|
||||||
/*
|
|
||||||
* VENDORS
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Add other vendors here, if any
|
|
||||||
vendors: [
|
|
||||||
'react',
|
|
||||||
'flux-react'
|
|
||||||
]
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// The task that handles both development and deployment
|
|
||||||
var browserifyTask = function (bundleOptions) {
|
|
||||||
|
|
||||||
// This bundle only runs when you start to develop,
|
|
||||||
// it is needed to prevent rebundling external deps
|
|
||||||
// on project changes
|
|
||||||
var vendorBundler = browserify({
|
|
||||||
debug: bundleOptions.debug,
|
|
||||||
require: appOptions.vendors
|
|
||||||
});
|
|
||||||
|
|
||||||
// This bundle is for the application
|
|
||||||
var appBundler = browserify({
|
|
||||||
entries: [appOptions.appDir + '/' + appOptions.entryFile],
|
|
||||||
debug: bundleOptions.debug,
|
|
||||||
|
|
||||||
// These options are needed by Watchify
|
|
||||||
cache: {},
|
|
||||||
packageCache: {},
|
|
||||||
fullPaths: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add reactify transformer
|
|
||||||
appBundler.transform(reactify);
|
|
||||||
|
|
||||||
// Add vendors as externals
|
|
||||||
appOptions.vendors.forEach(function (vendor) {
|
|
||||||
appBundler.external(vendor);
|
|
||||||
});
|
|
||||||
|
|
||||||
// The rebundle process
|
// The rebundle process
|
||||||
var rebundle = function () {
|
var rebundle = function () {
|
||||||
|
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
|
console.log('Building APP bundle');
|
||||||
appBundler.bundle()
|
appBundler.bundle()
|
||||||
.on('error', gutil.log)
|
.on('error', gutil.log)
|
||||||
.pipe(source(appOptions.entryFile))
|
.pipe(source('main.js'))
|
||||||
.pipe(gulpif(bundleOptions.uglify, streamify(uglify())))
|
.pipe(gulpif(!options.development, streamify(uglify())))
|
||||||
.pipe(gulp.dest(bundleOptions.dest))
|
.pipe(gulp.dest(options.dest))
|
||||||
|
.pipe(gulpif(options.development, livereload()))
|
||||||
.pipe(notify(function () {
|
.pipe(notify(function () {
|
||||||
console.log('Built in ' + (Date.now() - start) + 'ms');
|
console.log('APP bundle built in ' + (Date.now() - start) + 'ms');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fire up Watchify when developing
|
// Fire up Watchify when developing
|
||||||
if (bundleOptions.watch) {
|
if (options.development) {
|
||||||
appBundler = watchify(appBundler);
|
appBundler = watchify(appBundler);
|
||||||
appBundler.on('update', rebundle);
|
appBundler.on('update', rebundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the vendor bundle when the default Gulp task starts
|
rebundle();
|
||||||
vendorBundler.bundle()
|
|
||||||
.on('error', gutil.log)
|
|
||||||
.pipe(source(appOptions.vendorsFile))
|
|
||||||
.pipe(gulpif(bundleOptions.uglify, streamify(uglify())))
|
|
||||||
.pipe(gulp.dest(bundleOptions.dest));
|
|
||||||
|
|
||||||
return rebundle();
|
// We create a separate bundle for our dependencies as they
|
||||||
|
// should not rebundle on file changes. This only happens when
|
||||||
|
// we develop. When deploying the dependencies will be included
|
||||||
|
// in the application bundle
|
||||||
|
if (options.development) {
|
||||||
|
|
||||||
};
|
var testFiles = glob.sync('./specs/**/*-spec.js');
|
||||||
|
var testBundler = browserify({
|
||||||
|
entries: testFiles,
|
||||||
|
debug: true, // Gives us sourcemapping
|
||||||
|
transform: [reactify],
|
||||||
|
cache: {}, packageCache: {}, fullPaths: true // Requirement of watchify
|
||||||
|
});
|
||||||
|
|
||||||
|
dependencies.forEach(function (dep) {
|
||||||
|
testBundler.external(dep);
|
||||||
|
});
|
||||||
|
|
||||||
|
var rebundleTests = function () {
|
||||||
|
var start = Date.now();
|
||||||
|
console.log('Building TEST bundle');
|
||||||
|
testBundler.bundle()
|
||||||
|
.on('error', gutil.log)
|
||||||
|
.pipe(source('specs.js'))
|
||||||
|
.pipe(gulp.dest(options.dest))
|
||||||
|
.pipe(livereload())
|
||||||
|
.pipe(notify(function () {
|
||||||
|
console.log('TEST bundle built in ' + (Date.now() - start) + 'ms');
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
testBundler = watchify(testBundler);
|
||||||
|
testBundler.on('update', rebundleTests);
|
||||||
|
rebundleTests();
|
||||||
|
|
||||||
|
// Remove react-addons when deploying, as it is only for
|
||||||
|
// testing
|
||||||
|
if (!options.development) {
|
||||||
|
dependencies.splice(dependencies.indexOf('react-addons'), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var vendorsBundler = browserify({
|
||||||
|
debug: true,
|
||||||
|
require: dependencies
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run the vendor bundle
|
||||||
|
var start = new Date();
|
||||||
|
console.log('Building VENDORS bundle');
|
||||||
|
vendorsBundler.bundle()
|
||||||
|
.on('error', gutil.log)
|
||||||
|
.pipe(source('vendors.js'))
|
||||||
|
.pipe(gulpif(!options.development, streamify(uglify())))
|
||||||
|
.pipe(gulp.dest(options.dest))
|
||||||
|
.pipe(notify(function () {
|
||||||
|
console.log('VENDORS bundle built in ' + (Date.now() - start) + 'ms');
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var cssTask = function (options) {
|
||||||
|
if (options.development) {
|
||||||
|
var run = function () {
|
||||||
|
console.log(arguments);
|
||||||
|
var start = new Date();
|
||||||
|
console.log('Building CSS bundle');
|
||||||
|
gulp.src(options.src)
|
||||||
|
.pipe(concat('main.css'))
|
||||||
|
.pipe(gulp.dest(options.dest))
|
||||||
|
.pipe(notify(function () {
|
||||||
|
console.log('CSS bundle built in ' + (Date.now() - start) + 'ms');
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
run();
|
||||||
|
gulp.watch(options.src, run);
|
||||||
|
} else {
|
||||||
|
gulp.src(options.src)
|
||||||
|
.pipe(concat('main.css'))
|
||||||
|
.pipe(cssmin())
|
||||||
|
.pipe(gulp.dest(options.dest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts our development workflow
|
||||||
gulp.task('default', function () {
|
gulp.task('default', function () {
|
||||||
|
|
||||||
browserifyTask({
|
browserifyTask({
|
||||||
watch: true,
|
development: true,
|
||||||
dest: appOptions.buildDir,
|
src: './app/main.js',
|
||||||
uglify: false,
|
dest: './build'
|
||||||
debug: true
|
});
|
||||||
|
|
||||||
|
cssTask({
|
||||||
|
development: true,
|
||||||
|
src: './styles/**/*.css',
|
||||||
|
dest: './build'
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -123,10 +166,19 @@ gulp.task('default', function () {
|
|||||||
gulp.task('deploy', function () {
|
gulp.task('deploy', function () {
|
||||||
|
|
||||||
browserifyTask({
|
browserifyTask({
|
||||||
watch: false,
|
development: false,
|
||||||
dest: appOptions.distDir,
|
src: './app/main.js',
|
||||||
uglify: true,
|
dest: './dist'
|
||||||
debug: false
|
});
|
||||||
|
|
||||||
|
cssTask({
|
||||||
|
development: false,
|
||||||
|
src: './styles/**/*.css',
|
||||||
|
dest: './dist'
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('test', function () {
|
||||||
|
return gulp.src('./build/testrunner-phantomjs.html').pipe(jasminePhantomJs());
|
||||||
|
});
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
module.exports = function(config) {
|
|
||||||
config.set({
|
|
||||||
|
|
||||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
|
||||||
basePath: '',
|
|
||||||
|
|
||||||
|
|
||||||
// frameworks to use
|
|
||||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
|
||||||
frameworks: ['mocha', 'browserify'],
|
|
||||||
|
|
||||||
|
|
||||||
// list of files / patterns to load in the browser
|
|
||||||
files: [
|
|
||||||
'es5-shim.js',
|
|
||||||
'tests/**/*.js'
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
// list of files to exclude
|
|
||||||
exclude: [
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
// preprocess matching files before serving them to the browser
|
|
||||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
|
||||||
preprocessors: {
|
|
||||||
'tests/**/*.js': ['browserify']
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
browserify: {
|
|
||||||
debug: true,
|
|
||||||
transform: [ 'reactify' ]
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// test results reporter to use
|
|
||||||
// possible values: 'dots', 'progress'
|
|
||||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
|
||||||
reporters: ['progress'],
|
|
||||||
|
|
||||||
|
|
||||||
// web server port
|
|
||||||
port: 9876,
|
|
||||||
|
|
||||||
|
|
||||||
// enable / disable colors in the output (reporters and logs)
|
|
||||||
colors: true,
|
|
||||||
|
|
||||||
|
|
||||||
// level of logging
|
|
||||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
|
|
||||||
|
|
||||||
// enable / disable watching file and executing tests whenever any file changes
|
|
||||||
autoWatch: true,
|
|
||||||
|
|
||||||
|
|
||||||
// start these browsers
|
|
||||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
|
||||||
//browsers: ['Chrome', 'Firefox', 'PhantomJS'],
|
|
||||||
browsers: ['PhantomJS'],
|
|
||||||
|
|
||||||
|
|
||||||
// Continuous Integration mode
|
|
||||||
// if true, Karma captures browsers, runs the tests and exits
|
|
||||||
singleRun: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
40
package.json
40
package.json
@@ -1,35 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "flux-react-boilerplate",
|
"name": "flux-react-boilerplate",
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"description": "React flux architecture boilerplate",
|
"description": "React application boilerplate",
|
||||||
"main": "gulp",
|
|
||||||
"scripts": {
|
|
||||||
"test": "./node_modules/karma/bin/karma start karma.conf.js"
|
|
||||||
},
|
|
||||||
"author": "Christian Alfoni",
|
"author": "Christian Alfoni",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browserify": "^5.9.3",
|
"browserify": "^6.2.0",
|
||||||
"chai": "^1.9.1",
|
"glob": "^4.0.6",
|
||||||
"flux-react": "^2.1.0",
|
"gulp": "^3.8.9",
|
||||||
"gulp": "^3.8.7",
|
"gulp-concat": "^2.3.4",
|
||||||
|
"gulp-cssmin": "^0.1.6",
|
||||||
"gulp-if": "^1.2.4",
|
"gulp-if": "^1.2.4",
|
||||||
"gulp-livereload": "^2.1.0",
|
"gulp-livereload": "^2.1.1",
|
||||||
"gulp-notify": "^1.4.2",
|
"gulp-notify": "^1.4.2",
|
||||||
"gulp-shell": "^0.2.10",
|
|
||||||
"gulp-streamify": "0.0.5",
|
"gulp-streamify": "0.0.5",
|
||||||
"gulp-uglify": "^0.3.1",
|
"gulp-uglify": "^0.3.1",
|
||||||
"gulp-util": "^3.0.0",
|
"gulp-util": "^3.0.0",
|
||||||
"react": "^0.11.1",
|
"gulp-jasmine2-phantomjs": "^0.1.1",
|
||||||
"reactify": "^0.14.0",
|
"gulp-shell": "^0.2.10",
|
||||||
|
"phantomjs": "^1.9.12",
|
||||||
|
"react-addons": "^0.9.0",
|
||||||
|
"reactify": "^0.15.2",
|
||||||
"vinyl-source-stream": "^0.1.1",
|
"vinyl-source-stream": "^0.1.1",
|
||||||
"watchify": "^1.0.2",
|
"watchify": "^2.1.1"
|
||||||
"karma": "^0.12.21",
|
},
|
||||||
"karma-bro": "^0.6.2",
|
"dependencies": {
|
||||||
"karma-chrome-launcher": "^0.1.4",
|
"flux-react": "^2.4.1",
|
||||||
"karma-firefox-launcher": "^0.1.3",
|
"react": "^0.12.0"
|
||||||
"karma-mocha": "^0.1.7",
|
|
||||||
"karma-phantomjs-launcher": "^0.1.4",
|
|
||||||
"mocha": "^1.21.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
specs/App-spec.js
Normal file
11
specs/App-spec.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var App = require('./../app/App.js');
|
||||||
|
var TestUtils = require('react-addons').TestUtils;
|
||||||
|
|
||||||
|
describe("App", function() {
|
||||||
|
|
||||||
|
it("should be wrapped with a div", function() {
|
||||||
|
var app = TestUtils.renderIntoDocument(App());
|
||||||
|
expect(app.getDOMNode().tagName).toEqual('DIV');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
3
styles/main.css
Normal file
3
styles/main.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
body {
|
||||||
|
background-color: #EAEAEA;
|
||||||
|
}
|
||||||
22
test.html
22
test.html
@@ -1,22 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Mocha Tests</title>
|
|
||||||
<link rel="stylesheet" href="node_modules/mocha/mocha.css" />
|
|
||||||
<script src="node_modules/mocha/mocha.js"></script>
|
|
||||||
<script>mocha.setup('bdd')</script>
|
|
||||||
<script src="dev/test.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="mocha"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript">//<![CDATA[
|
|
||||||
document.write('<script src="http://localhost:35729/livereload.js?snipver=1" type="text/javascript"><\/script>')
|
|
||||||
//]]></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
mocha.run();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/** @jsx React.DOM */
|
|
||||||
var expect = require('chai').expect;
|
|
||||||
|
|
||||||
describe('App', function() {
|
|
||||||
it('has the text Hello world!', function() {
|
|
||||||
var React = require('react/addons');
|
|
||||||
var App = require('../app/App.js');
|
|
||||||
var TestUtils = React.addons.TestUtils;
|
|
||||||
|
|
||||||
var app = TestUtils.renderIntoDocument(
|
|
||||||
<App/>
|
|
||||||
);
|
|
||||||
|
|
||||||
var h1 = TestUtils.findRenderedDOMComponentWithTag(app, 'h1');
|
|
||||||
|
|
||||||
expect(h1.getDOMNode().textContent).to.equal('Hello world!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user