<commit_before>/**
 * app.js
 *
 * This is the entry file for the application, only setup and boilerplate
 * code.
 */

// Needed for redux-saga es6 generator support
import 'babel-polyfill';
// Import all the third party stuff
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { useScroll } from 'react-router-scroll';
import { applyRouterMiddleware, Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

/* eslint-disable import/no-unresolved, import/extensions */
// Load the favicon, the manifest.json file and the .htaccess file
import '!file-loader?name=[name].[ext]!./favicon.ico';
import '!file-loader?name=[name].[ext]!./manifest.json';
import 'file-loader?name=[name].[ext]!./.htaccess';
/* eslint-enable import/no-unresolved, import/extensions */

import { makeSelectLocationState } from 'containers/App/selectors';
import App from 'containers/App';
import 'sanitize.css/sanitize.css';

import createRoutes from './routes';

/* import FontFaceObserver from 'fontfaceobserver';*/
import configureStore from './store';

// Import CSS reset and Global Styles
import './global-styles';

// Observe loading of Open Sans (to remove open sans, remove the <link> tag in
// the index.html file and this observer)
/* import styles from 'containers/App/styles.css';*/
/* const openSansObserver = new FontFaceObserver('Open Sans', {});*/

// When Open Sans is loaded, add a font-family using Open Sans to the body
/* openSansObserver.load().then(() => {*/
  /* document.body.classList.add('fontLoaded');*/
  /* }, () => {*/
  /* document.body.classList.remove('fontLoaded');*/
  /* });*/

// Create redux store with history
// this uses the singleton browserHistory provided by react-router
// Optionally, this could be changed to leverage a created history
// e.g. `const browserHistory = useRouterHistory(createBrowserHistory)();`
const initialState = {};
const store = configureStore(initialState, browserHistory);

// Sync history and store, as the react-router-redux reducer
// is under the non-default key ("routing"), selectLocationState
// must be provided for resolving how to retrieve the "route" in the state
const history = syncHistoryWithStore(browserHistory, store, {
  selectLocationState: makeSelectLocationState(),
});

// Set up the router, wrapping all Routes in the App component
const rootRoute = {
  component: App,
  childRoutes: createRoutes(store),
};

ReactDOM.render(
  <Provider store={store}>
    <Router
      history={history}
      render={
        // Scroll to top when going to a new page, imitating default browser
        // behaviour
        applyRouterMiddleware(useScroll())
      }
      routes={rootRoute}
    />
  </Provider>,
  document.getElementById('app')
);

// Install ServiceWorker and AppCache in the end since
// it's not most important operation and if main code fails,
// we do not want it installed
if (process.env.NODE_ENV === 'production') {
  require('offline-plugin/runtime').install(); // eslint-disable-line global-require
}
<commit_msg>refactor(react-router-scroll): Import only useScroll<commit_after>/**
 * app.js
 *
 * This is the entry file for the application, only setup and boilerplate
 * code.
 */

// Needed for redux-saga es6 generator support
import 'babel-polyfill';
// Import all the third party stuff
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import useScroll from 'react-router-scroll/lib/useScroll';
import { applyRouterMiddleware, Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

/* eslint-disable import/no-unresolved, import/extensions */
// Load the favicon, the manifest.json file and the .htaccess file
import '!file-loader?name=[name].[ext]!./favicon.ico';
import '!file-loader?name=[name].[ext]!./manifest.json';
import 'file-loader?name=[name].[ext]!./.htaccess';
/* eslint-enable import/no-unresolved, import/extensions */

import { makeSelectLocationState } from 'containers/App/selectors';
import App from 'containers/App';
import 'sanitize.css/sanitize.css';

import createRoutes from './routes';

/* import FontFaceObserver from 'fontfaceobserver';*/
import configureStore from './store';

// Import CSS reset and Global Styles
import './global-styles';

// Observe loading of Open Sans (to remove open sans, remove the <link> tag in
// the index.html file and this observer)
/* import styles from 'containers/App/styles.css';*/
/* const openSansObserver = new FontFaceObserver('Open Sans', {});*/

// When Open Sans is loaded, add a font-family using Open Sans to the body
/* openSansObserver.load().then(() => {*/
  /* document.body.classList.add('fontLoaded');*/
  /* }, () => {*/
  /* document.body.classList.remove('fontLoaded');*/
  /* });*/

// Create redux store with history
// this uses the singleton browserHistory provided by react-router
// Optionally, this could be changed to leverage a created history
// e.g. `const browserHistory = useRouterHistory(createBrowserHistory)();`
const initialState = {};
const store = configureStore(initialState, browserHistory);

// Sync history and store, as the react-router-redux reducer
// is under the non-default key ("routing"), selectLocationState
// must be provided for resolving how to retrieve the "route" in the state
const history = syncHistoryWithStore(browserHistory, store, {
  selectLocationState: makeSelectLocationState(),
});

// Set up the router, wrapping all Routes in the App component
const rootRoute = {
  component: App,
  childRoutes: createRoutes(store),
};

ReactDOM.render(
  <Provider store={store}>
    <Router
      history={history}
      render={
        // Scroll to top when going to a new page, imitating default browser
        // behaviour
        applyRouterMiddleware(useScroll())
      }
      routes={rootRoute}
    />
  </Provider>,
  document.getElementById('app')
);

// Install ServiceWorker and AppCache in the end since
// it's not most important operation and if main code fails,
// we do not want it installed
if (process.env.NODE_ENV === 'production') {
  require('offline-plugin/runtime').install(); // eslint-disable-line global-require
}
<|endoftext|>


<commit_before>var buster = require("buster-node");

buster.testRunner.onCreate(function (runner) {
    runner.on("suite:end", function (results) {
        process.exit(results.ok ? 0 : 1);
    });
});

//require("./test/progress-reporter-integration-test");
require("./test/run-analyzer-test");
require("./test/test-cli-test");
require("./test/runners/node-test");
//require("./test/runners/browser-test");
//require("./test/runners/browser/progress-reporter-test");
require("./test/runners/browser/remote-runner-test");
<commit_msg>Make sure errors get reported<commit_after>var buster = require("buster-node");

buster.testRunner.onCreate(function (runner) {
    runner.on("suite:end", function (results) {
        process.nextTick(function () {
            process.exit(results.ok ? 0 : 1);
        });
    });
});

//require("./test/progress-reporter-integration-test");
require("./test/run-analyzer-test");
require("./test/test-cli-test");
require("./test/runners/node-test");
//require("./test/runners/browser-test");
//require("./test/runners/browser/progress-reporter-test");
require("./test/runners/browser/remote-runner-test");
<|endoftext|>


<commit_before>"use strict";

/*  ---------------------------------------------------------------------------

    A tests launcher. Runs tests for all languages and all exchanges, in
    parallel, with a humanized error reporting.

    Usage: node run-tests [--php] [--js] [--python] [--python-async] [exchange] [symbol]

    --------------------------------------------------------------------------- */

const fs = require ('fs')
const log = require ('ololog')//.configure ({ indent: { pattern: '  ' }})
const ansi = require ('ansicolor').nice

/*  --------------------------------------------------------------------------- */

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

/*  --------------------------------------------------------------------------- */

const [,, ...args] = process.argv

const keys = {

    '--js': false,      // run JavaScript tests only
    '--php': false,     // run PHP tests only
    '--python': false,  // run Python 3 tests only
    '--python-async': false, // run Python 3 async tests only
}

let exchanges = []
let symbol = 'all'
let maxConcurrency = 5 // Number.MAX_VALUE // no limit

for (const arg of args) {
    if (arg.startsWith ('--'))               { keys[arg] = true }
    else if (arg.includes ('/'))             { symbol = arg }
    else if (Number.isFinite (Number (arg))) { maxConcurrency = Number (arg) }
    else                                     { exchanges.push (arg) }
}

/*  --------------------------------------------------------------------------- */

if (!exchanges.length) {

    if (!fs.existsSync ('./exchanges.json')) {

        log.bright.red ('\n\tNo', 'exchanges.json'.white, 'found, please run', 'npm run build'.white, 'to generate it!\n')
        process.exit (1)
    }

    exchanges = require ('./exchanges.json').ids
}

/*  --------------------------------------------------------------------------- */

const sleep = s => new Promise (resolve => setTimeout (resolve, s*1000))
const timeout = (s, promise) => Promise.race ([ promise, sleep (s).then (() => { throw new Error ('timed out') }) ])

/*  --------------------------------------------------------------------------- */

const exec = (bin, ...args) =>

/*  A custom version of child_process.exec that captures both stdout and
    stderr,  not separating them into distinct buffers — so that we can show
    the same output as if it were running in a terminal.                        */

    timeout (120, new Promise (return_ => {

        const ps = require ('child_process').spawn (bin, args)

        let output = ''
        let stderr = ''
        let hasWarnings = false

        ps.stdout.on ('data', data => { output += data.toString () })
        ps.stderr.on ('data', data => { output += data.toString (); stderr += data.toString (); hasWarnings = true })

        ps.on ('exit', code => {

            output = ansi.strip (output.trim ())
            stderr = ansi.strip (stderr)

            const regex = /\[[a-z]+?\]/gmi

            let match = undefined
            const warnings = []

            match = regex.exec (output)

            if (match) {
                warnings.push (match[0])
                do {
                    if (match = regex.exec (output)) {
                        warnings.push (match[0])
                    }
                } while (match);
            }

            return_ ({
                failed: code !== 0,
                output,
                hasOutput: output.length > 0,
                hasWarnings: hasWarnings || warnings.length > 0,
                warnings: warnings,
            })
        })

    })).catch (e => ({

        failed: true,
        output: e.message

    })).then (x => Object.assign (x, { hasOutput: x.output.length > 0 }))

/*  ------------------------------------------------------------------------ */

// const execWithRetry = () => {

//     // Sometimes execution (on a remote CI server) is just fails with no
//     // apparent reason, leaving an empty stdout/stderr behind. I suspect
//     // it's related to out-of-memory errors. So in that case we will re-try
//     // until it eventually finalizes.
// }

/*  ------------------------------------------------------------------------ */

let numExchangesTested = 0

/*  Tests of different languages for the same exchange should be run
    sequentially to prevent the interleaving nonces problem.
    ------------------------------------------------------------------------ */

const sequentialMap = async (input, fn) => {

    const result = []
    for (const item of input) { result.push (await fn (item)) }
    return result
}

/*  ------------------------------------------------------------------------ */

const testExchange = async (exchange) => {

/*  Run tests for all/selected languages (in parallel)     */

    const args = [exchange, ...symbol === 'all' ? [] : symbol]
        , allTests = [

            { language: 'JavaScript',     key: '--js',           exec: ['node',      'js/test/test.js',           ...args] },
            { language: 'Python 3',       key: '--python',       exec: ['python3',   'python/test/test.py',       ...args] },
            { language: 'Python 3 Async', key: '--python-async', exec: ['python3',   'python/test/test_async.py', ...args] },
            { language: 'PHP',            key: '--php',          exec: ['php', '-f', 'php/test/test.php',         ...args] }
        ]
        , selectedTests  = allTests.filter (t => keys[t.key])
        , scheduledTests = selectedTests.length ? selectedTests : allTests
        , completeTests  = await sequentialMap (scheduledTests, async test => Object.assign (test, await exec (...test.exec)))
        , failed         = completeTests.find (test => test.failed)
        , hasWarnings    = completeTests.find (test => test.hasWarnings)
        , warnings       = completeTests.reduce ((total, { warnings }) => total.concat (warnings), [])

/*  Print interactive log output    */

    numExchangesTested++

    const percentsDone = ((numExchangesTested / exchanges.length) * 100).toFixed (0) + '%'

    log.bright (('[' + percentsDone + ']').dim, 'Testing', exchange.cyan, (failed      ? 'FAIL'.red :
                                                                          (hasWarnings ? (warnings.length ? warnings.join (' ') : 'WARN').yellow
                                                                                : 'OK'.green)))

/*  Return collected data to main loop     */

    return {

        exchange,
        failed,
        hasWarnings,
        explain () {
            for (const { language, failed, output, hasWarnings } of completeTests) {
                if (failed || hasWarnings) {

                    if (!failed && output.indexOf('[Skipped]') >= 0)
                        continue;

                    if (failed) { log.bright ('\nFAILED'.bgBrightRed.white, exchange.red,    '(' + language + '):\n') }
                    else        { log.bright ('\nWARN'.yellow.inverse,      exchange.yellow, '(' + language + '):\n') }

                    log.indent (1) (output)
                }
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

function TaskPool (maxConcurrency) {

    const pending = []
        , queue   = []

    let numActive = 0

    return {

        pending,

        run (task) {

            if (numActive >= maxConcurrency) { // queue task

                return new Promise (resolve => queue.push (() => this.run (task).then (resolve)))

            } else { // execute task

                let p = task ().then (x => {
                    numActive--
                    return (queue.length && (numActive < maxConcurrency))
                                ? queue.shift () ().then (() => x)
                                : x
                })
                numActive++
                pending.push (p)
                return p
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

async function testAllExchanges () {

    const taskPool = TaskPool (maxConcurrency)
    const results = []

    for (const exchange of exchanges) {
        taskPool.run (() => testExchange (exchange).then (x => results.push (x)))
    }

    await Promise.all (taskPool.pending)

    return results
}

/*  ------------------------------------------------------------------------ */

(async function () {

    log.bright.magenta.noPretty ('Testing'.white, Object.assign (
                                                            { exchanges, symbol, keys },
                                                            maxConcurrency >= Number.MAX_VALUE ? {} : { maxConcurrency }))

    const tested    = await testAllExchanges ()
        , warnings  = tested.filter (t => !t.failed && t.hasWarnings)
        , failed    = tested.filter (t =>  t.failed)
        , succeeded = tested.filter (t => !t.failed && !t.hasWarnings)

    log.newline ()

    warnings.forEach (t => t.explain ())
    failed.forEach (t => t.explain ())

    log.newline ()

    if (failed.length)   { log.noPretty.bright.red    ('FAIL'.bgBrightRed.white, failed.map (t => t.exchange)) }
    if (warnings.length) { log.noPretty.bright.yellow ('WARN'.inverse,           warnings.map (t => t.exchange)) }

    log.newline ()

    log.bright ('All done,', [failed.length    && (failed.length    + ' failed')   .red,
                              succeeded.length && (succeeded.length + ' succeeded').green,
                              warnings.length  && (warnings.length  + ' warnings') .yellow].filter (s => s).join (', '))

    if (failed.length) {

        await sleep (10) // to fight TravisCI log truncation issue, see https://github.com/travis-ci/travis-ci/issues/8189
        process.exit (1)

    } else {
        process.exit (0)
    }

}) ();

/*  ------------------------------------------------------------------------ */
<commit_msg>add php-async to run tests<commit_after>"use strict";

/*  ---------------------------------------------------------------------------

    A tests launcher. Runs tests for all languages and all exchanges, in
    parallel, with a humanized error reporting.

    Usage: node run-tests [--php] [--js] [--python] [--python-async] [exchange] [symbol]

    --------------------------------------------------------------------------- */

const fs = require ('fs')
const log = require ('ololog')//.configure ({ indent: { pattern: '  ' }})
const ansi = require ('ansicolor').nice

/*  --------------------------------------------------------------------------- */

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

/*  --------------------------------------------------------------------------- */

const [,, ...args] = process.argv

const keys = {

    '--js': false,      // run JavaScript tests only
    '--php': false,     // run PHP tests only
    '--python': false,  // run Python 3 tests only
    '--python-async': false, // run Python 3 async tests only
    '--php-async': false,    // run php async tests only
}

let exchanges = []
let symbol = 'all'
let maxConcurrency = 5 // Number.MAX_VALUE // no limit

for (const arg of args) {
    if (arg.startsWith ('--'))               { keys[arg] = true }
    else if (arg.includes ('/'))             { symbol = arg }
    else if (Number.isFinite (Number (arg))) { maxConcurrency = Number (arg) }
    else                                     { exchanges.push (arg) }
}

/*  --------------------------------------------------------------------------- */

if (!exchanges.length) {

    if (!fs.existsSync ('./exchanges.json')) {

        log.bright.red ('\n\tNo', 'exchanges.json'.white, 'found, please run', 'npm run build'.white, 'to generate it!\n')
        process.exit (1)
    }

    exchanges = require ('./exchanges.json').ids
}

/*  --------------------------------------------------------------------------- */

const sleep = s => new Promise (resolve => setTimeout (resolve, s*1000))
const timeout = (s, promise) => Promise.race ([ promise, sleep (s).then (() => { throw new Error ('timed out') }) ])

/*  --------------------------------------------------------------------------- */

const exec = (bin, ...args) =>

/*  A custom version of child_process.exec that captures both stdout and
    stderr,  not separating them into distinct buffers — so that we can show
    the same output as if it were running in a terminal.                        */

    timeout (120, new Promise (return_ => {

        const ps = require ('child_process').spawn (bin, args)

        let output = ''
        let stderr = ''
        let hasWarnings = false

        ps.stdout.on ('data', data => { output += data.toString () })
        ps.stderr.on ('data', data => { output += data.toString (); stderr += data.toString (); hasWarnings = true })

        ps.on ('exit', code => {

            output = ansi.strip (output.trim ())
            stderr = ansi.strip (stderr)

            const regex = /\[[a-z]+?\]/gmi

            let match = undefined
            const warnings = []

            match = regex.exec (output)

            if (match) {
                warnings.push (match[0])
                do {
                    if (match = regex.exec (output)) {
                        warnings.push (match[0])
                    }
                } while (match);
            }

            return_ ({
                failed: code !== 0,
                output,
                hasOutput: output.length > 0,
                hasWarnings: hasWarnings || warnings.length > 0,
                warnings: warnings,
            })
        })

    })).catch (e => ({

        failed: true,
        output: e.message

    })).then (x => Object.assign (x, { hasOutput: x.output.length > 0 }))

/*  ------------------------------------------------------------------------ */

// const execWithRetry = () => {

//     // Sometimes execution (on a remote CI server) is just fails with no
//     // apparent reason, leaving an empty stdout/stderr behind. I suspect
//     // it's related to out-of-memory errors. So in that case we will re-try
//     // until it eventually finalizes.
// }

/*  ------------------------------------------------------------------------ */

let numExchangesTested = 0

/*  Tests of different languages for the same exchange should be run
    sequentially to prevent the interleaving nonces problem.
    ------------------------------------------------------------------------ */

const sequentialMap = async (input, fn) => {

    const result = []
    for (const item of input) { result.push (await fn (item)) }
    return result
}

/*  ------------------------------------------------------------------------ */

const testExchange = async (exchange) => {

/*  Run tests for all/selected languages (in parallel)     */

    const args = [exchange, ...symbol === 'all' ? [] : symbol]
        , allTests = [

            { language: 'JavaScript',     key: '--js',           exec: ['node',      'js/test/test.js',           ...args] },
            { language: 'Python 3',       key: '--python',       exec: ['python3',   'python/test/test.py',       ...args] },
            { language: 'Python 3 Async', key: '--python-async', exec: ['python3',   'python/test/test_async.py', ...args] },
            { language: 'PHP',            key: '--php',          exec: ['php', '-f', 'php/test/test.php',         ...args] },
            { language: 'PHP Async',      key: '--php-async',    exec: ['php', '-f', 'php/test/test_async.php',   ...args] },
        ]
        , selectedTests  = allTests.filter (t => keys[t.key])
        , scheduledTests = selectedTests.length ? selectedTests : allTests
        , completeTests  = await sequentialMap (scheduledTests, async test => Object.assign (test, await exec (...test.exec)))
        , failed         = completeTests.find (test => test.failed)
        , hasWarnings    = completeTests.find (test => test.hasWarnings)
        , warnings       = completeTests.reduce ((total, { warnings }) => total.concat (warnings), [])

/*  Print interactive log output    */

    numExchangesTested++

    const percentsDone = ((numExchangesTested / exchanges.length) * 100).toFixed (0) + '%'

    log.bright (('[' + percentsDone + ']').dim, 'Testing', exchange.cyan, (failed      ? 'FAIL'.red :
                                                                          (hasWarnings ? (warnings.length ? warnings.join (' ') : 'WARN').yellow
                                                                                : 'OK'.green)))

/*  Return collected data to main loop     */

    return {

        exchange,
        failed,
        hasWarnings,
        explain () {
            for (const { language, failed, output, hasWarnings } of completeTests) {
                if (failed || hasWarnings) {

                    if (!failed && output.indexOf('[Skipped]') >= 0)
                        continue;

                    if (failed) { log.bright ('\nFAILED'.bgBrightRed.white, exchange.red,    '(' + language + '):\n') }
                    else        { log.bright ('\nWARN'.yellow.inverse,      exchange.yellow, '(' + language + '):\n') }

                    log.indent (1) (output)
                }
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

function TaskPool (maxConcurrency) {

    const pending = []
        , queue   = []

    let numActive = 0

    return {

        pending,

        run (task) {

            if (numActive >= maxConcurrency) { // queue task

                return new Promise (resolve => queue.push (() => this.run (task).then (resolve)))

            } else { // execute task

                let p = task ().then (x => {
                    numActive--
                    return (queue.length && (numActive < maxConcurrency))
                                ? queue.shift () ().then (() => x)
                                : x
                })
                numActive++
                pending.push (p)
                return p
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

async function testAllExchanges () {

    const taskPool = TaskPool (maxConcurrency)
    const results = []

    for (const exchange of exchanges) {
        taskPool.run (() => testExchange (exchange).then (x => results.push (x)))
    }

    await Promise.all (taskPool.pending)

    return results
}

/*  ------------------------------------------------------------------------ */

(async function () {

    log.bright.magenta.noPretty ('Testing'.white, Object.assign (
                                                            { exchanges, symbol, keys },
                                                            maxConcurrency >= Number.MAX_VALUE ? {} : { maxConcurrency }))

    const tested    = await testAllExchanges ()
        , warnings  = tested.filter (t => !t.failed && t.hasWarnings)
        , failed    = tested.filter (t =>  t.failed)
        , succeeded = tested.filter (t => !t.failed && !t.hasWarnings)

    log.newline ()

    warnings.forEach (t => t.explain ())
    failed.forEach (t => t.explain ())

    log.newline ()

    if (failed.length)   { log.noPretty.bright.red    ('FAIL'.bgBrightRed.white, failed.map (t => t.exchange)) }
    if (warnings.length) { log.noPretty.bright.yellow ('WARN'.inverse,           warnings.map (t => t.exchange)) }

    log.newline ()

    log.bright ('All done,', [failed.length    && (failed.length    + ' failed')   .red,
                              succeeded.length && (succeeded.length + ' succeeded').green,
                              warnings.length  && (warnings.length  + ' warnings') .yellow].filter (s => s).join (', '))

    if (failed.length) {

        await sleep (10) // to fight TravisCI log truncation issue, see https://github.com/travis-ci/travis-ci/issues/8189
        process.exit (1)

    } else {
        process.exit (0)
    }

}) ();

/*  ------------------------------------------------------------------------ */
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

var fs = require("fs-extra");
var path = require("path");
var utils = require("../utils");
var settings = require("../../lib/settings");
var chai = require("chai");
var expect = chai.expect;
var exec = utils.exec;

describe("jpm init", function () {
  beforeEach(utils.setup);
  afterEach(utils.tearDown);

  it("creates package.json with defaults", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();

    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.title).to.be.equal("My Jetpack Addon");
      expect(manifest.name).to.be.equal("tmp");
      expect(manifest.version).to.be.equal("0.0.1");
      expect(manifest.description).to.be.equal("");
      expect(manifest.main).to.be.equal("index.js");
      expect(manifest.author).to.be.equal("");
      expect(manifest.engines.firefox).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.engines.fennec).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.license).to.be.equal("MIT");
      done();
    });
  });

  it("creates package.json with custom entries", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = [
      'My Custom Name',
      'my-addon',
      '1.0.0',
      'A description',
      'lib/index.js',
      'Jordan Santell',
      'custom-firefox, nightly-firefox',
      'BSD',
      'yes'
    ];

    var proc = respond(exec("init"), responses.map(function (val) {
      return val + '\n';
    }));
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.title).to.be.equal(responses[0]);
      expect(manifest.name).to.be.equal(responses[1]);
      expect(manifest.version).to.be.equal(responses[2]);
      expect(manifest.description).to.be.equal(responses[3]);
      expect(manifest.main).to.be.equal(responses[4]);
      expect(manifest.author).to.be.equal(responses[5]);
      expect(manifest.engines['custom-firefox']).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.engines['nightly-firefox']).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.license).to.be.equal(responses[7]);
      done();
    });
  });

  it("sanitizes entries", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    responses[1] = "  an invalid $ _ name 123\n";
    responses[2] = "invalid version\n";
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.name).to.be.equal("aninvalidname123");
      expect(manifest.version).to.be.equal("0.0.0");
      done();
    });
  });

  it("copies in default index.js if it DNE", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "index.js"), "utf-8");
      var sourceIndex = fs.readFileSync(path.join("..", "..", "data", "index.js"), "utf-8");
      expect(dirIndex).to.be.equal(sourceIndex);
      done();
    });
  });

  it("does not copy in default index.js if it exists", function (done) {
    process.chdir(utils.tmpOutputDir);
    fs.writeFileSync(path.join(utils.tmpOutputDir, "index.js"), "hello");
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "index.js"), "utf-8");
      expect(dirIndex).to.be.equal("hello");
      done();
    });
  });

  it("copies in default README.md if it DNE", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "README.md"), "utf-8");
      var sourceIndex = fs.readFileSync(path.join("..", "..", "data", "README.md"), "utf-8");
      expect(dirIndex).to.be.equal(sourceIndex);
      done();
    });
  });

  it("does not copy in default README.md if it exists", function (done) {
    process.chdir(utils.tmpOutputDir);
    fs.writeFileSync(path.join(utils.tmpOutputDir, "README.md"), "readme!");
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "README.md"), "utf-8");
      expect(dirIndex).to.be.equal("readme!");
      done();
    });
  });

  it("copies in default test-index.js if it DNE", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirTest = fs.readFileSync(path.join(utils.tmpOutputDir, "test", "test-index.js"), "utf-8");
      var sourceTest = fs.readFileSync(path.join("..", "..", "data", "test-index.js"), "utf-8");
      expect(dirTest).to.be.equal(sourceTest);
      done();
    });
  });

  it("does not copy in default test-index.js if it exists", function (done) {
    process.chdir(utils.tmpOutputDir);
    fs.mkdirpSync(path.join(utils.tmpOutputDir, "test"));
    fs.writeFileSync(path.join(utils.tmpOutputDir, "test", "test-index.js"), "hello");
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirTest = fs.readFileSync(path.join(utils.tmpOutputDir, "test", "test-index.js"), "utf-8");
      expect(dirTest).to.be.equal("hello");
      done();
    });
  });

  it("allows non-numeric version strings", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = ["", "", "v0.4.0-rc4", "", "", "", "", "", "yes"];

    var proc = respond(exec("init"), responses.map(function (val) {
      return val + '\n';
    }));
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.version).to.be.equal("0.4.0-rc4");
      done();
    });
  });
});

