<commit_before>/**
 * Copyright 2018 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const path = require('path');
const os = require('os');
const fs = require('fs');
const {helper} = require('../lib/helper');
const rmAsync = helper.promisify(require('rimraf'));
const utils = require('./utils');
const {waitEvent} = utils;
const mkdtempAsync = helper.promisify(fs.mkdtemp);

const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');

function waitForBackgroundPageTarget(browser) {
  const target = browser.targets().find(target => target.type() === 'background_page');
  if (target)
    return Promise.resolve(target);
  return new Promise(resolve => {
    browser.on('targetcreated', function listener(target) {
      if (target.type() !== 'background_page')
        return;
      browser.removeListener(listener);
      resolve(target);
    });
  });
}

module.exports.addTests = function({testRunner, expect, puppeteer, defaultBrowserOptions}) {
  const {describe, xdescribe, fdescribe} = testRunner;
  const {it, fit, xit} = testRunner;
  const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;

  const headfulOptions = Object.assign({}, defaultBrowserOptions, {
    headless: false
  });
  const headlessOptions = Object.assign({}, defaultBrowserOptions, {
    headless: true
  });
  const extensionPath = path.join(__dirname, 'assets', 'simple-extension');
  const extensionOptions = Object.assign({}, defaultBrowserOptions, {
    headless: false,
    args: [
      `--disable-extensions-except=${extensionPath}`,
      `--load-extension=${extensionPath}`,
    ],
  });

  describe('HEADFUL', function() {
    it('background_page target type should be available', async() => {
      const browserWithExtension = await puppeteer.launch(extensionOptions);
      const page = await browserWithExtension.newPage();
      const backgroundPageTarget = await waitForBackgroundPageTarget(browserWithExtension);
      await page.close();
      await browserWithExtension.close();
      expect(backgroundPageTarget).toBeTruthy();
    });
    it('target.page() should return a background_page', async({}) => {
      const browserWithExtension = await puppeteer.launch(extensionOptions);
      const backgroundPageTarget = await waitForBackgroundPageTarget(browserWithExtension);
      const page = await backgroundPageTarget.page();
      expect(await page.evaluate(() => 2 * 3)).toBe(6);
      expect(await page.evaluate(() => window.MAGIC)).toBe(42);
      await browserWithExtension.close();
    });
    it('should have default url when launching browser', async function() {
      const browser = await puppeteer.launch(extensionOptions);
      const pages = (await browser.pages()).map(page => page.url());
      expect(pages).toEqual(['about:blank']);
      await browser.close();
    });
    it('headless should be able to read cookies written by headful', async({server}) => {
      const userDataDir = await mkdtempAsync(TMP_FOLDER);
      // Write a cookie in headful chrome
      const headfulBrowser = await puppeteer.launch(Object.assign({userDataDir}, headfulOptions));
      const headfulPage = await headfulBrowser.newPage();
      await headfulPage.goto(server.EMPTY_PAGE);
      await headfulPage.evaluate(() => document.cookie = 'foo=true; expires=Fri, 31 Dec 9999 23:59:59 GMT');
      await headfulBrowser.close();
      // Read the cookie from headless chrome
      const headlessBrowser = await puppeteer.launch(Object.assign({userDataDir}, headlessOptions));
      const headlessPage = await headlessBrowser.newPage();
      await headlessPage.goto(server.EMPTY_PAGE);
      const cookie = await headlessPage.evaluate(() => document.cookie);
      await headlessBrowser.close();
      // This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
      await rmAsync(userDataDir).catch(e => {});
      expect(cookie).toBe('foo=true');
    });
    it('OOPIF: should report google.com frame', async({server}) => {
      // https://google.com is isolated by default in Chromium embedder.
      const browser = await puppeteer.launch(headfulOptions);
      const page = await browser.newPage();
      await page.goto(server.EMPTY_PAGE);
      await page.setRequestInterception(true);
      page.on('request', r => r.respond({body: 'YO, GOOGLE.COM'}));
      await page.evaluate(() => {
        const frame = document.createElement('iframe');
        frame.setAttribute('src', 'https://google.com/');
        document.body.appendChild(frame);
        return new Promise(x => frame.onload = x);
      });
      await page.waitForSelector('iframe[src="https://google.com/"]');
      const urls = page.frames().map(frame => frame.url()).sort();
      expect(urls).toEqual([
        server.EMPTY_PAGE,
        'https://google.com/'
      ]);
      await browser.close();
    });
    it('should close browser with beforeunload page', async({server}) => {
      const browser = await puppeteer.launch(headfulOptions);
      const page = await browser.newPage();
      await page.goto(server.PREFIX + '/beforeunload.html');
      // We have to interact with a page so that 'beforeunload' handlers
      // fire.
      await page.click('body');
      await browser.close();
    });
  });
};

<commit_msg>fix(tests): background page tests should wait for the page (#4769)<commit_after>/**
 * Copyright 2018 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const path = require('path');
const os = require('os');
const fs = require('fs');
const {helper} = require('../lib/helper');
const rmAsync = helper.promisify(require('rimraf'));
const utils = require('./utils');
const {waitEvent} = utils;
const mkdtempAsync = helper.promisify(fs.mkdtemp);

const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');

module.exports.addTests = function({testRunner, expect, puppeteer, defaultBrowserOptions}) {
  const {describe, xdescribe, fdescribe} = testRunner;
  const {it, fit, xit} = testRunner;
  const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;

  const headfulOptions = Object.assign({}, defaultBrowserOptions, {
    headless: false
  });
  const headlessOptions = Object.assign({}, defaultBrowserOptions, {
    headless: true
  });
  const extensionPath = path.join(__dirname, 'assets', 'simple-extension');
  const extensionOptions = Object.assign({}, defaultBrowserOptions, {
    headless: false,
    args: [
      `--disable-extensions-except=${extensionPath}`,
      `--load-extension=${extensionPath}`,
    ],
  });

  describe('HEADFUL', function() {
    it('background_page target type should be available', async() => {
      const browserWithExtension = await puppeteer.launch(extensionOptions);
      const page = await browserWithExtension.newPage();
      const backgroundPageTarget = await browserWithExtension.waitForTarget(target => target.type() === 'background_page');
      await page.close();
      await browserWithExtension.close();
      expect(backgroundPageTarget).toBeTruthy();
    });
    it('target.page() should return a background_page', async({}) => {
      const browserWithExtension = await puppeteer.launch(extensionOptions);
      const backgroundPageTarget = await browserWithExtension.waitForTarget(target => target.type() === 'background_page');
      const page = await backgroundPageTarget.page();
      expect(await page.evaluate(() => 2 * 3)).toBe(6);
      expect(await page.evaluate(() => window.MAGIC)).toBe(42);
      await browserWithExtension.close();
    });
    it('should have default url when launching browser', async function() {
      const browser = await puppeteer.launch(extensionOptions);
      const pages = (await browser.pages()).map(page => page.url());
      expect(pages).toEqual(['about:blank']);
      await browser.close();
    });
    it('headless should be able to read cookies written by headful', async({server}) => {
      const userDataDir = await mkdtempAsync(TMP_FOLDER);
      // Write a cookie in headful chrome
      const headfulBrowser = await puppeteer.launch(Object.assign({userDataDir}, headfulOptions));
      const headfulPage = await headfulBrowser.newPage();
      await headfulPage.goto(server.EMPTY_PAGE);
      await headfulPage.evaluate(() => document.cookie = 'foo=true; expires=Fri, 31 Dec 9999 23:59:59 GMT');
      await headfulBrowser.close();
      // Read the cookie from headless chrome
      const headlessBrowser = await puppeteer.launch(Object.assign({userDataDir}, headlessOptions));
      const headlessPage = await headlessBrowser.newPage();
      await headlessPage.goto(server.EMPTY_PAGE);
      const cookie = await headlessPage.evaluate(() => document.cookie);
      await headlessBrowser.close();
      // This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
      await rmAsync(userDataDir).catch(e => {});
      expect(cookie).toBe('foo=true');
    });
    it('OOPIF: should report google.com frame', async({server}) => {
      // https://google.com is isolated by default in Chromium embedder.
      const browser = await puppeteer.launch(headfulOptions);
      const page = await browser.newPage();
      await page.goto(server.EMPTY_PAGE);
      await page.setRequestInterception(true);
      page.on('request', r => r.respond({body: 'YO, GOOGLE.COM'}));
      await page.evaluate(() => {
        const frame = document.createElement('iframe');
        frame.setAttribute('src', 'https://google.com/');
        document.body.appendChild(frame);
        return new Promise(x => frame.onload = x);
      });
      await page.waitForSelector('iframe[src="https://google.com/"]');
      const urls = page.frames().map(frame => frame.url()).sort();
      expect(urls).toEqual([
        server.EMPTY_PAGE,
        'https://google.com/'
      ]);
      await browser.close();
    });
    it('should close browser with beforeunload page', async({server}) => {
      const browser = await puppeteer.launch(headfulOptions);
      const page = await browser.newPage();
      await page.goto(server.PREFIX + '/beforeunload.html');
      // We have to interact with a page so that 'beforeunload' handlers
      // fire.
      await page.click('body');
      await browser.close();
    });
  });
};

<|endoftext|>


<commit_before>const fs = require('fs');
const join = require('path').join;
const rimraf = require('rimraf');
const assert = require('assert');
const webpack = require('webpack');
const getWebpackConfig = require('./webpack.config.js');

const root = join(__dirname, 'integrations');
const output = join(__dirname, '_out');

describe('Integrations with webpack 2', function() {
    const cases = fs.readdirSync(root);

    rimraf.sync(output);

    cases.forEach(function(testCase) {
        it('with ' + testCase + ' test', function() {
            return new Promise(function(resolve, reject) {
                const outputDirectory = join(output, testCase);
                const testDirectory = join(root, testCase);
                const configFile = join(testDirectory, 'webpack.config.js');

                let options = getWebpackConfig({
                    outputDirectory: outputDirectory,
                    testDirectory: testDirectory
                });

                if (fs.existsSync(configFile)) {
                    const testConfig = require(configFile);
                    options = Object.assign({}, options, testConfig, {
                        plugins: options.plugins.concat(testConfig.plugins)
                    });
                }

                webpack(options, function (err, stats) {
                    if (err) return reject(err);
                    if (stats.hasErrors()) return reject(new Error(stats.toString()));

                    const actual = fs.readFileSync(join(outputDirectory, 'test.css'), 'utf-8');
                    const expected = fs.readFileSync(join(testDirectory, 'expected.css'), 'utf-8').replace(/\n$/g, '');

                    assert.equal(actual, expected,
                        'Output ' + testCase + '/test.css file isn\'t equals ' + testCase + '/expected.css'
                    );

                    resolve();
                });
            });
        });
    });
});
<commit_msg>Fix intergation tests for node 4<commit_after>const fs = require('fs');
const join = require('path').join;
const rimraf = require('rimraf');
const assert = require('assert');
const webpack = require('webpack');
const getWebpackConfig = require('./webpack.config.js');

const root = join(__dirname, 'integrations');
const output = join(__dirname, '_out');

describe('Integrations with webpack 2', function() {
    const cases = fs.readdirSync(root);

    rimraf.sync(output);

    cases.forEach(function(testCase) {
        it('with ' + testCase + ' test', function() {
            return new Promise(function(resolve, reject) {
                const outputDirectory = join(output, testCase);
                const testDirectory = join(root, testCase);
                const configFile = join(testDirectory, 'webpack.config.js');

                var options = getWebpackConfig({
                    outputDirectory: outputDirectory,
                    testDirectory: testDirectory
                });

                if (fs.existsSync(configFile)) {
                    const testConfig = require(configFile);
                    options = Object.assign({}, options, testConfig, {
                        plugins: options.plugins.concat(testConfig.plugins)
                    });
                }

                webpack(options, function (err, stats) {
                    if (err) return reject(err);
                    if (stats.hasErrors()) return reject(new Error(stats.toString()));

                    const actual = fs.readFileSync(join(outputDirectory, 'test.css'), 'utf-8');
                    const expected = fs.readFileSync(join(testDirectory, 'expected.css'), 'utf-8').replace(/\n$/g, '');

                    assert.equal(actual, expected,
                        'Output ' + testCase + '/test.css file isn\'t equals ' + testCase + '/expected.css'
                    );

                    resolve();
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>var hippie = require("hippie"),
	path = require("path"),
	turtleio = require(path.join("..", "lib", "index.js")),
	etag = "";

function request () {
	return hippie().base( "http://localhost:8002" );
}

turtleio().start({
	default: "test",
	root: path.join(__dirname, "..", "sites"),
	port: 8002,
	logs: {
		stdout: false,
		dtrace: true
	},
	vhosts: {
		"test": "test"
	}
});

describe( "Invalid Requests", function () {
	it( "GET / (416 / 'Partial response - invalid')", function ( done ) {
		request()
			.get( "/" )
			.header( "range", "a-b" )
			.expectStatus( 416 )
			.expectHeader( "status", "416 Requested Range Not Satisfiable" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Requested Range not Satisfiable/)
			.end( function ( err, res ) {
				if ( err ) throw err;
				etag = res.headers.etag;
				done();
			} );
	} );

	it( "GET / (416 / 'Partial response - invalid #2')", function ( done ) {
		request()
			.get( "/" )
			.header( "range", "5-0" )
			.expectStatus( 416 )
			.expectHeader( "status", "416 Requested Range Not Satisfiable" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Requested Range not Satisfiable/)
			.end( function ( err, res ) {
				if ( err ) throw err;
				etag = res.headers.etag;
				done();
			} );
	} );

	it( "POST / (405 / 'Method not allowed')", function ( done ) {
		request()
			.post( "/" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "PUT / (405 / 'Method not allowed')", function ( done ) {
		request()
			.put( "/" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "PATCH / (405 / 'Method not allowed')", function ( done ) {
		request()
			.patch( "/" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "DELETE / (405 / 'Method not allowed')", function ( done ) {
		request()
			.del( "/" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "GET /nothere.html (404 / 'File not found')", function ( done ) {
		request()
			.get( "/nothere.html" )
			.expectStatus( 404 )
			.expectHeader( "status", "404 Not Found" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/File not found/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "GET /nothere.html%3fa=b?=c (404 / 'File not found')", function ( done ) {
		request()
			.get( "/nothere.html%3fa=b?=c" )
			.expectStatus( 404 )
			.expectHeader( "status", "404 Not Found" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/File not found/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	// 405 is a result of a cached route that leads to a file system based 404 on GET
	it( "POST /nothere.html (405 / 'Method not allowed')", function ( done ) {
		request()
			.post( "/nothere.html" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "PUT /nothere.html (405 / 'Method not allowed')", function ( done ) {
		request()
			.put( "/nothere.html" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "PATCH /nothere.html (405 / 'Method not allowed')", function ( done ) {
		request()
			.patch( "/nothere.html" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "DELETE /nothere.html (405 / 'Method not allowed')", function ( done ) {
		request()
			.del( "/nothere.html" )
			.expectStatus( 405 )
			.expectHeader( "status", "405 Method Not Allowed" )
			.expectHeader( "allow", "GET, HEAD, OPTIONS" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/Method not allowed/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "GET /../README (404 / 'File not found')", function ( done ) {
		request()
			.get( "/../README" )
			.expectStatus( 404 )
			.expectHeader( "status", "404 Not Found" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/File not found/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );

	it( "GET /././../README (404 / 'File not found')", function ( done ) {
		request()
			.get( "/././../README" )
			.expectStatus( 404 )
			.expectHeader( "status", "404 Not Found" )
			.expectHeader( "transfer-encoding", "identity" )
			.expectBody(/File not found/)
			.end( function ( err ) {
				if ( err ) throw err;
				done();
			} );
	} );
} );
<commit_msg>Fixing formatting of test<commit_after>var hippie = require("hippie"),
	path = require("path"),
	turtleio = require(path.join("..", "lib", "index.js")),
	etag = "";

function request () {
	return hippie().base("http://localhost:8002");
}

turtleio().start({
	default: "test",
	root: path.join(__dirname, "..", "sites"),
	port: 8002,
	logs: {
		stdout: false,
		dtrace: true
	},
	vhosts: {
		"test": "test"
	}
});

describe("Invalid Requests", function () {
	it("GET / (416 / 'Partial response - invalid')", function (done) {
		request()
			.get("/")
			.header("range", "a-b")
			.expectStatus(416)
			.expectHeader("status", "416 Requested Range Not Satisfiable")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Requested Range not Satisfiable/)
			.end(function (err, res) {
				if (err) throw err;
				etag = res.headers.etag;
				done();
			});
	});

	it("GET / (416 / 'Partial response - invalid #2')", function (done) {
		request()
			.get("/")
			.header("range", "5-0")
			.expectStatus(416)
			.expectHeader("status", "416 Requested Range Not Satisfiable")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Requested Range not Satisfiable/)
			.end(function (err, res) {
				if (err) throw err;
				etag = res.headers.etag;
				done();
			});
	});

	it("POST / (405 / 'Method not allowed')", function (done) {
		request()
			.post("/")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("PUT / (405 / 'Method not allowed')", function (done) {
		request()
			.put("/")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("PATCH / (405 / 'Method not allowed')", function (done) {
		request()
			.patch("/")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("DELETE / (405 / 'Method not allowed')", function (done) {
		request()
			.del("/")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("GET /nothere.html (404 / 'File not found')", function (done) {
		request()
			.get("/nothere.html")
			.expectStatus(404)
			.expectHeader("status", "404 Not Found")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/File not found/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("GET /nothere.html%3fa=b?=c (404 / 'File not found')", function (done) {
		request()
			.get("/nothere.html%3fa=b?=c")
			.expectStatus(404)
			.expectHeader("status", "404 Not Found")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/File not found/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	// 405 is a result of a cached route that leads to a file system based 404 on GET
	it("POST /nothere.html (405 / 'Method not allowed')", function (done) {
		request()
			.post("/nothere.html")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("PUT /nothere.html (405 / 'Method not allowed')", function (done) {
		request()
			.put("/nothere.html")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("PATCH /nothere.html (405 / 'Method not allowed')", function (done) {
		request()
			.patch("/nothere.html")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("DELETE /nothere.html (405 / 'Method not allowed')", function (done) {
		request()
			.del("/nothere.html")
			.expectStatus(405)
			.expectHeader("status", "405 Method Not Allowed")
			.expectHeader("allow", "GET, HEAD, OPTIONS")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/Method not allowed/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("GET /../README (404 / 'File not found')", function (done) {
		request()
			.get("/../README")
			.expectStatus(404)
			.expectHeader("status", "404 Not Found")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/File not found/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});

	it("GET /././../README (404 / 'File not found')", function (done) {
		request()
			.get("/././../README")
			.expectStatus(404)
			.expectHeader("status", "404 Not Found")
			.expectHeader("transfer-encoding", "identity")
			.expectBody(/File not found/)
			.end(function (err) {
				if (err) throw err;
				done();
			});
	});
});
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');

var Config = require('../../lib/Config');

describe('Config', function() {
  describe('()', function() {
    it('should work with no options supplied', function(done) {
      var config = new Config();
      assert(config instanceof Config);
      done();
    });

    it('should not require the $HOME environment variable to be set', function(done) {
      var home = process.env.HOME;

      if (home) {
        delete process.env.HOME;
      }

      var config = new Config();
      assert(config instanceof Config);

      process.env.HOME = home;
      done();
    });
  });
});
<commit_msg>Adding more tests for Config.<commit_after>'use strict';

var assert = require('assert');

var Config = require('../../lib/Config');

describe('Config', function() {
  describe('()', function() {
    it('should work with no options supplied', function(done) {
      var config = new Config();
      assert(config instanceof Config);
      done();
    });

    it('should not require the $HOME environment variable to be set', function(done) {
      var home = process.env.HOME;

      if (home) {
        delete process.env.HOME;
      }

      var config = new Config();
      assert(config instanceof Config);

      process.env.HOME = home;
      done();
    });

    it('should generate the appropriate apikey options when environment variables are supplied', function(done) {
      var oldApiKeyId = process.env.STORMPATH_CLIENT_APIKEY_ID;
      var oldApiKeySecret = process.env.STORMPATH_CLIENT_APIKEY_SECRET;

      process.env.STORMPATH_CLIENT_APIKEY_ID = 'xxx';
      process.env.STORMPATH_CLIENT_APIKEY_SECRET = 'yyy';

      var config = new Config();
      assert.equal(config.client.apiKey.id, 'xxx');
      assert.equal(config.client.apiKey.secret, 'yyy');

      process.env.STORMPATH_CLIENT_APIKEY_ID = oldApiKeyId;
      process.env.STORMPATH_CLIENT_APIKEY_SECRET = oldApiKeySecret;

      done();
    });

    it('should generate the appropriate application options when environment variables are supplied', function(done) {
      var oldApplicationHref = process.env.STORMPATH_APPLICATION_HREF;
      var oldApplicationName = process.env.STORMPATH_APPLICATION_NAME;

      process.env.STORMPATH_APPLICATION_HREF = 'xxx';
      process.env.STORMPATH_APPLICATION_NAME = 'yyy';

      var config = new Config();
      assert.equal(config.application.href, 'xxx');
      assert.equal(config.application.name, 'yyy');

      process.env.STORMPATH_APPLICATION_HREF = oldApplicationHref;
      process.env.STORMPATH_APPLICATION_NAME = oldApplicationName;

      done();
    });
  });
});
<|endoftext|>


<commit_before>
var _ = require('underscore')
;

var MockRedisSub = exports.MockRedisSub = function () {
    this.subscriptions = {};
    this.messageListeners = [];
    this.subscriptionListeners = [];
};

_.extend(MockRedisSub.prototype, {
    subscribe: function (channel) {
	var _this = this;
	_this.subscriptions[channel] = 1 + (_this.subscriptions[channel] || 0);
	_.each(_this.subscribeListeners, function (listener) {
	    listener(channel, _.keys(_this.subscriptions).length);
	});
    }
    , unsubscribe: function (channel) {
	delete this.subscriptions[channel];
    }
    , on: function (type, listener) {
	if (type === 'message') {
	    this.messageListeners.push(listener);
	}
	else if (type === 'subscribe') {
	    this.subscribeListeners.push(listener);
	}
    }
    , _receive: function (channel, message) {
	if (this.subscriptions[channel] > 0) {
	    _.each(this.messageListeners, function (listener) {
		listener(channel, message);
	    });
	}
    }
});
<commit_msg>Stringify messages in the mock redis subscriber.<commit_after>
var _ = require('underscore')
;

var MockRedisSub = exports.MockRedisSub = function () {
    this.subscriptions = {};
    this.messageListeners = [];
    this.subscriptionListeners = [];
};

_.extend(MockRedisSub.prototype, {
    subscribe: function (channel) {
	var _this = this;
	_this.subscriptions[channel] = 1 + (_this.subscriptions[channel] || 0);
	_.each(_this.subscribeListeners, function (listener) {
	    listener(channel, _.keys(_this.subscriptions).length);
	});
    }
    , unsubscribe: function (channel) {
	delete this.subscriptions[channel];
    }
    , on: function (type, listener) {
	if (type === 'message') {
	    this.messageListeners.push(listener);
	}
	else if (type === 'subscribe') {
	    this.subscribeListeners.push(listener);
	}
    }
    , _receive: function (channel, message) {
	if (this.subscriptions[channel] > 0) {
	    _.each(this.messageListeners, function (listener) {
		listener(channel, JSON.stringify(message));
	    });
	}
    }
});
<|endoftext|>


<commit_before>var happens = require('..');
var should = require('chai').should();

describe('[no-listeners]', function(){

  var Extended = null;

  before(function(){
    Extended = function(){
      happens(this);
    };
  });

  it('should not raise error when emitting event with no listeners', function(){
    var tmp = new Extended();
    tmp.emit('ping');
  });

  it('should not raise error when removing unexistent listener', function(){
    var tmp = new Extended();
    tmp.off('none', function(){});
  });

  it('should not accept undefined functions as listeners', function(){
    var tmp = new Extended();

    (function(){
      tmp.on( 'emit', undefined );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', null);
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit' );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', 1 );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', {} );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', [] );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', '' );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', new Date() );
    }).should.throw(/is not a Function/);

    tmp.emit( "emit", "anything" );
  });
});<commit_msg>correcting word<commit_after>var happens = require('..');
var should = require('chai').should();

describe('[no-listeners]', function(){

  var Extended = null;

  before(function(){
    Extended = function(){
      happens(this);
    };
  });

  it('should not raise error when emitting event with no listeners', function(){
    var tmp = new Extended();
    tmp.emit('ping');
  });

  it('should not raise error when removing inexistent listener', function(){
    var tmp = new Extended();
    tmp.off('none', function(){});
  });

  it('should not accept undefined functions as listeners', function(){
    var tmp = new Extended();

    (function(){
      tmp.on( 'emit', undefined );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', null);
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit' );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', 1 );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', {} );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', [] );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', '' );
    }).should.throw(/is not a Function/);

    (function(){
      tmp.on( 'emit', new Date() );
    }).should.throw(/is not a Function/);

    tmp.emit( "emit", "anything" );
  });
});<|endoftext|>


<commit_before>/* global describe, it, expect */

var pkg = require('..');

describe('bixby-http', function() {

  it('should export manifest', function() {
    expect(pkg).to.be.an('object');
    expect(pkg['server']).to.be.a('function');
  });

  describe('http/server', function() {
    var logger = pkg['server'];

    it('should be annotated', function() {
      expect(logger['@implements']).to.equal('http://i.bixbyjs.org/http/Server');
      expect(logger['@singleton']).to.equal(true);
    });
  });

});
<commit_msg>Update tests.<commit_after>/* global describe, it, expect */

describe('bixby-http', function() {

  describe('package.json', function() {
    var json = require('../package.json');

    it('should have assembly metadata', function() {
      expect(json.assembly.namespace).to.equal('http');

      expect(json.assembly.components).to.have.length(7);
      expect(json.assembly.components).to.include('server');
    });
  });

  it('should throw if required', function() {
    expect(function() {
      var pkg = require('..');
    }).to.throw(Error).with.property('code', 'MODULE_NOT_FOUND');
  });

});
<|endoftext|>


<commit_before>/* eslint-disable no-unused-expressions */
/*
 * Tests for parse result namespace elements, including all their
 * convenience properties and methods.
 */

import chai, { Assertion, expect } from 'chai';

import minim from 'minim';
import minimParseResult from '../src/parse-result';