/**
 * Takes a process and array of strings. Everytime stdout emits its
 * data event, the helper writes to stdin in order of the strings array.
 * Also takes an optional function to respond to every stdout `data`
 * event before writing to stdin.
 *
 * @param {Object} proc
 * @param {Array} responses
 * @param {Function} fn
 * @return {Object}
 */

function respond (proc, responses, fn) {
  var count = 0;
  proc.stdout.on("data", sendResponse);
  function sendResponse (data) {
    if (fn)
      fn(data);
    proc.stdin.write(responses[count++], "utf-8");

    if (count > responses.length) {
      proc.stdout.off("data", sendResponse);
      proc.stdin.end();
    }
  }
  return proc;
}

// Create 8 empty responses and a "yes"
function generateResponses () {
  var responses = Array(9).join("\n").split("");
  responses.push("yes\n");
  return responses;
}
<commit_msg>jpm init defaults test, updated addon description<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

var fs = require("fs-extra");
var path = require("path");
var utils = require("../utils");
var settings = require("../../lib/settings");
var chai = require("chai");
var expect = chai.expect;
var exec = utils.exec;

describe("jpm init", function () {
  beforeEach(utils.setup);
  afterEach(utils.tearDown);

  it("creates package.json with defaults", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();

    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.title).to.be.equal("My Jetpack Addon");
      expect(manifest.name).to.be.equal("tmp");
      expect(manifest.version).to.be.equal("0.0.1");
      expect(manifest.description).to.be.equal("A basic add-on");
      expect(manifest.main).to.be.equal("index.js");
      expect(manifest.author).to.be.equal("");
      expect(manifest.engines.firefox).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.engines.fennec).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.license).to.be.equal("MIT");
      done();
    });
  });

  it("creates package.json with custom entries", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = [
      'My Custom Name',
      'my-addon',
      '1.0.0',
      'A description',
      'lib/index.js',
      'Jordan Santell',
      'custom-firefox, nightly-firefox',
      'BSD',
      'yes'
    ];

    var proc = respond(exec("init"), responses.map(function (val) {
      return val + '\n';
    }));
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.title).to.be.equal(responses[0]);
      expect(manifest.name).to.be.equal(responses[1]);
      expect(manifest.version).to.be.equal(responses[2]);
      expect(manifest.description).to.be.equal(responses[3]);
      expect(manifest.main).to.be.equal(responses[4]);
      expect(manifest.author).to.be.equal(responses[5]);
      expect(manifest.engines['custom-firefox']).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.engines['nightly-firefox']).to.be.equal(
        ">=" + settings.MIN_VERSION);
      expect(manifest.license).to.be.equal(responses[7]);
      done();
    });
  });

  it("sanitizes entries", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    responses[1] = "  an invalid $ _ name 123\n";
    responses[2] = "invalid version\n";
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.name).to.be.equal("aninvalidname123");
      expect(manifest.version).to.be.equal("0.0.0");
      done();
    });
  });

  it("copies in default index.js if it DNE", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "index.js"), "utf-8");
      var sourceIndex = fs.readFileSync(path.join("..", "..", "data", "index.js"), "utf-8");
      expect(dirIndex).to.be.equal(sourceIndex);
      done();
    });
  });

  it("does not copy in default index.js if it exists", function (done) {
    process.chdir(utils.tmpOutputDir);
    fs.writeFileSync(path.join(utils.tmpOutputDir, "index.js"), "hello");
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "index.js"), "utf-8");
      expect(dirIndex).to.be.equal("hello");
      done();
    });
  });

  it("copies in default README.md if it DNE", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "README.md"), "utf-8");
      var sourceIndex = fs.readFileSync(path.join("..", "..", "data", "README.md"), "utf-8");
      expect(dirIndex).to.be.equal(sourceIndex);
      done();
    });
  });

  it("does not copy in default README.md if it exists", function (done) {
    process.chdir(utils.tmpOutputDir);
    fs.writeFileSync(path.join(utils.tmpOutputDir, "README.md"), "readme!");
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirIndex = fs.readFileSync(path.join(utils.tmpOutputDir, "README.md"), "utf-8");
      expect(dirIndex).to.be.equal("readme!");
      done();
    });
  });

  it("copies in default test-index.js if it DNE", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirTest = fs.readFileSync(path.join(utils.tmpOutputDir, "test", "test-index.js"), "utf-8");
      var sourceTest = fs.readFileSync(path.join("..", "..", "data", "test-index.js"), "utf-8");
      expect(dirTest).to.be.equal(sourceTest);
      done();
    });
  });

  it("does not copy in default test-index.js if it exists", function (done) {
    process.chdir(utils.tmpOutputDir);
    fs.mkdirpSync(path.join(utils.tmpOutputDir, "test"));
    fs.writeFileSync(path.join(utils.tmpOutputDir, "test", "test-index.js"), "hello");
    var responses = generateResponses();
    var proc = respond(exec("init"), responses);
    proc.on("close", function () {
      var dirTest = fs.readFileSync(path.join(utils.tmpOutputDir, "test", "test-index.js"), "utf-8");
      expect(dirTest).to.be.equal("hello");
      done();
    });
  });

  it("allows non-numeric version strings", function (done) {
    process.chdir(utils.tmpOutputDir);
    var responses = ["", "", "v0.4.0-rc4", "", "", "", "", "", "yes"];

    var proc = respond(exec("init"), responses.map(function (val) {
      return val + '\n';
    }));
    proc.on("close", function () {
      var manifest = JSON.parse(fs.readFileSync(path.join(utils.tmpOutputDir, "package.json"), "utf-8"));
      expect(manifest.version).to.be.equal("0.4.0-rc4");
      done();
    });
  });
});

/**
 * Takes a process and array of strings. Everytime stdout emits its
 * data event, the helper writes to stdin in order of the strings array.
 * Also takes an optional function to respond to every stdout `data`
 * event before writing to stdin.
 *
 * @param {Object} proc
 * @param {Array} responses
 * @param {Function} fn
 * @return {Object}
 */

function respond (proc, responses, fn) {
  var count = 0;
  proc.stdout.on("data", sendResponse);
  function sendResponse (data) {
    if (fn)
      fn(data);
    proc.stdin.write(responses[count++], "utf-8");

    if (count > responses.length) {
      proc.stdout.off("data", sendResponse);
      proc.stdin.end();
    }
  }
  return proc;
}

// Create 8 empty responses and a "yes"
function generateResponses () {
  var responses = Array(9).join("\n").split("");
  responses.push("yes\n");
  return responses;
}
<|endoftext|>


<commit_before>var GameRoomService = require('../gameRoomService');
var server = require('../server');
var chai = require('chai');
var chaiAsPromised = require("chai-as-promised");
var should = chai.should();

chai.use(chaiAsPromised);

describe('GameRoomService', function(){

    after(function() {
	server.restifyServer.close();
	server.redisClient.quit();
    });

    afterEach(function() {
	server.redisClient.flushdb();
    });

    describe('serialize', function(){
	it('should serialize a gameRoom object so it can be saved in a redis db', function(){
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    gameRoomService.serialize(testGameRoom).should.be.a('object');
	    gameRoomService.serialize(testGameRoom).should.have.property('code').equal('number');
	    gameRoomService.serialize(testGameRoom).should.have.property('creator').equal('mike');
	    gameRoomService.serialize(testGameRoom).should.have.property('players');
	    gameRoomService.serialize(testGameRoom).players.should.be.a('string').equal('["mike"]');
	});
    });

    describe('parse', function() {
	it('should parse a serialized gameRoom', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: '["mike"]'};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    gameRoomService.parse(testGameRoom).should.be.a('object');
	    gameRoomService.parse(testGameRoom).should.have.property('code').equal('number');
	    gameRoomService.parse(testGameRoom).should.have.property('creator').equal('mike');
	    gameRoomService.parse(testGameRoom).should.have.property('players');
	    gameRoomService.parse(testGameRoom).players.should.be.a('array').eql(['mike']);
	});
    });

    describe('save', function() {
	it('should return "OK" when it is successful', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    var test = gameRoomService.save(testGameRoom);
	    return test.should.eventually.be.a('string').equal('OK');
	});

	it('should save a game room and all its properties to redis when a game is created', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    gameRoomService.save(testGameRoom);
	    var test = server.redisClient.keysAsync('number');
	    return test.should.eventually.be.a('array').eql(['number']);
	});

    });

    describe('update', function() {
	it('should return the updated game room when it is successful', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'tike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom)
		.then(function() {
		    var test = gameRoomService.update('number', newPlayer);
		    test.should.eventually.be.a('object')
			.and.should.eventually.have.property('players').equal('["mike","wike","tike"]');
		});
	});
    });

    describe('validateCode', () => {
	it('should validate a code with if the room exists', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateCode('number');
		test.should.eventually.be.a('object')
		    .and.should.eventually.include({creator: 'mike'})
		    .and.should.eventually.have.property('players').equal('["mike","wike"]');
	    });
	});

	it('should not validate a room when if the room does not exist', () => {
	    var gameRoomService = new GameRoomService(server.redisClient);
	    var test = gameRoomService.validateCode('invalidcode');
	    test.should.eventually.be.rejectedWith('invalid code');
	});
    });

    describe('validateUsername', () => {
	it('should not validate a username with if the room exists and the name is in use', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'mike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateUsername('number', newPlayer);
		test.should.eventually.be.a('string').equal('name already in use');
	    });
	});

	it('should validate a username with if the room exists and the name is not in use', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'tike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateUsername('number', newPlayer);
		test.should.eventually.be.a('string').equal('true');
	    });
	});

	it('should validate a username with if the room does not exist', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'mike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateUsername('invalidcode', newPlayer);
		test.should.eventually.be.rejectedWith('invalid code');
	    });
	});
    });
});
<commit_msg>update mocha tests so they can run together<commit_after>var GameRoomService = require('../gameRoomService');
var server = require('../server');
var chai = require('chai');
var chaiAsPromised = require("chai-as-promised");
var should = chai.should();