const namespace = minim.namespace()
  .use(minimParseResult);

const Annotation = namespace.getElementClass('annotation');
const Category = namespace.getElementClass('category');

chai.use((_chai, utils) => {
  /*
   * Asserts that an element has a certain class.
   */
  utils.addMethod(Assertion.prototype, 'class', function hasClass(name) {
    // eslint-disable-next-line no-underscore-dangle
    const obj = this._obj;

    this.assert(
      obj.classes.contains(name),
      'Expected class list #{act} to contain #{exp}',
      'Expected class list #{act} to not contain #{exp}',
      name,
      obj.classes.toValue(),
    );
  });
});

/*
 * Shortcut to get an attribute value from an element.
 */
function attrValue(element, name) {
  return element.attributes.getValue(name);
}

describe('Parse result namespace', () => {
  context('parse result element', () => {
    let parseResult;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'parseResult',
        content: [
          {
            element: 'annotation',
            meta: {
              classes: {
                element: 'array',
                content: [
                  {
                    element: 'string',
                    content: 'warning',
                  },
                ],
              },
            },
            content: [],
          },
          {
            element: 'annotation',
            meta: {
              classes: {
                element: 'array',
                content: [
                  {
                    element: 'string',
                    content: 'error',
                  },
                ],
              },
            },
            content: [],
          },
          {
            element: 'category',
            meta: {
              classes: {
                element: 'array',
                content: [
                  {
                    element: 'string',
                    content: 'api',
                  },
                ],
              },
            },
            content: [],
          },
        ],
      };

      parseResult = namespace.fromRefract(refracted);
    });

    it('should round-trip correctly', () => {
      expect(namespace.toRefract(parseResult)).to.deep.equal(refracted);
    });

    it('should have element name parseResult', () => {
      expect(parseResult.element).to.equal('parseResult');
    });

    it('should contain an API', () => {
      const { api } = parseResult;
      expect(api).to.be.an.instanceof(Category);
      expect(api).to.have.class('api');
    });

    it('should contain two annotations', () => {
      const items = parseResult.annotations;
      expect(items).to.have.length(2);
      items.forEach((item) => {
        expect(item).to.be.an.instanceof(Annotation);
      });
    });

    it('should contain a warning', () => {
      const items = parseResult.warnings;
      expect(items).to.have.length(1);
      items.forEach((item) => {
        expect(item).to.be.an.instanceof(Annotation);
        expect(item).to.have.class('warning');
      });
    });

    it('should contain an error', () => {
      const items = parseResult.errors;
      expect(items).to.have.length(1);
      items.forEach((item) => {
        expect(item).to.be.an.instanceof(Annotation);
        expect(item).to.have.class('error');
      });
    });
  });

  context('annotation element', () => {
    let annotation;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'annotation',
        attributes: {
          code: {
            element: 'number',
            content: 123,
          },
        },
        content: 'Missing argument description',
      };

      annotation = namespace.fromRefract(refracted);
    });

    it('should round-trip correctly', () => {
      expect(namespace.toRefract(annotation)).to.deep.equal(refracted);
    });

    it('should have element name annotation', () => {
      expect(annotation.element).to.equal('annotation');
    });

    it('should get a code', () => {
      expect(annotation.code.toValue()).to.equal(123);
    });

    it('should set a code', () => {
      annotation.code = 456;
      expect(attrValue(annotation, 'code')).to.equal(456);
    });

    it('should have text content', () => {
      expect(annotation.content).to.equal('Missing argument description');
    });
  });

  context('source map element', () => {
    let sourceMap;

    beforeEach(() => {
      sourceMap = namespace.fromRefract({
        element: 'sourceMap',
        content: [],
      });
    });

    it('should have element name sourceMap', () => {
      expect(sourceMap.element).to.equal('sourceMap');
    });
  });

  context('source maps', () => {
    let element;
    let sourceMaps;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'string',
        attributes: {
          sourceMap: {
            element: 'array',
            content: [
              {
                element: 'sourceMap',
                content: [
                  {
                    element: 'array',
                    content: [
                      {
                        element: 'number',
                        content: 1,
                      },
                      {
                        element: 'number',
                        content: 2,
                      },
                    ],
                  },
                ],
              },
            ],
          },
        },
        content: '',
      };

      element = namespace.fromRefract(refracted);
      sourceMaps = element.attributes.get('sourceMap');
    });

    it('should round-trip correctly', () => {
      expect(namespace.toRefract(element)).to.deep.equal(refracted);
    });

    it('should contain a sourceMap attribute with one item', () => {
      // eslint-disable-next-line no-unused-expressions
      expect(sourceMaps).to.exist;
      expect(sourceMaps).to.have.length(1);
    });

    it('should have the source map location', () => {
      expect(sourceMaps.first.toValue()).to.deep.equal([[1, 2]]);
    });

    it('should have a convenience method for retrieving source map', () => {
      expect(element.sourceMapValue).to.deep.equal([[1, 2]]);
    });
  });

  context('source map convenience function', () => {
    let element;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'string',
        content: '',
      };

      element = namespace.fromRefract(refracted);
    });

    it('should have a convenience method for retrieving source map', () => {
      expect(element.sourceMapValue).to.be.undefined;
    });
  });
});
<commit_msg>fix: Fix test fixtures<commit_after>/* eslint-disable no-unused-expressions */
/*
 * Tests for parse result namespace elements, including all their
 * convenience properties and methods.
 */

import chai, { Assertion, expect } from 'chai';

import minim from 'minim';
import minimParseResult from '../src/parse-result';

const namespace = minim.namespace()
  .use(minimParseResult);

const Annotation = namespace.getElementClass('annotation');
const Category = namespace.getElementClass('category');

chai.use((_chai, utils) => {
  /*
   * Asserts that an element has a certain class.
   */
  utils.addMethod(Assertion.prototype, 'class', function hasClass(name) {
    // eslint-disable-next-line no-underscore-dangle
    const obj = this._obj;

    this.assert(
      obj.classes.contains(name),
      'Expected class list #{act} to contain #{exp}',
      'Expected class list #{act} to not contain #{exp}',
      name,
      obj.classes.toValue(),
    );
  });
});

/*
 * Shortcut to get an attribute value from an element.
 */
function attrValue(element, name) {
  return element.attributes.getValue(name);
}

describe('Parse result namespace', () => {
  context('parse result element', () => {
    let parseResult;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'parseResult',
        content: [
          {
            element: 'annotation',
            meta: {
              classes: {
                element: 'array',
                content: [
                  {
                    element: 'string',
                    content: 'warning',
                  },
                ],
              },
            },
          },
          {
            element: 'annotation',
            meta: {
              classes: {
                element: 'array',
                content: [
                  {
                    element: 'string',
                    content: 'error',
                  },
                ],
              },
            },
          },
          {
            element: 'category',
            meta: {
              classes: {
                element: 'array',
                content: [
                  {
                    element: 'string',
                    content: 'api',
                  },
                ],
              },
            },
          },
        ],
      };

      parseResult = namespace.fromRefract(refracted);
    });

    it('should round-trip correctly', () => {
      expect(namespace.toRefract(parseResult)).to.deep.equal(refracted);
    });

    it('should have element name parseResult', () => {
      expect(parseResult.element).to.equal('parseResult');
    });

    it('should contain an API', () => {
      const { api } = parseResult;
      expect(api).to.be.an.instanceof(Category);
      expect(api).to.have.class('api');
    });

    it('should contain two annotations', () => {
      const items = parseResult.annotations;
      expect(items).to.have.length(2);
      items.forEach((item) => {
        expect(item).to.be.an.instanceof(Annotation);
      });
    });

    it('should contain a warning', () => {
      const items = parseResult.warnings;
      expect(items).to.have.length(1);
      items.forEach((item) => {
        expect(item).to.be.an.instanceof(Annotation);
        expect(item).to.have.class('warning');
      });
    });

    it('should contain an error', () => {
      const items = parseResult.errors;
      expect(items).to.have.length(1);
      items.forEach((item) => {
        expect(item).to.be.an.instanceof(Annotation);
        expect(item).to.have.class('error');
      });
    });
  });

  context('annotation element', () => {
    let annotation;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'annotation',
        attributes: {
          code: {
            element: 'number',
            content: 123,
          },
        },
        content: 'Missing argument description',
      };

      annotation = namespace.fromRefract(refracted);
    });

    it('should round-trip correctly', () => {
      expect(namespace.toRefract(annotation)).to.deep.equal(refracted);
    });

    it('should have element name annotation', () => {
      expect(annotation.element).to.equal('annotation');
    });

    it('should get a code', () => {
      expect(annotation.code.toValue()).to.equal(123);
    });

    it('should set a code', () => {
      annotation.code = 456;
      expect(attrValue(annotation, 'code')).to.equal(456);
    });

    it('should have text content', () => {
      expect(annotation.content).to.equal('Missing argument description');
    });
  });

  context('source map element', () => {
    let sourceMap;

    beforeEach(() => {
      sourceMap = namespace.fromRefract({
        element: 'sourceMap',
        content: [],
      });
    });

    it('should have element name sourceMap', () => {
      expect(sourceMap.element).to.equal('sourceMap');
    });
  });

  context('source maps', () => {
    let element;
    let sourceMaps;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'string',
        attributes: {
          sourceMap: {
            element: 'array',
            content: [
              {
                element: 'sourceMap',
                content: [
                  {
                    element: 'array',
                    content: [
                      {
                        element: 'number',
                        content: 1,
                      },
                      {
                        element: 'number',
                        content: 2,
                      },
                    ],
                  },
                ],
              },
            ],
          },
        },
        content: '',
      };

      element = namespace.fromRefract(refracted);
      sourceMaps = element.attributes.get('sourceMap');
    });

    it('should round-trip correctly', () => {
      expect(namespace.toRefract(element)).to.deep.equal(refracted);
    });

    it('should contain a sourceMap attribute with one item', () => {
      // eslint-disable-next-line no-unused-expressions
      expect(sourceMaps).to.exist;
      expect(sourceMaps).to.have.length(1);
    });

    it('should have the source map location', () => {
      expect(sourceMaps.first.toValue()).to.deep.equal([[1, 2]]);
    });

    it('should have a convenience method for retrieving source map', () => {
      expect(element.sourceMapValue).to.deep.equal([[1, 2]]);
    });
  });

  context('source map convenience function', () => {
    let element;
    let refracted;

    beforeEach(() => {
      refracted = {
        element: 'string',
        content: '',
      };

      element = namespace.fromRefract(refracted);
    });

    it('should have a convenience method for retrieving source map', () => {
      expect(element.sourceMapValue).to.be.undefined;
    });
  });
});
<|endoftext|>