chai.use(chaiAsPromised);

describe('GameRoomService', function(){

    after(function() {
	server.restifyServer.close();
	//server.redisClient.quit();
    });

    afterEach(function() {
	server.redisClient.flushdb();
    });

    describe('serialize', function(){
	it('should serialize a gameRoom object so it can be saved in a redis db', function(){
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    gameRoomService.serialize(testGameRoom).should.be.a('object');
	    gameRoomService.serialize(testGameRoom).should.have.property('code').equal('number');
	    gameRoomService.serialize(testGameRoom).should.have.property('creator').equal('mike');
	    gameRoomService.serialize(testGameRoom).should.have.property('players');
	    gameRoomService.serialize(testGameRoom).players.should.be.a('string').equal('["mike"]');
	});
    });

    describe('parse', function() {
	it('should parse a serialized gameRoom', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: '["mike"]'};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    gameRoomService.parse(testGameRoom).should.be.a('object');
	    gameRoomService.parse(testGameRoom).should.have.property('code').equal('number');
	    gameRoomService.parse(testGameRoom).should.have.property('creator').equal('mike');
	    gameRoomService.parse(testGameRoom).should.have.property('players');
	    gameRoomService.parse(testGameRoom).players.should.be.a('array').eql(['mike']);
	});
    });

    describe('save', function() {
	it('should return "OK" when it is successful', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    var test = gameRoomService.save(testGameRoom);
	    return test.should.eventually.be.a('string').equal('OK');
	});

	it('should save a game room and all its properties to redis when a game is created', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    gameRoomService.save(testGameRoom);
	    var test = server.redisClient.keysAsync('number');
	    return test.should.eventually.be.a('array').eql(['number']);
	});

    });

    describe('update', function() {
	it('should return the updated game room when it is successful', function() {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'tike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom)
		.then(function() {
		    var test = gameRoomService.update('number', newPlayer);
		    test.should.eventually.be.a('object')
			.and.should.eventually.have.property('players').equal('["mike","wike","tike"]');
		});
	});
    });

    describe('validateCode', () => {
	it('should validate a code with if the room exists', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateCode('number');
		test.should.eventually.be.a('object')
		    .and.should.eventually.include({creator: 'mike'})
		    .and.should.eventually.have.property('players').equal('["mike","wike"]');
	    });
	});

	it('should not validate a room when if the room does not exist', () => {
	    var gameRoomService = new GameRoomService(server.redisClient);
	    var test = gameRoomService.validateCode('invalidcode');
	    test.should.eventually.be.rejectedWith('invalid code');
	});
    });

    describe('validateUsername', () => {
	it('should not validate a username with if the room exists and the name is in use', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'mike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateUsername('number', newPlayer);
		test.should.eventually.be.a('string').equal('name already in use');
	    });
	});

	it('should validate a username with if the room exists and the name is not in use', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'tike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateUsername('number', newPlayer);
		test.should.eventually.be.a('string').equal('true');
	    });
	});

	it('should validate a username with if the room does not exist', () => {
	    var testGameRoom = {code: 'number', creator: 'mike', players: ['mike','wike']};
	    var newPlayer = 'mike';
	    var gameRoomService = new GameRoomService(server.redisClient);
	    return gameRoomService.save(testGameRoom).then(() => {
		var test = gameRoomService.validateUsername('invalidcode', newPlayer);
		test.should.eventually.be.rejectedWith('invalid code');
	    });
	});
    });
});
<|endoftext|>