<commit_before>describe('Parsing', function() {
  describe('Replacement', function() {
    beforeEach(function() {
      foreigner.locale = 'en';
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should output the string as-is when parameters aren’t passed', function() {
      foreigner.translations.en = {
        test_1: 'Hello, {name}.'
      };

      expect(foreigner.t('test_1')).toEqual('Hello, {name}.');
    });

    it('should output the string with an empty string replacing variables when passing an empty object', function() {
      foreigner.translations.en = {
        test_1: 'Hello, {name}.'
      };

      expect(foreigner.t('test_1', {})).toEqual('Hello, .');
    });

    it('should allow you to escape { and } characters', function() {
      foreigner.translations.en = {
        test_1: '\{test',
        test_2: 'test\}',
        test_3: '\{test\}'
      };

      expect(foreigner.t('test_1')).toEqual('{test');
      expect(foreigner.t('test_2')).toEqual('test}');
      expect(foreigner.t('test_3')).toEqual('{test}');
    });

    it('should gracefully handle quotes (since it ends up in a JS String)', function() {
      foreigner.translations.en = {
        test_1: 'This is a dbl quote: "',
        test_2: "This is a single quote: '"
      };

      expect(foreigner.t('test_1')).toEqual('This is a dbl quote: "');
      expect(foreigner.t('test_2')).toEqual("This is a single quote: '");
    });

    it('should not care about whitespace in a variable', function() {
      foreigner.translations.en = {
        test_1: '{test }',
        test_2: '{ test}',
        test_3: '{test  }',
        test_4: '{  test}',
        test_5: '{test}'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_2', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_3', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_4', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_5', {test: 'Hello'})).toEqual('Hello');
    });

    it('should maintain exact strings - not affected by variables', function() {
      foreigner.translations.en = {
        test_1: 'x{test}',
        test_2: '\n{test}',
        test_3: ' {test}',
        test_4: 'x { test}',
        test_5: 'x{test} x ',
        test_6: 'x\n{test}\n'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('xHello');
      expect(foreigner.t('test_2', {test: 'Hello'})).toEqual('\nHello');
      expect(foreigner.t('test_3', {test: 'Hello'})).toEqual(' Hello');
      expect(foreigner.t('test_4', {test: 'Hello'})).toEqual('x Hello');
      expect(foreigner.t('test_5', {test: 'Hello'})).toEqual('xHello x ');
      expect(foreigner.t('test_6', {test: 'Hello'})).toEqual('x\nHello\n');
    });

    it('should handle extended character literals', function() {
      foreigner.translations.en = {
        test_1: '☺{test}',
        test_2: '中{test}中国话不用彁字。😁'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('☺Hello');
      expect(foreigner.t('test_2', {test: 'Hello'})).toEqual('中Hello中国话不用彁字。😁');
    });

    it('shouldn’t matter if it has html or something in it', function() {
      foreigner.translations.en = {
        test_1: '
content: {test}
'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('
content: Hello
');
    });

    it('should return the string with an empty string as the replacement if the variable provided is null', function() {
      foreigner.translations.en = {
        greet: 'Hello, {name}'
      };

      expect(foreigner.t('greet', {name: null})).toEqual('Hello, ');
    });
  });

  describe('Selects', function() {
    beforeEach(function() {
      foreigner.locale = 'en';
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should be very whitespace agnostic', function() {
      foreigner.translations.en = {
        test_1: '{VAR, select, key{a} other{b}}',
        test_2: '{VAR,select,key{a}other{b}}',
        test_3: '{    VAR   ,    select   ,    key      {a}   other    {b}    }',
        test_4: '{ \n   VAR  \n , \n   select  \n\n , \n \n  key \n    \n {a}  \n other \n   {b} \n  \n }',
        test_5: '{ \t  VAR  \n , \n\t\r  select  \n\t , \t \n  key \n    \t {a}  \n other \t   {b} \t  \t }'
      };

      expect(foreigner.t('test_1', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_2', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_3', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_4', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_5', {VAR: null})).toEqual('b');
    });

    it('should allow you to use keywords in other places, including in select keys', function() {
      foreigner.translations.en = {
        test_1: 'x {TEST, select, select{a} other{b} }',
        test_2: 'x {TEST, select, TEST{a} other{b} }'
      };

      // use `select` as a select key
      expect(foreigner.t('test_1', {TEST: 'select'})).toEqual('x a');
      // use the exact variable name as a key name
      expect(foreigner.t('test_2', {TEST: 'TEST'})).toEqual('x a');
    });
  });

  describe('Plurals', function() {
    beforeEach(function() {
      foreigner.locale = 'en';
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should be very whitespace agnostic', function () {
      foreigner.translations.en = {
        test_1: '{ NUM, plural, one{1} other{2} }',
        test_2: '{NUM,plural,one{1}other{2}}',
        test_3: '{\nNUM,   \nplural,\n   one\n\n{1}\n other {2}\n\n\n}',
        test_4: '{\tNUM\t,\t\t\r plural\t\n, \tone\n{1}    other\t\n{2}\n\n\n}'
      };

      expect(foreigner.t('test_1', {NUM: 1})).toEqual('1');
      expect(foreigner.t('test_2', {NUM: 1})).toEqual('1');
      expect(foreigner.t('test_3', {NUM: 1})).toEqual('1');
      expect(foreigner.t('test_4', {NUM: 1})).toEqual('1');
    });

    it('should be able to match `zero` given a value of 0', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 0})).toEqual('You found 0 coins.');
    });

    it('should be able to match `one` given a value of 1', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 1})).toEqual('You found one coin.');
    });

    it('should be able to match `two` given a value of 2', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 2})).toEqual('You found two coins.');
    });

    it('should be able to match any specific number given the exact value of the number', function() {
      foreigner.translations.en = {
        skill_points: 'You have {skillPoints, plural, 2{2 skill points} two{two skill points} 4{four skill points}} to spend.',
      };

      expect(foreigner.t('skill_points', {skillPoints: 4})).toEqual('You have four skill points to spend.');
    });

    it('should be able to match 0, 1 and 2, and override the named key given the same number and named key are specified', function() {
      foreigner.translations.en = {
        skill_points: 'You have {skillPoints, plural, 2{2 skill points} two{two skill points} 4{four skill points}} to spend.',
      };

      expect(foreigner.t('skill_points', {skillPoints: 2})).toEqual('You have 2 skill points to spend.');
    });

    it('should be able to fall back to `other` when the value doesn’t match any choice', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 3})).toEqual('You found 3 coins.');
    });

    it('should be able to match `other` when no other choice is defined', function() {
      foreigner.translations.en = {
        found_gems: 'You found {gemsCount, plural, other{gems}}.'
      };

      expect(foreigner.t('found_gems', {gemsCount: 1})).toEqual('You found gems.');
    });
  });

  describe('Selects', function() {

    beforeEach(function() {
      foreigner.locale = 'en';
      foreigner.translations.en = {
        the_cake_is: 'The cake is {opinion, select, good{good} bad{bad} other{a lie}}.'
      };
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should be able to match a choice', function() {
      expect(foreigner.t('the_cake_is', {opinion: 'good'})).toEqual('The cake is good.');
    });

    it('should be able to fall back to `other` when the value doesn’t match any choice', function() {
      expect(foreigner.t('the_cake_is', {opinion: 'dont_know'})).toEqual('The cake is a lie.');
    });
  });
});
<commit_msg>Move single interpolation assertion to its own test<commit_after>describe('Parsing', function() {
  describe('Replacement', function() {
    beforeEach(function() {
      foreigner.locale = 'en';
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should work when the string contains only an interpolation', function() {
      foreigner.translations.en = {
        test_1: '{test}'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('Hello');
    });

    it('should output the string as-is when parameters aren’t passed', function() {
      foreigner.translations.en = {
        test_1: 'Hello, {name}.'
      };

      expect(foreigner.t('test_1')).toEqual('Hello, {name}.');
    });

    it('should output the string with an empty string replacing variables when passing an empty object', function() {
      foreigner.translations.en = {
        test_1: 'Hello, {name}.'
      };

      expect(foreigner.t('test_1', {})).toEqual('Hello, .');
    });

    it('should allow you to escape { and } characters', function() {
      foreigner.translations.en = {
        test_1: '\{test',
        test_2: 'test\}',
        test_3: '\{test\}'
      };

      expect(foreigner.t('test_1')).toEqual('{test');
      expect(foreigner.t('test_2')).toEqual('test}');
      expect(foreigner.t('test_3')).toEqual('{test}');
    });

    it('should gracefully handle quotes (since it ends up in a JS String)', function() {
      foreigner.translations.en = {
        test_1: 'This is a dbl quote: "',
        test_2: "This is a single quote: '"
      };

      expect(foreigner.t('test_1')).toEqual('This is a dbl quote: "');
      expect(foreigner.t('test_2')).toEqual("This is a single quote: '");
    });

    it('should not care about whitespace in a variable', function() {
      foreigner.translations.en = {
        test_1: '{test }',
        test_2: '{ test}',
        test_3: '{test  }',
        test_4: '{  test}'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_2', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_3', {test: 'Hello'})).toEqual('Hello');
      expect(foreigner.t('test_4', {test: 'Hello'})).toEqual('Hello');
    });

    it('should maintain exact strings - not affected by variables', function() {
      foreigner.translations.en = {
        test_1: 'x{test}',
        test_2: '\n{test}',
        test_3: ' {test}',
        test_4: 'x { test}',
        test_5: 'x{test} x ',
        test_6: 'x\n{test}\n'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('xHello');
      expect(foreigner.t('test_2', {test: 'Hello'})).toEqual('\nHello');
      expect(foreigner.t('test_3', {test: 'Hello'})).toEqual(' Hello');
      expect(foreigner.t('test_4', {test: 'Hello'})).toEqual('x Hello');
      expect(foreigner.t('test_5', {test: 'Hello'})).toEqual('xHello x ');
      expect(foreigner.t('test_6', {test: 'Hello'})).toEqual('x\nHello\n');
    });

    it('should handle extended character literals', function() {
      foreigner.translations.en = {
        test_1: '☺{test}',
        test_2: '中{test}中国话不用彁字。😁'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('☺Hello');
      expect(foreigner.t('test_2', {test: 'Hello'})).toEqual('中Hello中国话不用彁字。😁');
    });

    it('shouldn’t matter if it has html or something in it', function() {
      foreigner.translations.en = {
        test_1: '
content: {test}
'
      };

      expect(foreigner.t('test_1', {test: 'Hello'})).toEqual('
content: Hello
');
    });

    it('should return the string with an empty string as the replacement if the variable provided is null', function() {
      foreigner.translations.en = {
        greet: 'Hello, {name}'
      };

      expect(foreigner.t('greet', {name: null})).toEqual('Hello, ');
    });
  });

  describe('Selects', function() {
    beforeEach(function() {
      foreigner.locale = 'en';
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should be very whitespace agnostic', function() {
      foreigner.translations.en = {
        test_1: '{VAR, select, key{a} other{b}}',
        test_2: '{VAR,select,key{a}other{b}}',
        test_3: '{    VAR   ,    select   ,    key      {a}   other    {b}    }',
        test_4: '{ \n   VAR  \n , \n   select  \n\n , \n \n  key \n    \n {a}  \n other \n   {b} \n  \n }',
        test_5: '{ \t  VAR  \n , \n\t\r  select  \n\t , \t \n  key \n    \t {a}  \n other \t   {b} \t  \t }'
      };

      expect(foreigner.t('test_1', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_2', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_3', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_4', {VAR: null})).toEqual('b');
      expect(foreigner.t('test_5', {VAR: null})).toEqual('b');
    });

    it('should allow you to use keywords in other places, including in select keys', function() {
      foreigner.translations.en = {
        test_1: 'x {TEST, select, select{a} other{b} }',
        test_2: 'x {TEST, select, TEST{a} other{b} }'
      };

      // use `select` as a select key
      expect(foreigner.t('test_1', {TEST: 'select'})).toEqual('x a');
      // use the exact variable name as a key name
      expect(foreigner.t('test_2', {TEST: 'TEST'})).toEqual('x a');
    });
  });

  describe('Plurals', function() {
    beforeEach(function() {
      foreigner.locale = 'en';
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should be very whitespace agnostic', function () {
      foreigner.translations.en = {
        test_1: '{ NUM, plural, one{1} other{2} }',
        test_2: '{NUM,plural,one{1}other{2}}',
        test_3: '{\nNUM,   \nplural,\n   one\n\n{1}\n other {2}\n\n\n}',
        test_4: '{\tNUM\t,\t\t\r plural\t\n, \tone\n{1}    other\t\n{2}\n\n\n}'
      };

      expect(foreigner.t('test_1', {NUM: 1})).toEqual('1');
      expect(foreigner.t('test_2', {NUM: 1})).toEqual('1');
      expect(foreigner.t('test_3', {NUM: 1})).toEqual('1');
      expect(foreigner.t('test_4', {NUM: 1})).toEqual('1');
    });

    it('should be able to match `zero` given a value of 0', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 0})).toEqual('You found 0 coins.');
    });

    it('should be able to match `one` given a value of 1', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 1})).toEqual('You found one coin.');
    });

    it('should be able to match `two` given a value of 2', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 2})).toEqual('You found two coins.');
    });

    it('should be able to match any specific number given the exact value of the number', function() {
      foreigner.translations.en = {
        skill_points: 'You have {skillPoints, plural, 2{2 skill points} two{two skill points} 4{four skill points}} to spend.',
      };

      expect(foreigner.t('skill_points', {skillPoints: 4})).toEqual('You have four skill points to spend.');
    });

    it('should be able to match 0, 1 and 2, and override the named key given the same number and named key are specified', function() {
      foreigner.translations.en = {
        skill_points: 'You have {skillPoints, plural, 2{2 skill points} two{two skill points} 4{four skill points}} to spend.',
      };

      expect(foreigner.t('skill_points', {skillPoints: 2})).toEqual('You have 2 skill points to spend.');
    });

    it('should be able to fall back to `other` when the value doesn’t match any choice', function() {
      foreigner.translations.en = {
        found_coins: 'You found {coinsCount, plural, zero{# coins} one{one coin} two{two coins} other{# coins}}.',
      };

      expect(foreigner.t('found_coins', {coinsCount: 3})).toEqual('You found 3 coins.');
    });

    it('should be able to match `other` when no other choice is defined', function() {
      foreigner.translations.en = {
        found_gems: 'You found {gemsCount, plural, other{gems}}.'
      };

      expect(foreigner.t('found_gems', {gemsCount: 1})).toEqual('You found gems.');
    });
  });

  describe('Selects', function() {

    beforeEach(function() {
      foreigner.locale = 'en';
      foreigner.translations.en = {
        the_cake_is: 'The cake is {opinion, select, good{good} bad{bad} other{a lie}}.'
      };
    });

    afterEach(function() {
      foreigner.locale = '';
      foreigner.translations = {};
    });

    it('should be able to match a choice', function() {
      expect(foreigner.t('the_cake_is', {opinion: 'good'})).toEqual('The cake is good.');
    });

    it('should be able to fall back to `other` when the value doesn’t match any choice', function() {
      expect(foreigner.t('the_cake_is', {opinion: 'dont_know'})).toEqual('The cake is a lie.');
    });
  });
});
<|endoftext|>