<commit_before><commit_msg>test: rawValidation<commit_after><|endoftext|>


<commit_before>import {
	assert, fixture, html, aTimeout
} from '@open-wc/testing';

import {
	PolymerElement
} from '@polymer/polymer';

import { hauntedPolymer } from '../lib/haunted-polymer.js';
import { useMemo } from 'haunted';

const useTestHook = element => {
	return useMemo(() => {
		switch (element.mood) {
		case 'happy': return 'not so scared';
		case 'frightened': return 'very scared';
		}
	}, [element.mood]);
};

class MyHauntedPolymer extends hauntedPolymer('scared', useTestHook)(PolymerElement) {
	static get properties() {
		return {
			scared: {
				type: String
			},
			mood: {
				type: String,
				value: 'happy'
			}
		};
	}
}

customElements.define('my-haunted-polymer', MyHauntedPolymer);

suite('haunted polymer', () => {
	let basicFixture;
	setup(async () => {
		basicFixture = await fixture(html`<my-haunted-polymer></my-haunted-polymer>`);
	});
	test('happy start', () => {
		assert.equal(basicFixture.mood, 'happy');
		assert.equal(basicFixture.scared, 'not so scared');
	});
	test('👻', async () => {
		basicFixture.mood = 'frightened';
		await aTimeout(1000);
		assert.equal(basicFixture.scared, 'very scared');
	});
});
<commit_msg>test(haunted-polymer): fix test<commit_after>import {
	assert, fixture, html, nextFrame
} from '@open-wc/testing';