<commit_before>/*
 * object3d.js
 * Copyright 2017 Lucas Neves <lcneves@gmail.com>
 *
 * Exports an object that extends THREE.Object3D with extra functionality.
 * Part of the Livre project.
 */

'use strict';

const THREE = require('three');

/*
 * Gives the object's world boundaries relative to its position point.
 * Three.js uses the right-hand coordinate system, so:
 * - the x axis grows to the right;
 * - the y axis grows to the top;
 * - the z axis grows to the near.
 */
function getBoundaries(object) {
  const bbox = new THREE.Box3().setFromObject(object);
  return {
    left: object.position.x - bbox.min.x,
    right: bbox.max.x - object.position.x,
    top: bbox.max.y - object.position.y,
    bottom: object.position.y - bbox.min.y,
    far: object.position.z - bbox.min.z,
    near: bbox.max.z - object.position.z
  };
}

/*
 * Gives the object's world dimensions in a boundary box.
 */
function getDimensions(object) {
  console.dir(object);

  const bbox = new THREE.Box3().setFromObject(object);

  return {
    x: bbox.max.x - bbox.min.x,
    y: bbox.max.y - bbox.min.y,
    z: bbox.max.z - bbox.min.z
  };
}

function makeInitialPosition(axis) {
  var position = {
    reference: undefined,
    distance: 0
  };
  switch (axis) {
    case 'x':
      position.reference = 'left';
      break;
    case 'y':
      position.reference = 'top';
      break;
    case 'z':
      position.reference = 'far';
      break;
  }

  return position;
}

/*
 * Returns the world position that the child should have
 * given its relative position to the parent.
 */
function makeWorldPosition(childObject, parentObject) {
  // Continue below this line
  return { x: 0, y: 0, z: 0 };

  const parentBoundaries = parentObject.boundaries;
  const childBoundaries = childObject.boundaries;

  var position = {};

  for (let axis of ['x', 'y', 'z']) {
    let reference = childObject.relativePosition[axis].reference;
    let factor;
    switch (reference) {
      case 'right':
      case 'top':
      case 'near':
        factor = -1;
        break;
      default:
        factor = 1;
        break;
    }

    position[axis] =
      parentObject.position[axis] + factor * (
        childObject.relativePosition[axis].distance +
        childBoundaries[reference] -
        parentBoundaries[reference]
      );
  }

  return position;
}

class Object3D extends THREE.Object3D {
  constructor(mesh) {
    super();

    this._isLivreObject = true;

    if (mesh) {
      this.add(mesh);
    }

    this.relativePosition = {
      x: makeInitialPosition('x'),
      y: makeInitialPosition('y'),
      z: makeInitialPosition('z')
    };
  }

  get dimensions() {
    return getDimensions(this);
  }

  get boundaries() {
    return getBoundaries(this);
  }

  setWorldPosition(parentObject) {
    parentObject = parentObject || this.parent;

    var position = makeWorldPosition(this, parentObject);
    for (let prop in position) {
      if (position.hasOwnProperty(prop)) {
        this.position[prop] = position[prop];
      }
    }
  }

  // Overrides THREE.Object3D's add function
  add(object) {
    if(object._isLivreObject) {
      object.setWorldPosition(this);
    }
    THREE.Object3D.prototype.add.call(this, object);
  }
}

module.exports = Object3D;
<commit_msg>WIP: Positioning of elements<commit_after>/*
 * object3d.js
 * Copyright 2017 Lucas Neves <lcneves@gmail.com>
 *
 * Exports an object that extends THREE.Object3D with extra functionality.
 * Part of the Livre project.
 */

'use strict';

const THREE = require('three');

/*
 * Gives the object's world boundaries relative to its position point.
 * Three.js uses the right-hand coordinate system, so:
 * - the x axis grows to the right;
 * - the y axis grows to the top;
 * - the z axis grows to the near.
 */
function getBoundaries(object) {
  const bbox = new THREE.Box3().setFromObject(object);
  return {
    left: object.position.x - bbox.min.x,
    right: bbox.max.x - object.position.x,
    top: bbox.max.y - object.position.y,
    bottom: object.position.y - bbox.min.y,
    far: object.position.z - bbox.min.z,
    near: bbox.max.z - object.position.z
  };
}

/*
 * Gives the object's world dimensions in a boundary box.
 */
function getDimensions(object) {
  if (object.children && object.children[0]._isLivreObject) {
    var virtualBox = {
      x: 0,
      y: 0,
      z: 0
    };
    for (let child of object.children) {
      let dimensions = getDimensions(child);
      virtualBox.x = Math.max(virtualBox.x, dimensions.x);
      virtualBox.y += dimensions.y;
      virtualBox.z = Math.max(virtualBox.z, dimensions.z);
    }
    return virtualBox;
  }

  else {
    const bbox = new THREE.Box3().setFromObject(object);

    return {
      x: bbox.max.x - bbox.min.x,
      y: bbox.max.y - bbox.min.y,
      z: bbox.max.z - bbox.min.z
    };
  }
}

function makeInitialPosition(axis) {
  var position = {
    reference: undefined,
    distance: 0
  };
  switch (axis) {
    case 'x':
      position.reference = 'left';
      break;
    case 'y':
      position.reference = 'top';
      break;
    case 'z':
      position.reference = 'far';
      break;
  }

  return position;
}

/*
 * Returns the world position that the child should have
 * given its relative position to the parent.
 */

/*
 * Will consider for absolute positioning
function makeWorldPosition(childObject, parentObject) {
  // Continue below this line
  return { x: 0, y: 0, z: 0 };

  const parentBoundaries = parentObject.boundaries;
  const childBoundaries = childObject.boundaries;

  var position = {};

  for (let axis of ['x', 'y', 'z']) {
    let reference = childObject.relativePosition[axis].reference;
    let factor;
    switch (reference) {
      case 'right':
      case 'top':
      case 'near':
        factor = -1;
        break;
      default:
        factor = 1;
        break;
    }

    position[axis] =
      parentObject.position[axis] + factor * (
        childObject.relativePosition[axis].distance +
        childBoundaries[reference] -
        parentBoundaries[reference]
      );
  }

  return position;
}
*/

function makeWorldPosition(childObject, parentObject) {
}

class Object3D extends THREE.Object3D {
  constructor(mesh) {
    super();

    this._isLivreObject = true;

    if (mesh) {
      this.add(mesh);
    }

    this.relativePosition = {
      x: makeInitialPosition('x'),
      y: makeInitialPosition('y'),
      z: makeInitialPosition('z')
    };
  }

  get dimensions() {
    return getDimensions(this);
  }

  get boundaries() {
    return getBoundaries(this);
  }

  setWorldPosition(parentObject) {
    parentObject = parentObject || this.parent;

    var position = makeWorldPosition(this, parentObject);
    for (let prop in position) {
      if (position.hasOwnProperty(prop)) {
        this.position[prop] = position[prop];
      }
    }
  }

  // Overrides THREE.Object3D's add function
  add(object) {
    if(object._isLivreObject) {
      object.setWorldPosition(this);
    }
    THREE.Object3D.prototype.add.call(this, object);
  }
}

module.exports = Object3D;
<|endoftext|>


<commit_before>/*global require:true */
/**
 * Assemble <http://assemble.io>
 * Created and maintained by Jon Schlinkert and Brian Woodward
 *
 * Copyright (c) 2013 Upstage.
 * Licensed under the MIT License (MIT).
 */

var grunt = require('grunt');
var assemble = require('../lib/assemble');
var expect   = require('chai').expect;

describe("plugins", function() {

  describe("core", function () {

    it('should load plugins from node modules', function() {
      // pretend some node modules are plugins
      var plugins = assemble.plugins.resolve(['lodash', 'inflection']);

      expect(plugins.length).to.equal(2);
      expect(plugins[0].VERSION).to.be.a('string');
      expect(plugins[1].version).to.be.a('string');
    });

    it('should load plugins from glob', function() {
      var plugins = assemble.plugins.resolve(['./test/plugins/*one.js', ]);

      expect(plugins.length).to.equal(1);
      expect(plugins[0]).to.be.a('function');
    });

    it('should load plugins as functions', function() {
      var plugin = function () {};
      var plugins = assemble.plugins.resolve([plugin]);

      expect(plugins.length).to.equal(1);
      expect(plugins[0]).to.be.a('function');
    });

  });

  describe("examples: ", function () {

    describe("before :", function () {

      it('should run once and first', function() {
        var contents = grunt.file.read('./test/actual/plugin_before.html');
        expect(contents).to.equal('\n\nBEFORE TITLE 1');
      });

    });

    describe("after :", function () {

      it('should run once and last', function() {
        var contents = grunt.file.read('./test/actual/plugin_after.html');
        expect(contents).to.equal('AFTER OVERWRITE 1');
      });

    });

  });

});

<commit_msg>fix (jshint error)<commit_after>/*global require:true */
/**
 * Assemble <http://assemble.io>
 * Created and maintained by Jon Schlinkert and Brian Woodward
 *
 * Copyright (c) 2013 Upstage.
 * Licensed under the MIT License (MIT).
 */

var grunt = require('grunt');
var assemble = require('../lib/assemble');
var expect   = require('chai').expect;