import {
	PolymerElement
} from '@polymer/polymer';

import { hauntedPolymer } from '../lib/haunted-polymer.js';
import { useMemo } from 'haunted';

const useTestHook = element => {
	return useMemo(() => {
		switch (element.mood) {
		case 'happy': return 'not so scared';
		case 'frightened': return 'very scared';
		}
	}, [element.mood]);
};

class MyHauntedPolymer extends hauntedPolymer('scared', useTestHook)(PolymerElement) {
	static get properties() {
		return {
			scared: {
				type: String
			},
			mood: {
				type: String,
				value: 'happy',
				// In order for hauntedPolymer to detect a change, property effects need to be initialized for that specific property.
				// To do this make sure there exists a template binding for that prop or that it is a notifying prop.
				notify: true
			}
		};
	}
}

customElements.define('my-haunted-polymer', MyHauntedPolymer);

suite('haunted polymer', () => {
	let basicFixture;
	setup(async () => {
		basicFixture = await fixture(html`<my-haunted-polymer></my-haunted-polymer>`);
	});
	test('happy start', () => {
		assert.equal(basicFixture.mood, 'happy');
		assert.equal(basicFixture.scared, 'not so scared');
	});
	test('👻', async () => {
		basicFixture.mood = 'frightened';
		await nextFrame();
		assert.equal(basicFixture.scared, 'very scared');
	});
});
<|endoftext|>