describe("plugins", function() {

  describe("core", function () {

    it('should load plugins from node modules', function() {
      // pretend some node modules are plugins
      var plugins = assemble.plugins.resolve(['lodash', 'inflection']);

      expect(plugins.length).to.equal(2);
      expect(plugins[0].VERSION).to.be.a('string');
      expect(plugins[1].version).to.be.a('string');
    });

    it('should load plugins from glob', function() {
      var plugins = assemble.plugins.resolve(['./test/plugins/*one.js', ]);

      expect(plugins.length).to.equal(1);
      expect(plugins[0]).to.be.a('function');
    });

    it('should load plugins as functions', function() {
      var plugin = function () {};
      var plugins = assemble.plugins.resolve([plugin]);

      expect(plugins.length).to.equal(1);
      expect(plugins[0]).to.be.a('function');
    });

  });

  describe("examples: ", function () {

    describe("before :", function () {

      it('should run once and first', function() {
        var contents = grunt.file.read('./test/actual/plugin_before.html');
        expect(contents).to.equal('BEFORE TITLE 1');
      });

    });

    describe("after :", function () {

      it('should run once and last', function() {
        var contents = grunt.file.read('./test/actual/plugin_after.html');
        expect(contents).to.equal('AFTER OVERWRITE 1');
      });

    });

  });

});

<|endoftext|>


<commit_before>class Oncogene {
    constructor({
        selector,
        steps,
        config = {},
        result = {}
    } = {}) {
        const options = {
            selector,
            steps,
            config,
            result
        }

        this.checkOptions(options)
        this.handleOptions(options)

        this.root.classList.add(this.classes.root)

        this.nextStep()
    }

    nextStep() {
        if (this.nextStepInx >= this.steps.length) return this.showResults()

        this.renderStep(this.steps[this.nextStepInx++])
    }

    renderStep(step) {
        const root = document.createDocumentFragment()
        const hint = this.createNode(this.classes.commonHint)
        const variants = this.createNode(this.classes.variants)

        step.variants.forEach(addVariant.bind(this))

        hint.textContent = step.hint

        root.appendChild(hint)
        root.appendChild(variants)

        this.clearRoot()
        this.root.appendChild(root)

        function addVariant(variant, inx) {
            const item = this.createNode(this.classes.variant)
            const hint = this.createNode(this.classes.hint)
            const code = this.createNode(this.classes.code)

            hint.innerHTML = variant.hint
            code.textContent = variant.code

            item.dataset.inx = inx
            item.appendChild(hint)
            item.appendChild(code)
            item.addEventListener('click', clickHandler.bind(this))

            variants.appendChild(item)
        }

        function clickHandler(e) {
            const inx = e.currentTarget.dataset.inx
            const value = step.variants[inx].value

            if (step.key) {
                this.config[step.key] = value
            }

            if (step.callback) {
                this.config = step.callback(this.config, value)
            }

            this.nextStep()
        }
    }

    showResults() {
        this.renderResult()
    }

    renderResult() {
        const result = this.createNode(this.classes.result)
        const config = this.result.callback(this.config)

        result.textContent = config

        this.clearRoot()
        this.root.appendChild(result)
    }

    createNode(className) {
        const node = document.createElement('div')

        node.className = className

        return node
    }

    clearRoot() {
        while (this.root.firstChild) {
            this.root.removeChild(this.root.firstChild)
        }
    }

    checkOptions(options) {
        const required = ['selector', 'steps']

        if (!options) throw new Error('You should specify options')

        required.forEach(field => {
            if (!options.hasOwnProperty(field)) {
                throw new Error(`You should specify ${field}`)
            }
        })

        if (!(options.steps instanceof Array))
            throw new Error('Steps should be an array')
    }

    handleOptions(options) {
        this.root = document.querySelector(options.selector)
        this.steps = options.steps
        this.config = options.config
        this.result = Object.assign({
            callback: (config) => JSON.stringify(config, 0, 4)
        }, options.result)
        this.nextStepInx = 0

        this.classes = {
            root: 'oncogene',
            commonHint: 'oncogene__hint',
            variants: 'oncogene-variants',
            variant: 'oncogene-variant',
            hint: 'oncogene-variant__hint',
            code: 'oncogene-variant__code',
            result: 'oncogene__result'
        }

        if (!this.root) throw new Error('Can\'t find element by selector')
    }
}
<commit_msg>Constructor definition is simplified.<commit_after>class Oncogene {
    constructor(options) {
        this.checkOptions(options)
        this.handleOptions(options)

        this.root.classList.add(this.classes.root)

        this.nextStep()
    }

    nextStep() {
        if (this.nextStepInx >= this.steps.length) return this.showResults()

        this.renderStep(this.steps[this.nextStepInx++])
    }

    renderStep(step) {
        const root = document.createDocumentFragment()
        const hint = this.createNode(this.classes.commonHint)
        const variants = this.createNode(this.classes.variants)

        step.variants.forEach(addVariant.bind(this))

        hint.textContent = step.hint

        root.appendChild(hint)
        root.appendChild(variants)

        this.clearRoot()
        this.root.appendChild(root)

        function addVariant(variant, inx) {
            const item = this.createNode(this.classes.variant)
            const hint = this.createNode(this.classes.hint)
            const code = this.createNode(this.classes.code)

            hint.innerHTML = variant.hint
            code.textContent = variant.code

            item.dataset.inx = inx
            item.appendChild(hint)
            item.appendChild(code)
            item.addEventListener('click', clickHandler.bind(this))

            variants.appendChild(item)
        }

        function clickHandler(e) {
            const inx = e.currentTarget.dataset.inx
            const value = step.variants[inx].value

            if (step.key) {
                this.config[step.key] = value
            }

            if (step.callback) {
                this.config = step.callback(this.config, value)
            }

            this.nextStep()
        }
    }

    showResults() {
        this.renderResult()
    }

    renderResult() {
        const result = this.createNode(this.classes.result)
        const config = this.result.callback(this.config)

        result.textContent = config

        this.clearRoot()
        this.root.appendChild(result)
    }

    createNode(className) {
        const node = document.createElement('div')

        node.className = className

        return node
    }

    clearRoot() {
        while (this.root.firstChild) {
            this.root.removeChild(this.root.firstChild)
        }
    }

    checkOptions(options) {
        const required = ['selector', 'steps']

        if (!options) throw new Error('You should specify options')

        required.forEach(field => {
            if (!options.hasOwnProperty(field)) {
                throw new Error(`You should specify ${field}`)
            }
        })

        if (!(options.steps instanceof Array))
            throw new Error('Steps should be an array')
    }

    handleOptions(options) {
        this.root = document.querySelector(options.selector)
        this.steps = options.steps
        this.config = options.config || {}
        this.result = Object.assign({
            callback: (config) => JSON.stringify(config, 0, 4)
        }, options.result)
        this.nextStepInx = 0

        this.classes = {
            root: 'oncogene',
            commonHint: 'oncogene__hint',
            variants: 'oncogene-variants',
            variant: 'oncogene-variant',
            hint: 'oncogene-variant__hint',
            code: 'oncogene-variant__code',
            result: 'oncogene__result'
        }

        if (!this.root) throw new Error('Can\'t find element by selector')
    }
}
<|endoftext|>


<commit_before>var request = require('request'),
    twitter_update_with_media = require('./twitter_update_with_media'),
    twitterAPI = require('node-twitter-api'),
    config = require('./config');

var tuwm = new twitter_update_with_media({
  consumer_key: config.consumer_key,
  consumer_secret: config.consumer_secret,
  token: config.token,
  token_secret: config.token_secret,
});

var twitter = new twitterAPI({
  consumerKey: config.consumer_key,
  consumerSecret: config.consumer_secret,
  callback: ''
});

var dogData;
var nameData;
var sex;
var breed;
var mix;
var picArray;
var picture;
var id;
var startPhrase;
var endPhrase;
var buddyTweet;

var getRequest = function() {
  var petFinderKey = config.petfinder_key,
      offset = Math.round(Math.random() * 1999),
      url = 'http://api.petfinder.com/pet.find?key=' + petFinderKey + '&animal=dog&location=new%20york%20ny&count=1&offset=' + offset + '&output=full&format=json';

  request(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      parsedData = JSON.parse(body);
      dogData = parsedData.petfinder.pets.pet;
      nameData = dogData.name.$t;

      name = formatName(nameData);
      sex = sex(dogData.sex.$t);
      mix = mix(dogData.mix.$t);
      id = link(dogData.id.$t);
      breed = pickBreed(dogData.breeds.breed);
      buddyTweet = oneOrTwo(name, id);

      if (Object.getOwnPropertyNames(dogData.media).length === 0) {
        //postTweetText(buddyTweet);
        console.log(buddyTweet);
      }
      else {
        picArray = dogData.media.photos.photo;
        pickPic(picArray);
        //postTweetPic(buddyTweet, picture);
        console.log(buddyTweet + " || " + picture);
      }
    }
    else {
      console.log('Error!');
    }
  });
};

var postTweetPic = function(tweetText, tweetPic) {
  tuwm.post(tweetText, tweetPic, function(err, response) {
    if (err) {
      console.log(err);
    }
    console.log(buddyTweet + " || " + picture);
  });
};

var postTweetText = function(tweetText) {
  twitter.statuses("update", {
    status: tweetText
  },
  config.token,
  config.token_secret,
  function(error, data, response) {
    if (error) {
      console.log(error);
    }
    else {
      console.log(buddyTweet);
    }
  });
};

function oneOrTwo(name, id) {
  var oneDoggie;

  if (name.indexOf('&') > -1 || name.indexOf(' and ') > -1) {
    if (name.indexOf('-') > -1 || name.indexOf('~') > -1 || name.indexOf('(') > -1 && name.indexOf(')') > -1) {
      oneDoggie = true;
      startPhrase = name + " is a " + sex + " " + breed + mix;
    }
    else {
      oneDoggie = false;
      startPhrase = name + " are doggies";
    }
  }
  else {
    oneDoggie = true;
    startPhrase = name + " is a " + sex + " " + breed + mix;
  }
  endPhrase = endOfSentence(oneDoggie);
  buddyTweet = startPhrase + endPhrase + " " + id;
  return buddyTweet;
}