<commit_before>define(["Tone/instrument/PolySynth", "helper/Basic", "helper/InstrumentTests", "helper/OutputAudioStereo",
	"Tone/instrument/Instrument", "helper/Test", "helper/OutputAudio", "Tone/instrument/MonoSynth", "helper/Offline",
	"Tone/instrument/Sampler", "Tone/type/Frequency", "helper/CompareToFile"],
function(PolySynth, Basic, InstrumentTests, OutputAudioStereo, Instrument, Test, OutputAudio, MonoSynth, Offline, Sampler, Frequency, CompareToFile){

	describe("PolySynth", function(){

		Basic(PolySynth);
		InstrumentTests(PolySynth, "C4");

		it("matches a file", function(){
			return CompareToFile(function(){
				var synth = new PolySynth(2).toMaster();
				synth.triggerAttackRelease("C4", 0.2, 0);
				synth.triggerAttackRelease("C4", 0.1, 0.1);
				synth.triggerAttackRelease("E4", 0.1, 0.2);
				synth.triggerAttackRelease("E4", 0.1, 0.3);
				synth.triggerAttackRelease("G4", 0.1, 0.4);
				synth.triggerAttackRelease("B4", 0.1, 0.4);
				synth.triggerAttackRelease("C4", 0.2, 0.5);
			}, "polySynth.wav", 0.07);
		});

		it("matches another file", function(){
			return CompareToFile(function(){
				var synth = new PolySynth(4).toMaster();
				synth.triggerAttackRelease(["C4", "E4", "G4", "B4"], 0.2, 0);
				synth.triggerAttackRelease(["C4", "E4", "G4", "B4"], 0.2, 0.3);
			}, "polySynth2.wav", 0.4);
		});

		context("PolySynth Tests", function(){

			it("extends Tone.Instrument", function(){
				var polySynth = new PolySynth();
				expect(polySynth).to.be.an.instanceof(Instrument);
				polySynth.dispose();
			});

			it("can connect the output", function(){
				var polySynth = new PolySynth();
				polySynth.connect(Test);
				polySynth.dispose();
			});

			it("can be trigged with an array of Tone.Frequency", function(){
				return OutputAudio(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
					polySynth.triggerAttackRelease(Frequency("C4").harmonize([0, 2]), 0.1, 0);
				});
			});

			it("triggerAttackRelease can take an array of durations", function(){
				return OutputAudio(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
					polySynth.triggerAttackRelease(["C4", "D4"], [0.1, 0.2]);
				});
			});

			it("triggerAttack and triggerRelease can be invoked without arrays", function(){
				return Offline(function(){
					var polySynth = new PolySynth(2);
					polySynth.set("envelope.release", 0.1);
					polySynth.toMaster();
					polySynth.triggerAttack("C4", 0);
					polySynth.triggerRelease("C4", 0.1);
				}, 0.3).then(function(buffer){
					expect(buffer.getFirstSoundTime()).to.be.closeTo(0, 0.01);
					expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0, 0.01);
				});
			});

			it("can stop all of the currently playing sounds", function(){
				return Offline(function(){
					var polySynth = new PolySynth(4);
					polySynth.set("envelope.release", 0.1);
					polySynth.toMaster();
					polySynth.triggerAttack(["C4", "E4", "G4", "B4"], 0);
					polySynth.releaseAll(0.1);
				}, 0.3).then(function(buffer){
					expect(buffer.getFirstSoundTime()).to.be.closeTo(0, 0.01);
					expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0, 0.01);
				});
			});

			it("is silent before being triggered", function(){
				return Offline(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
				}).then(function(buffer){
					expect(buffer.isSilent()).to.be.true;
				});
			});

			it("can be scheduled to start in the future", function(){
				return Offline(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
					polySynth.triggerAttack("C4", 0.1);
				}, 0.3).then(function(buffer){
					expect(buffer.getFirstSoundTime()).to.be.closeTo(0.1, 0.01);
				});
			});

		});

		context("API", function(){

			it("can be constructed with an options object", function(){
				var polySynth = new PolySynth(4, MonoSynth, {
					"envelope" : {
						"sustain" : 0.3
					}
				});
				expect(polySynth.get().envelope.sustain).to.equal(0.3);
				polySynth.dispose();
			});

			it("throws an error if voice type is not Monophonic", function(){
				expect(function(){
					var polySynth = new PolySynth(4, Sampler);
				}).to.throw(Error);
			});

			it("can be set the detune", function(){
				var polySynth = new PolySynth();
				polySynth.detune.value = -1200;
				expect(polySynth.detune.value).to.equal(-1200);
				polySynth.dispose();
			});

			it("can pass in the volume and detune", function(){
				var polySynth = new PolySynth({
					"volume" : -12,
					"detune" : 120,
				});
				expect(polySynth.volume.value).to.be.closeTo(-12, 0.1);
				expect(polySynth.detune.value).to.be.closeTo(120, 1);
				polySynth.dispose();
			});

			it("can get/set attributes", function(){
				var polySynth = new PolySynth();
				polySynth.set({
					"envelope.decay" : 0.24
				});
				expect(polySynth.get().envelope.decay).to.equal(0.24);
				polySynth.dispose();
			});

		});
	});
});
<commit_msg>expanding threshold<commit_after>define(["Tone/instrument/PolySynth", "helper/Basic", "helper/InstrumentTests", "helper/OutputAudioStereo",
	"Tone/instrument/Instrument", "helper/Test", "helper/OutputAudio", "Tone/instrument/MonoSynth", "helper/Offline",
	"Tone/instrument/Sampler", "Tone/type/Frequency", "helper/CompareToFile"],
function(PolySynth, Basic, InstrumentTests, OutputAudioStereo, Instrument, Test, OutputAudio, MonoSynth, Offline, Sampler, Frequency, CompareToFile){

	describe("PolySynth", function(){

		Basic(PolySynth);
		InstrumentTests(PolySynth, "C4");

		it("matches a file", function(){
			return CompareToFile(function(){
				var synth = new PolySynth(2).toMaster();
				synth.triggerAttackRelease("C4", 0.2, 0);
				synth.triggerAttackRelease("C4", 0.1, 0.1);
				synth.triggerAttackRelease("E4", 0.1, 0.2);
				synth.triggerAttackRelease("E4", 0.1, 0.3);
				synth.triggerAttackRelease("G4", 0.1, 0.4);
				synth.triggerAttackRelease("B4", 0.1, 0.4);
				synth.triggerAttackRelease("C4", 0.2, 0.5);
			}, "polySynth.wav", 0.4);
		});

		it("matches another file", function(){
			return CompareToFile(function(){
				var synth = new PolySynth(4).toMaster();
				synth.triggerAttackRelease(["C4", "E4", "G4", "B4"], 0.2, 0);
				synth.triggerAttackRelease(["C4", "E4", "G4", "B4"], 0.2, 0.3);
			}, "polySynth2.wav", 0.6);
		});

		context("PolySynth Tests", function(){

			it("extends Tone.Instrument", function(){
				var polySynth = new PolySynth();
				expect(polySynth).to.be.an.instanceof(Instrument);
				polySynth.dispose();
			});

			it("can connect the output", function(){
				var polySynth = new PolySynth();
				polySynth.connect(Test);
				polySynth.dispose();
			});

			it("can be trigged with an array of Tone.Frequency", function(){
				return OutputAudio(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
					polySynth.triggerAttackRelease(Frequency("C4").harmonize([0, 2]), 0.1, 0);
				});
			});

			it("triggerAttackRelease can take an array of durations", function(){
				return OutputAudio(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
					polySynth.triggerAttackRelease(["C4", "D4"], [0.1, 0.2]);
				});
			});

			it("triggerAttack and triggerRelease can be invoked without arrays", function(){
				return Offline(function(){
					var polySynth = new PolySynth(2);
					polySynth.set("envelope.release", 0.1);
					polySynth.toMaster();
					polySynth.triggerAttack("C4", 0);
					polySynth.triggerRelease("C4", 0.1);
				}, 0.3).then(function(buffer){
					expect(buffer.getFirstSoundTime()).to.be.closeTo(0, 0.01);
					expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0, 0.01);
				});
			});

			it("can stop all of the currently playing sounds", function(){
				return Offline(function(){
					var polySynth = new PolySynth(4);
					polySynth.set("envelope.release", 0.1);
					polySynth.toMaster();
					polySynth.triggerAttack(["C4", "E4", "G4", "B4"], 0);
					polySynth.releaseAll(0.1);
				}, 0.3).then(function(buffer){
					expect(buffer.getFirstSoundTime()).to.be.closeTo(0, 0.01);
					expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0, 0.01);
				});
			});

			it("is silent before being triggered", function(){
				return Offline(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
				}).then(function(buffer){
					expect(buffer.isSilent()).to.be.true;
				});
			});

			it("can be scheduled to start in the future", function(){
				return Offline(function(){
					var polySynth = new PolySynth(2);
					polySynth.toMaster();
					polySynth.triggerAttack("C4", 0.1);
				}, 0.3).then(function(buffer){
					expect(buffer.getFirstSoundTime()).to.be.closeTo(0.1, 0.01);
				});
			});

		});

		context("API", function(){

			it("can be constructed with an options object", function(){
				var polySynth = new PolySynth(4, MonoSynth, {
					"envelope" : {
						"sustain" : 0.3
					}
				});
				expect(polySynth.get().envelope.sustain).to.equal(0.3);
				polySynth.dispose();
			});

			it("throws an error if voice type is not Monophonic", function(){
				expect(function(){
					var polySynth = new PolySynth(4, Sampler);
				}).to.throw(Error);
			});

			it("can be set the detune", function(){
				var polySynth = new PolySynth();
				polySynth.detune.value = -1200;
				expect(polySynth.detune.value).to.equal(-1200);
				polySynth.dispose();
			});

			it("can pass in the volume and detune", function(){
				var polySynth = new PolySynth({
					"volume" : -12,
					"detune" : 120,
				});
				expect(polySynth.volume.value).to.be.closeTo(-12, 0.1);
				expect(polySynth.detune.value).to.be.closeTo(120, 1);
				polySynth.dispose();
			});

			it("can get/set attributes", function(){
				var polySynth = new PolySynth();
				polySynth.set({
					"envelope.decay" : 0.24
				});
				expect(polySynth.get().envelope.decay).to.equal(0.24);
				polySynth.dispose();
			});

		});
	});
});
<|endoftext|>