function endOfSentence(oneDoggie) {
  var phrases;

  if (oneDoggie === false) {
    phrases = [' who need a loving home!', ' looking for a new family!', ' looking for a furever home!', ' who need a new best friend!', ' who need a place to call home!', ' looking for a forever home!', ' who want to be your buddies!', ' looking for a loving family!', ' in need of love!', ' in need of a loving home!', ' looking for a new home!', ' who need some lovin\'!', ' who could be your new buddies!'];
  }
  else if (oneDoggie === true) {
    phrases = [' who needs a loving home!', ' looking for a new family!', ' looking for a furever home!', ' who needs a new best friend!', ' who needs a place to call home!', ' looking for a forever home!', ' who wants to be your buddy!', ' looking for a loving family!', ' in need of love!', ' in need of a loving home!', ' looking for a new home!', ' who needs some lovin\'!', ' who could be your new buddy!'];
  }
  endPhrase = phrases[Math.floor(Math.random() * phrases.length)];
  return endPhrase;
}

function formatName(petName) {
  if (petName.match(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|zzz|[0-9]|#/gi) !== null && petName.match(/\/|[(]|[)]|[\[\]]|-|–|—|[*]/gi) === null) {
    petName = petName.replace(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|zzz|[0-9]|#/gi, '');
  }
  else if (petName.match(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|dob |zzz|[0-9]|#/gi) !== null && petName.match(/\/|[(]|[)]|[\[\]]|-|–|—|[*]/gi) !== null) {
    petName = petName.replace(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|dob |zzz|[0-9]|#|\/|[(]|[)]|[\[\]]|-|–|—|[*]/gi, '');
  }
  // Filter for formatting caps/lowercase letters in name, if desired. People are unpredictable, and more cases can be added as needed
  // petName = petName.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
  // petName = petName.replace(/ And /gi, function(i) { return i.toLowerCase(); });
  // petName = petName.replace(/ Or /gi, function(j) { return j.toLowerCase(); });
  // petName = petName.replace(/ Asap/gi, function(k) { return k.toUpperCase(); });
  // petName = petName.replace(/ Aka /gi, function(l) { return l.toUpperCase(); });
  // petName = petName.replace(/ Fka /gi, function(l) { return l.toUpperCase(); });
  // petName = petName.replace(/ Bff /gi, " BFF ");
  // petName = petName.replace(/ Bffs /gi, " BFFs ");
  // petName = petName.replace(/\s+/g,' ').trim();
  // if (petName.length === 2 && petName !== "Al" && petName !== "Bo") {
  //   petName = petName.toUpperCase();
  // }
  return petName;
}

function pickBreed(breed) {
  var singleBreed = true;

  if (breed.length) {
    var breedString = '';
    singleBreed = false;

    for (var i = 0; i < breed.length; i++) {

      if(i === breed.length - 1) {
        breedString += breed[i].$t;
      } else {
        breedString += breed[i].$t + '/';
      }
    }
    breed = breedString;
  }

  if (singleBreed === true) {
    breed = breed.$t ? breed.$t : 'doggie';
  }
  return breed;
}

function pickPic(photos) {
  photo = 0;
  while (photos[photo]['@size'] !== 'x') {
    photo++;
    if (photo === photos.length) {
      getRequest();
    }
    picture = photos[photo].$t;
  }
}

function link(idNumber) {
  return "https://www.petfinder.com/petdetail/" + idNumber + "/";
}

function sex(whichSex) {
  if (whichSex === 'F') {
    return "female";
  }
  else if (whichSex === 'M') {
    return "male";
  }
}

function mix(isMix) {
  if (isMix === 'yes' && breed !== 'doggie') {
    return " mix";
  }
  else {
    return "";
  }
}

getRequest();
<commit_msg>Finished refactoring code<commit_after>var request = require('request'),
    twitter_update_with_media = require('./twitter_update_with_media'),
    twitterAPI = require('node-twitter-api'),
    config = require('./config');

var tuwm = new twitter_update_with_media({
  consumer_key: config.consumer_key,
  consumer_secret: config.consumer_secret,
  token: config.token,
  token_secret: config.token_secret,
});

var twitter = new twitterAPI({
  consumerKey: config.consumer_key,
  consumerSecret: config.consumer_secret,
  callback: ''
});

var getRequest = function() {
  var petFinderKey = config.petfinder_key,
      offset = Math.round(Math.random() * 1999),
      url = 'http://api.petfinder.com/pet.find?key=' + petFinderKey + '&animal=dog&location=new%20york%20ny&count=1&offset=' + offset + '&output=full&format=json';

  request(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var parsedData = JSON.parse(body),
          dogData = parsedData.petfinder.pets.pet,
          oneDoggie,
          buddyTweet = createTweet(dogData);

      if (Object.getOwnPropertyNames(dogData.media).length === 0) {
        postTweetText(buddyTweet);
        //console.log(buddyTweet);
      } else {
        var picArray = dogData.media.photos.photo,
            picture = pickPic(picArray);

        postTweetPic(buddyTweet, picture);
        //console.log(buddyTweet + " || " + picture);
      }
    } else {
      console.log('Error!');
    }
  });
};

var postTweetPic = function(tweetText, tweetPic) {
  tuwm.post(tweetText, tweetPic, function(err, response) {
    if (err) {
      console.log(err);
    }
    console.log(tweetText + " || " + tweetPic);
  });
};

var postTweetText = function(tweetText) {
  twitter.statuses("update", {
    status: tweetText
  },
  config.token,
  config.token_secret,
  function(error, data, response) {
    if (error) {
      console.log(error);
    }
    else {
      console.log(tweetText);
    }
  });
};

function createTweet(dogData) {
  var name = formatName(dogData.name.$t),
      sex = whichSex(dogData.sex.$t),
      breed = pickBreed(dogData.breeds.breed),
      mix = whichMix(dogData.mix.$t, breed),
      id = link(dogData.id.$t),
      startPhrase = beginningOfSentence(name, sex, breed, mix),
      endPhrase = endOfSentence(oneDoggie),
      returnTweet = startPhrase + endPhrase + " " + id;
  return returnTweet;
}

function beginningOfSentence(name, sex, breed, mix) {

  if (name.indexOf('&') > -1 || name.indexOf(' and ') > -1) {
    if (name.indexOf('-') > -1 || name.indexOf('~') > -1 || name.indexOf('(') > -1 && name.indexOf(')') > -1) {
      oneDoggie = true;
      startPhrase = name + " is a " + sex + " " + breed + mix;
    }
    else {
      oneDoggie = false;
      startPhrase = name + " are doggies";
    }
  }
  else {
    oneDoggie = true;
    startPhrase = name + " is a " + sex + " " + breed + mix;
  }
  return startPhrase;
}

function endOfSentence(oneDoggie) {
  var phrases;

  if (oneDoggie === false) {
    phrases = [' who need a loving home!', ' looking for a new family!', ' looking for a furever home!', ' who need a new best friend!', ' who need a place to call home!', ' looking for a forever home!', ' who want to be your buddies!', ' looking for a loving family!', ' in need of love!', ' in need of a loving home!', ' looking for a new home!', ' who need some lovin\'!', ' who could be your new buddies!'];
  }
  else if (oneDoggie === true) {
    phrases = [' who needs a loving home!', ' looking for a new family!', ' looking for a furever home!', ' who needs a new best friend!', ' who needs a place to call home!', ' looking for a forever home!', ' who wants to be your buddy!', ' looking for a loving family!', ' in need of love!', ' in need of a loving home!', ' looking for a new home!', ' who needs some lovin\'!', ' who could be your new buddy!'];
  }
  endPhrase = phrases[Math.floor(Math.random() * phrases.length)];
  return endPhrase;
}

function formatName(petName) {
  if (petName.match(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|zzz|[0-9]|#/gi) !== null && petName.match(/\/|[(]|[)]|[\[\]]|-|–|—|[*]/gi) === null) {
    petName = petName.replace(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|zzz|[0-9]|#/gi, '');
  }
  else if (petName.match(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|dob |zzz|[0-9]|#/gi) !== null && petName.match(/\/|[(]|[)]|[\[\]]|-|–|—|[*]/gi) !== null) {
    petName = petName.replace(/zzcourtesy|zzzcourtesy|zz courtesy|zzz courtesy|coutesy|courtesy|listing|posting|post|dob |zzz|[0-9]|#|\/|[(]|[)]|[\[\]]|-|–|—|[*]/gi, '');
  }
  // Filter for formatting caps/lowercase letters in name, if desired. People are unpredictable, and more cases can be added as needed
  // petName = petName.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
  // petName = petName.replace(/ And /gi, function(i) { return i.toLowerCase(); });
  // petName = petName.replace(/ Or /gi, function(j) { return j.toLowerCase(); });
  // petName = petName.replace(/ Asap/gi, function(k) { return k.toUpperCase(); });
  // petName = petName.replace(/ Aka /gi, function(l) { return l.toUpperCase(); });
  // petName = petName.replace(/ Fka /gi, function(l) { return l.toUpperCase(); });
  // petName = petName.replace(/ Bff /gi, " BFF ");
  // petName = petName.replace(/ Bffs /gi, " BFFs ");
  // petName = petName.replace(/\s+/g,' ').trim();
  // if (petName.length === 2 && petName !== "Al" && petName !== "Bo") {
  //   petName = petName.toUpperCase();
  // }
  return petName;
}

function pickBreed(breed) {
  var singleBreed = true;

  if (breed.length) {
    var breedString = '';
    singleBreed = false;

    for (var i = 0; i < breed.length; i++) {

      if(i === breed.length - 1) {
        breedString += breed[i].$t;
      } else {
        breedString += breed[i].$t + '/';
      }
    }
    breed = breedString;
  }

  if (singleBreed === true) {
    breed = breed.$t ? breed.$t : 'doggie';
  }
  return breed;
}

function pickPic(photos) {
  photo = 0;
  while (photos[photo]['@size'] !== 'x') {
    photo++;
    if (photo === photos.length) {
      getRequest();
    }
    return photos[photo].$t;
  }
}

function link(idNumber) {
  return "https://www.petfinder.com/petdetail/" + idNumber + "/";
}

function whichSex(sex) {
  if (sex === 'F') {
    return "female";
  }
  else if (sex === 'M') {
    return "male";
  }
}

function whichMix(isMix, breed) {
  if (isMix === 'yes' && breed !== 'doggie') {
    return " mix";
  }
  else {
    return "";
  }
}

getRequest();
<|endoftext|>