<commit_before>var ocargo = ocargo || {};

var DEFAULT_CODE = "import van\n\nv = van.Van()\n";
var appendCodeToPanel = function(code, panel) {
	panel.setValue(DEFAULT_CODE + code.replace(/<br\s*[\/]?>/gi, '\n'));
};

ocargo.PythonControl = function() {
    /***********/
    /** State **/
    /***********/

    var codePanel;
    var console;

    /********************/
    /** Public methods **/
    /********************/

    this.run = function() {
        ocargo.model.reset(0);
        Sk.failed = false;

        try {
            Sk.importMainWithBody("<stdin>", false, codePanel.getValue());
            if (!Sk.failed) {
                ocargo.model.programExecutionEnded();
            }
        } catch(e) {
            outf(e.toString() + "\n");
        }
    };

    this.prepare = function() {
        return {
            success: true,
            program:{run: this.run},
        };
    };

    this.reset = function() {
        this.clearCodePanel();
        this.clearConsole();
    };

    this.clearCodePanel = function() {
        this.setCode(DEFAULT_CODE);
    };

    this.clearConsole = function() {
        console.text("");
    };

    this.appendToConsole = function(str) {
        console.text(console.text() + str);
    };

    this.setCode = function(code) {
        codePanel.setValue(code.replace(/<br\s*[\/]?>/gi, '\n'));
    };

    this.appendCode = function(code) {
    	appendCodeToPanel(code, codePanel);
    };

    this.getCode = function() {
        return codePanel.getValue();
    };

    this.loadPreviousAttempt = function() {
        function decodeHTML(text) {
            var e = document.createElement('div');
            e.innerHTML = text;
            return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
        }
        if (PYTHON_WORKSPACE) {
            this.setCode(PYTHON_WORKSPACE);
        } else {
            try {
                this.setCode(
                    localStorage.getItem('pythonWorkspace-' + LEVEL_ID));
            } catch (e) {
                this.reset();
            }
        }
    };

    this.teardown = function() {
        if (localStorage && !ANONYMOUS) {
            var text = this.getCode();
            try {
                localStorage.setItem('pythonWorkspace-' + LEVEL_ID, text);

            } catch (e) {
                // No point in even logging, as page is unloading
            }
        }
    };

    /*********************/
    /** Private methods **/
    /*********************/

    function createCodePanel(id) {
        var cm = CodeMirror.fromTextArea(document.getElementById(id), {
            parserfile: ["parsepython.js"],
            autofocus: true,
            theme: "eclipse",
            lineNumbers: true,
            textWrapping: false,
            indentUnit: 2,
            tabSize: 2,
            height: "160px",
            fontSize: "9pt",
            autoMatchParens: true,
            parserConfig: {pythonVersion: 2, strictErrors: true}
        });

        cm.addKeyMap({
            Tab: function (cm) {
                if (cm.somethingSelected()) {
                    cm.indentSelection("add");
                } else {
                    cm.execCommand("insertSoftTab");
                }
            },
            "Shift-Tab": function (cm) {
                cm.indentSelection("subtract");
            }
        });

        return cm;
    }

    function builtinRead(x) {
        if (Sk.builtinFiles === undefined || Sk.builtinFiles.files[x] === undefined) {
            throw "File not found: '" + x + "'";
        }
        return Sk.builtinFiles.files[x];
    }

    function outf (outputText) {
        ocargo.animation.appendAnimation({
            type: 'console',
            text: outputText
        });
    }

    /*************************/
    /** Initialisation code **/
    /*************************/
    codePanel = createCodePanel('code');
    console = $('#consoleOutput');

    var codeView = createCodePanel('pythonView');
    codeView.setValue(DEFAULT_CODE);
    codeView.setOption("readOnly", "nocursor");
    setInterval(function(){appendCodeToPanel(ocargo.blocklyCompiler.workspaceToPython(), codeView);}, 100);

    // Limit the code so that it stops after 2 seconds
    Sk.execLimit = 2000;

    // Configure Skulpt
    Sk.configure({output: outf, read: builtinRead});
    //Sk.canvas = "mycanvas";
    Sk.pre = "consoleOutput";

    this.reset();
};
<commit_msg>Formatted pythonControl.js<commit_after>var ocargo = ocargo || {};

var DEFAULT_CODE = "import van\n\nv = van.Van()\n";
var appendCodeToPanel = function (code, panel) {
    panel.setValue(DEFAULT_CODE + code.replace(/<br\s*[\/]?>/gi, '\n'));
};

ocargo.PythonControl = function () {
    /***********/
    /** State **/
    /***********/

    var codePanel;
    var console;

    /********************/
    /** Public methods **/
    /********************/

    this.run = function () {
        ocargo.model.reset(0);
        Sk.failed = false;

        try {
            Sk.importMainWithBody("<stdin>", false, codePanel.getValue());
            if (!Sk.failed) {
                ocargo.model.programExecutionEnded();
            }
        } catch (e) {
            outf(e.toString() + "\n");
        }
    };

    this.prepare = function () {
        return {
            success: true,
            program: {run: this.run},
        };
    };

    this.reset = function () {
        this.clearCodePanel();
        this.clearConsole();
    };

    this.clearCodePanel = function () {
        this.setCode(DEFAULT_CODE);
    };

    this.clearConsole = function () {
        console.text("");
    };

    this.appendToConsole = function (str) {
        console.text(console.text() + str);
    };

    this.setCode = function (code) {
        codePanel.setValue(code.replace(/<br\s*[\/]?>/gi, '\n'));
    };

    this.appendCode = function (code) {
        appendCodeToPanel(code, codePanel);
    };

    this.getCode = function () {
        return codePanel.getValue();
    };

    this.loadPreviousAttempt = function () {
        function decodeHTML(text) {
            var e = document.createElement('div');
            e.innerHTML = text;
            return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
        }

        if (PYTHON_WORKSPACE) {
            this.setCode(PYTHON_WORKSPACE);
        } else {
            try {
                this.setCode(
                    localStorage.getItem('pythonWorkspace-' + LEVEL_ID));
            } catch (e) {
                this.reset();
            }
        }
    };

    this.teardown = function () {
        if (localStorage && !ANONYMOUS) {
            var text = this.getCode();
            try {
                localStorage.setItem('pythonWorkspace-' + LEVEL_ID, text);

            } catch (e) {
                // No point in even logging, as page is unloading
            }
        }
    };

    /*********************/
    /** Private methods **/
    /*********************/

    function createCodePanel(id) {
        var cm = CodeMirror.fromTextArea(document.getElementById(id), {
            parserfile: ["parsepython.js"],
            autofocus: true,
            theme: "eclipse",
            lineNumbers: true,
            textWrapping: false,
            indentUnit: 2,
            tabSize: 2,
            height: "160px",
            fontSize: "9pt",
            autoMatchParens: true,
            parserConfig: {pythonVersion: 2, strictErrors: true}
        });

        cm.addKeyMap({
            Tab: function (cm) {
                if (cm.somethingSelected()) {
                    cm.indentSelection("add");
                } else {
                    cm.execCommand("insertSoftTab");
                }
            },
            "Shift-Tab": function (cm) {
                cm.indentSelection("subtract");
            }
        });

        return cm;
    }

    function builtinRead(x) {
        if (Sk.builtinFiles === undefined || Sk.builtinFiles.files[x] === undefined) {
            throw "File not found: '" + x + "'";
        }
        return Sk.builtinFiles.files[x];
    }

    function outf(outputText) {
        ocargo.animation.appendAnimation({
            type: 'console',
            text: outputText
        });
    }

    /*************************/
    /** Initialisation code **/
    /*************************/
    codePanel = createCodePanel('code');
    console = $('#consoleOutput');

    var codeView = createCodePanel('pythonView');
    codeView.setValue(DEFAULT_CODE);
    codeView.setOption("readOnly", "nocursor");
    setInterval(function () {
        appendCodeToPanel(ocargo.blocklyCompiler.workspaceToPython(), codeView);
    }, 100);

    // Limit the code so that it stops after 2 seconds
    Sk.execLimit = 2000;

    // Configure Skulpt
    Sk.configure({output: outf, read: builtinRead});
    //Sk.canvas = "mycanvas";
    Sk.pre = "consoleOutput";

    this.reset();
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    "PRODUCT_NAME"                   : "Edge Web Fonts",

    "DIALOG_DONE"                    : "Done",
    "SEARCH_PLACEHOLDER"             : "Search",
    "BROWSE_FONTS_INSTRUCTIONS"      : "Browse for and select the web font you wish to include in your web project.",
    "CODEHINT_BROWSE"                : "Browse Web Fonts...", // Needs to be short to fit in popup, but not sure about acronym
    "GENERATE_INCLUDE_TOOLTIP"       : "Generate Edge Web Fonts Embed Code",
    "WEBFONTS_OFFLINE"               : "The Edge Web Fonts extension is disabled because the Web Fonts server cannot be reached. Please check your internet connection or try again later.",
    "INCLUDE_INSTRUCTIONS"           : "To ensure the fonts on your site load correctly, add this script tag to the <head> of any HTML files that reference this CSS file.",
    "HOWTO_INSTRUCTIONS_1"           : "Edge Web Fonts gives you access to a library of web fonts made possible by contributions from Adobe, Google, and designers around the world. The fonts are served by Typekit, free for use on your website.",
    "HOWTO_INSTRUCTIONS_2"           : "When specifying a font-family property in a CSS document, select 'Browse Web Fonts' from the code completion drop-down to browse for free online web fonts.",
    "HOWTO_INSTRUCTIONS_3"           : "When you're done, click the

 icon in the top right to generate the required embed code.",
    "HOWTO_INSTRUCTIONS_4"           : "Paste the embed code into any HTML page to include the fonts.",
    "HOWTO_DIAGRAM_IMAGE"            : "img/ewf-howto-dialog-en.png",
    "HOWTO_DIAGRAM_IMAGE_HIDPI"      : "img/ewf-howto-dialog-en@2x.png",
    "TERMS_OF_USE"                   : "Edge Web Fonts Terms of Use",
    "SAMPLE_TEXT"                    : "Sample",

    // Font classifications
    "serif"                    : "Serif",
    "sans-serif"               : "Sans-Serif",
    "slab-serif"               : "Slab-Serif",
    "script"                   : "Script",
    "blackletter"              : "Blackletter",
    "monospaced"               : "Monospaced",
    "handmade"                 : "Handmade",
    "decorative"               : "Decorative",
    "headings"                 : "Headings",
    "paragraphs"               : "Paragraphs"
});
<commit_msg>replace deprecated clickable-link class with simple href<commit_after>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    "PRODUCT_NAME"                   : "Edge Web Fonts",

    "DIALOG_DONE"                    : "Done",
    "SEARCH_PLACEHOLDER"             : "Search",
    "BROWSE_FONTS_INSTRUCTIONS"      : "Browse for and select the web font you wish to include in your web project.",
    "CODEHINT_BROWSE"                : "Browse Web Fonts...", // Needs to be short to fit in popup, but not sure about acronym
    "GENERATE_INCLUDE_TOOLTIP"       : "Generate Edge Web Fonts Embed Code",
    "WEBFONTS_OFFLINE"               : "The Edge Web Fonts extension is disabled because the Web Fonts server cannot be reached. Please check your internet connection or try again later.",
    "INCLUDE_INSTRUCTIONS"           : "To ensure the fonts on your site load correctly, add this script tag to the <head> of any HTML files that reference this CSS file.",
    "HOWTO_INSTRUCTIONS_1"           : "Edge Web Fonts gives you access to a library of web fonts made possible by contributions from Adobe, Google, and designers around the world. The fonts are served by Typekit, free for use on your website.",
    "HOWTO_INSTRUCTIONS_2"           : "When specifying a font-family property in a CSS document, select 'Browse Web Fonts' from the code completion drop-down to browse for free online web fonts.",
    "HOWTO_INSTRUCTIONS_3"           : "When you're done, click the

 icon in the top right to generate the required embed code.",
    "HOWTO_INSTRUCTIONS_4"           : "Paste the embed code into any HTML page to include the fonts.",
    "HOWTO_DIAGRAM_IMAGE"            : "img/ewf-howto-dialog-en.png",
    "HOWTO_DIAGRAM_IMAGE_HIDPI"      : "img/ewf-howto-dialog-en@2x.png",
    "TERMS_OF_USE"                   : "Edge Web Fonts Terms of Use",
    "SAMPLE_TEXT"                    : "Sample",

    // Font classifications
    "serif"                    : "Serif",
    "sans-serif"               : "Sans-Serif",
    "slab-serif"               : "Slab-Serif",
    "script"                   : "Script",
    "blackletter"              : "Blackletter",
    "monospaced"               : "Monospaced",
    "handmade"                 : "Handmade",
    "decorative"               : "Decorative",
    "headings"                 : "Headings",
    "paragraphs"               : "Paragraphs"
});
<|endoftext|>


<commit_before>const co = require('co');
const mkdirp = require('mkdirp');
const promisify = require('es6-promisify');
const through2 = require('through2');
const { readdir } = require('fs');
const { join } = require('path');
const { ncp } = require('ncp2');

// `create-wxapp` init
exports.run = co.wrap(function *(argv, clt) {
	try {
		// 小程序项目名称
		let projectName;

		// 是否集成 underscore 类库到项目
		let integrateUnderscore = false;

		// 提示：输入小程序项目名称
		while (true) {
			let answer = yield clt.getInput('请输入小程序项目名称: ');
			answer = answer.trim();

			if (/^[-\w]{3,30}$/.test(answer)) {
				projectName = answer;
				break;
			} else {
				console.log('项目名称输入错误，请重新输入（格式：3 ~ 30 位字母）！\n');
			}
		}

		// 提示：是否集成 underscore 类库到项目
		while (true) {
			let answer = yield clt.getInput('是否集成 underscore 类库到项目？(Y/n) ');
			answer = answer.trim();

			if (['yes', 'no', 'Y', 'n'].includes(answer)) {
				integrateUnderscore = ({ yes: true, no: false, Y: true, n: false })[answer];
				break;
			} else {
				console.log('请输入 Y(yes) 或者 n(no)！\n');
			}
		}

		// 源目录 及 安装目录
		const packageDir = join(__dirname, '../../package');
		const releaseDir = join(process.cwd(), projectName);

		// 新建目标目录
		yield promisify(mkdirp)(releaseDir);

		// 判断目标目录是否为空？
		const files = yield promisify(readdir)(releaseDir);
		if (files.length) {
			console.error(`目录 ${releaseDir} 不为空，操作取消！`);
			return;
		}

		yield promisify(ncp)(packageDir, releaseDir, {
			stopOnErr: true,

			filter(target) {
				target = target.split(/\\/).join('/');

				if (target.includes('/package/node_modules')) {
					return false;
				}

				if (!integrateUnderscore) {
					if (target.includes('/package/src/vendor/underscore.js')) {
						return false;
					}
				}

				return true;
			},

			rename(target) {
				target = target.replace('editorconfig.template', '.editorconfig');
				target = target.replace('gitignore.template', '.gitignore');
				return target;
			},

			transform(readStream, writeStream, file) {
				const filename = file.name.split(/\\/).join('/');

				readStream
					.pipe(through2(function (chunk, enc, callback) {
						let str = chunk.toString('utf8');

						if (!integrateUnderscore) {
							if (filename.includes('/package/src/globals.js')) {
								str = str.replace(`\t_: require('./vendor/underscore'),\n`, '');
								str = str.replace(`\t_,\n`, '');
							}

							if (filename.includes('/package/runner/config/default.js')) {
								str = str.replace(`\t\t'_',\n`, '');
							}
						}

						this.push(str);
						callback();
					}))
					.pipe(writeStream);
			},
		});

		console.log(done(projectName));
	} catch (err) {
		console.log(err);
	}
});

const done = projectName => `
Well done，项目初始化成功!!

接下来，你可以进行如下操作：

1) 安装构建依赖
$ cd ${projectName}
$ npm i -d

2) 执行构建
$ npm run dev

3) 打开微信开发者工具，添加小程序项目，项目目录指定如下:
${join(process.cwd(), projectName, 'debug')}
`;<commit_msg>脚手架添加 `是否注入全局的 `pify` 方法` 选项<commit_after>const co = require('co');
const mkdirp = require('mkdirp');
const promisify = require('es6-promisify');
const through2 = require('through2');
const { readdir } = require('fs');
const { join } = require('path');
const { ncp } = require('ncp2');

// `create-wxapp` init
exports.run = co.wrap(function *(argv, clt) {
	try {
		// 小程序项目名称
		let projectName;

		// 是否集成 `underscore` 类库到项目
		let integrateUnderscore = false;

		// 是否注入全局的 `pify` 方法
		let useGlobalPify = false;

		// 提示：输入小程序项目名称
		while (true) {
			let answer = yield clt.getInput('请输入小程序项目名称: ');
			answer = answer.trim();

			if (/^[-\w]{3,30}$/.test(answer)) {
				projectName = answer;
				break;
			} else {
				console.log('项目名称输入错误，请重新输入（格式：3 ~ 30 位字母）！\n');
			}
		}

		// 提示：是否集成 `underscore` 类库到项目
		while (true) {
			let answer = yield clt.getInput('是否集成 underscore 类库到项目？(Y/n) ');
			answer = answer.trim();

			if (['yes', 'no', 'Y', 'n'].includes(answer)) {
				integrateUnderscore = ({ yes: true, no: false, Y: true, n: false })[answer];
				break;
			} else {
				console.log('请输入 Y(yes) 或者 n(no)！\n');
			}
		}

		// 提示：是否注入全局的 `pify` 方法
		while (true) {
			let answer = yield clt.getInput('是否注入全局的 pify 方法？(Y/n) ');
			answer = answer.trim();

			if (['yes', 'no', 'Y', 'n'].includes(answer)) {
				useGlobalPify = ({ yes: true, no: false, Y: true, n: false })[answer];
				break;
			} else {
				console.log('请输入 Y(yes) 或者 n(no)！\n');
			}
		}

		// 源目录 及 安装目录
		const packageDir = join(__dirname, '../../package');
		const releaseDir = join(process.cwd(), projectName);

		// 新建目标目录
		yield promisify(mkdirp)(releaseDir);

		// 判断目标目录是否为空？
		const files = yield promisify(readdir)(releaseDir);
		if (files.length) {
			console.error(`目录 ${releaseDir} 不为空，操作取消！`);
			return;
		}

		yield promisify(ncp)(packageDir, releaseDir, {
			stopOnErr: true,

			filter(target) {
				target = target.split(/\\/).join('/');

				if (target.includes('/package/node_modules')) {
					return false;
				}

				if (!integrateUnderscore) {
					if (target.includes('/package/src/vendor/underscore.js')) {
						return false;
					}
				}

				return true;
			},

			rename(target) {
				target = target.replace('editorconfig.template', '.editorconfig');
				target = target.replace('gitignore.template', '.gitignore');
				return target;
			},

			transform(readStream, writeStream, file) {
				const filename = file.name.split(/\\/).join('/');

				readStream
					.pipe(through2(function (chunk, enc, callback) {
						let str = chunk.toString('utf8');

						if (!integrateUnderscore) {
							if (filename.includes('/package/src/globals.js')) {
								str = str.replace(`\n\t_: require('./vendor/underscore'),`, '');
							}

							if (filename.includes('/package/runner/config/default.js')) {
								str = str.replace(`\t\t'_',\n`, '');
							}
						}

						if (!useGlobalPify) {
							if (filename.includes('/package/src/globals.js')) {
								str = str.replace(`\n\nglobal.pify = require('./lib/wx-pify');`, '');
							}

							if (filename.includes('/package/runner/config/default.js')) {
								str = str.replace(`\t\t'pify',\n`, '');
							}
						}

						this.push(str);
						callback();
					}))
					.pipe(writeStream);
			},
		});

		console.log(done(projectName));
	} catch (err) {
		console.log(err);
	}
});

const done = projectName => `
Well done，项目初始化成功!!

接下来，你可以进行如下操作：

1) 安装构建依赖
$ cd ${projectName}
$ npm i -d

2) 执行构建
$ npm run dev

3) 打开微信开发者工具，添加小程序项目，项目目录指定如下:
${join(process.cwd(), projectName, 'debug')}
`;<|endoftext|>


<commit_before>const moment = require('moment-timezone')
const twitchAPI = require('./twitchAPI')
const Archive = require('./mongo').ArchivedVideoLengths
const _ = require('lodash')

async function update() {
  const { body } = await twitchAPI.getArchivesKraken()
  const { videos } = body
  const operations = []
  videos.forEach((video) => {
    operations.push({
      updateOne: {
        filter: { videoId: video.broadcast_id },
        update: {
          videoId: video.broadcast_id,
          createdAt: video.created_at,
          length: video.length,
        },
        upsert: true,
      },
    })
  })
  if (operations.length === 0) return
  await Archive.bulkWrite(operations)
}

async function getHoursThisQuarter() {
  const startOfQuarter = moment.tz('America/Los_Angeles').startOf('quarter')
  const endOfQuarter = moment.tz('America/Los_Angeles').endOf('quarter')
  const startOfLastQuarter = moment(startOfQuarter)
    .subtract(1, 'quarter')
    .startOf('quarter')
  const endOfLastQuarter = moment(endOfQuarter)
    .subtract(1, 'quarter')
    .endOf('quarter')
  return {
    thisQuarter: await getHours(startOfQuarter, endOfQuarter),
    lastQuarter: await getHours(startOfLastQuarter, endOfLastQuarter),
  }
}

async function getHours(start, end) {
  const videos = await Archive.find({
    createdAt: { $gte: start, $lte: end },
  })
  const sum = videos.reduce((prev, next) => {
    return prev + next.length
  }, 0)
  const duration = moment.duration(sum, 'seconds')
  return Math.round(duration.asHours())
}

module.exports = () => {
  // Process videos every 20 minutes
  update().catch()
  setInterval(update, 1000 * 60 * 20)
  return {
    getHoursThisQuarter,
  }
}
<commit_msg>subtract a month from quarters<commit_after>const moment = require('moment-timezone')
const twitchAPI = require('./twitchAPI')
const Archive = require('./mongo').ArchivedVideoLengths
const _ = require('lodash')

async function update() {
  const { body } = await twitchAPI.getArchivesKraken()
  const { videos } = body
  const operations = []
  videos.forEach((video) => {
    operations.push({
      updateOne: {
        filter: { videoId: video.broadcast_id },
        update: {
          videoId: video.broadcast_id,
          createdAt: video.created_at,
          length: video.length,
        },
        upsert: true,
      },
    })
  })
  if (operations.length === 0) return
  await Archive.bulkWrite(operations)
}

async function getHoursThisQuarter() {
  const startOfQuarter = moment
    .tz('America/Los_Angeles')
    .startOf('quarter')
    .subtract(1, 'month')
    .startOf('month')
  const endOfQuarter = moment
    .tz('America/Los_Angeles')
    .endOf('quarter')
    .subtract(1, 'month')
    .endOf('month')
  const startOfLastQuarter = moment
    .tz('America/Los_Angeles')
    .startOf('quarter')
    .subtract(1, 'quarter')
    .subtract(1, 'month')
    .startOf('month')
  const endOfLastQuarter = moment
    .tz('America/Los_Angeles')
    .endOf('quarter')
    .subtract(1, 'quarter')
    .subtract(1, 'month')
    .endOf('month')
  return {
    thisQuarter: await getHours(startOfQuarter, endOfQuarter),
    lastQuarter: await getHours(startOfLastQuarter, endOfLastQuarter),
  }
}

async function getHours(start, end) {
  const videos = await Archive.find({
    createdAt: { $gte: start, $lte: end },
  })
  const sum = videos.reduce((prev, next) => {
    return prev + next.length
  }, 0)
  const duration = moment.duration(sum, 'seconds')
  return Math.round(duration.asHours())
}

module.exports = () => {
  // Process videos every 20 minutes
  update().catch()
  setInterval(update, 1000 * 60 * 20)
  return {
    getHoursThisQuarter,
  }
}
<|endoftext|>


<commit_before>'use strict';

var titleize = require('titleize');
var chalk = require('chalk');
var Registry = require('npm-registry');
var npm = new Registry({ retries: 4 });

var utils = require('./utils');
var errorHandler = require('./errorHandler');

var NPM_CARTRIDGE_TASK_KEYWORD = 'cartridge-task';

var _cartridgeTaskModules;
var _promptOptions = [];
var _log;

var promptOptionsApi = {};

promptOptionsApi.setup = function(options) {
	_log = utils.getLogInstance(options);
}

promptOptionsApi.getNewCommandPromptOptions = function() {
	_log.debug('');
	_log.debug('Getting prompt options data');

	return getCartridgeTaskModulesFromNpm()
		.then(setPromptOptionsData);
}

function getCartridgeTaskModulesFromNpm() {

	return new Promise(function(resolve, reject) {

		_log.debug('Getting cartridge task modules from npm registry');

		npm.packages.keyword(NPM_CARTRIDGE_TASK_KEYWORD, function(err, data) {
			if(err) errorHandler(err);

			_cartridgeTaskModules = formatModuleData(data);

			resolve();
		});

	})
}

/**
 * Go through all modules and combine the name and description into one key.
 * @param  {Array} moduleData Module data from npm registry
 * @return {Array}            Formatted module data
 */
function formatModuleData(moduleData) {
	return moduleData.map(function(module) {
	   var formattedModule = {};
	   formattedModule.name = ' ' + module.name + ' - ' + module.description;
	   return formattedModule;
	})
}

function setPromptOptionsData() {
	_log.debug('Setting prompt options data');

	_promptOptions.push(getProjectTypePromptOptions());
	_promptOptions.push(getProjectNamePromptOptions());
	_promptOptions.push(getProjectAuthorPromptOptions());
	_promptOptions.push(getProjectDescriptionPromptOptions());
	_promptOptions.push(getCartridgeModulesPromptOptions());
	_promptOptions.push(getUserConfirmCopyPromptOptions());

	return Promise.resolve(_promptOptions);
}

function getCartridgeModulesPromptOptions() {
	return {
		type: 'checkbox',
		name: 'cartridgeModules',
		message: 'What modules would you like included?',
		choices: _cartridgeTaskModules,
		filter: extractModuleNames
	}
}

function extractModuleNames(values) {
	var moduleNames = [];

	values.forEach(function (value) {
		var regex = /\s([^\s]+)\s.*/g;
		var matches = regex.exec(value);
		moduleNames.push(matches[1]);
	});

	return moduleNames;
}

function getProjectTypePromptOptions() {
	return {
		type: 'list',
		name: 'projectType',
		message: 'What is the project type?',
		choices: [
			'Dot NET',
			'Static Website'
		]
	}
}

function getProjectNamePromptOptions() {
	return {
		type: 'input',
		name: 'projectName',
		message: 'What is the project name?',
		validate: function(value) { return inputNotEmpty(value, 'Project Name'); },
	}
}

function getProjectAuthorPromptOptions() {
	return {
		type: 'input',
		name: 'projectAuthor',
		message: 'Who is the author of the project?',
		validate: function(value) { return inputNotEmpty(value, 'Author'); },
		filter: function(value) { return titleize(value); }
	}
}

function getProjectDescriptionPromptOptions() {
	return {
		type: 'input',
		name: 'projectDescription',
		message: 'What is the project description?',
		default: function () { return ''; }
	}
}

function getUserConfirmCopyPromptOptions() {
	return {
		type: 'confirm',
		name: 'isOkToCopyFiles',
		message: 'Ready to start setup! Press enter to confirm',
		default: true
	}
}

function inputNotEmpty(value, fieldName) {
	var isValid = (value !== '');

	return (isValid) ? true : fieldName + ' cannot be empty' ;
}

module.exports = promptOptionsApi;<commit_msg>feat: base spike for modules, comments<commit_after>'use strict';

var titleize = require('titleize');
var chalk = require('chalk');
var Registry = require('npm-registry');
var npm = new Registry({ retries: 4 });

var utils = require('./utils');
var errorHandler = require('./errorHandler');

var NPM_CARTRIDGE_TASK_KEYWORD = 'cartridge-task';

var _cartridgeTaskModules;
var _promptOptions = [];
var _log;

var promptOptionsApi = {};

promptOptionsApi.setup = function(options) {
	_log = utils.getLogInstance(options);
}

promptOptionsApi.getNewCommandPromptOptions = function() {
	_log.debug('');
	_log.debug('Getting prompt options data');

	return Promise.all([getCartridgeTaskModulesFromNpm(), getCartridgeDefaultModulesFromNpm()])
		.then(setPromptOptionsData);

	// return getCartridgeTaskModulesFromNpm()
	// 	.then(setPromptOptionsData);
}

function getCartridgeTaskModulesFromNpm() {

	return new Promise(function(resolve, reject) {

		_log.debug('Getting cartridge task modules from npm registry');

		npm.packages.keyword(NPM_CARTRIDGE_TASK_KEYWORD, function(err, data) {
			if(err) errorHandler(err);

			_cartridgeTaskModules = formatModuleData(data);

			resolve(data);
		});

	})
}

function getCartridgeDefaultModulesFromNpm() {

	return new Promise(function(resolve, reject) {

		_log.debug('Getting cartridge task modules from npm registry');

		npm.packages.keyword('cartridge-module', function(err, data) {
			if(err) errorHandler(err);

			_cartridgeTaskModules = formatModuleData(data);

			resolve(data);
		});

	})
}

/**
 * Go through all modules and combine the name and description into one key.
 * @param  {Array} moduleData Module data from npm registry
 * @return {Array}            Formatted module data
 */
function formatModuleData(moduleData) {
	return moduleData.map(function(module) {
	   var formattedModule = {};
	   formattedModule.name = ' ' + module.name + ' - ' + module.description;
	   return formattedModule;
	})
}

function setPromptOptionsData(data) {
	console.log('data[0]', data[0]);
	console.log('data[1]', data[1]);

	var moduleList = data[0];
	var defaultModuleList = data[1];

	moduleList.forEach(function(element, index, array) {
		con
	})

	//module data ['module-1', 'module-2']
	//loop through the module data 'module-1'

	//default module data ['module-4', 'module-1']
	//loop through default module data 'module-1'

	// if module name is in both then it is a default module!
	// if not, then it isn't (duh!)

	_log.debug('Setting prompt options data');

	_promptOptions.push(getProjectTypePromptOptions());
	_promptOptions.push(getProjectNamePromptOptions());
	_promptOptions.push(getProjectAuthorPromptOptions());
	_promptOptions.push(getProjectDescriptionPromptOptions());
	_promptOptions.push(getCartridgeModulesPromptOptions());
	_promptOptions.push(getUserConfirmCopyPromptOptions());

	return Promise.resolve(_promptOptions);
}

function getCartridgeModulesPromptOptions() {
	return {
		type: 'checkbox',
		name: 'cartridgeModules',
		message: 'What modules would you like included?',
		choices: _cartridgeTaskModules,
		filter: extractModuleNames
	}
}

function extractModuleNames(values) {
	var moduleNames = [];

	values.forEach(function (value) {
		var regex = /\s([^\s]+)\s.*/g;
		var matches = regex.exec(value);
		moduleNames.push(matches[1]);
	});

	return moduleNames;
}

function getProjectTypePromptOptions() {
	return {
		type: 'list',
		name: 'projectType',
		message: 'What is the project type?',
		choices: [
			'Dot NET',
			'Static Website'
		]
	}
}

function getProjectNamePromptOptions() {
	return {
		type: 'input',
		name: 'projectName',
		message: 'What is the project name?',
		validate: function(value) { return inputNotEmpty(value, 'Project Name'); },
	}
}

function getProjectAuthorPromptOptions() {
	return {
		type: 'input',
		name: 'projectAuthor',
		message: 'Who is the author of the project?',
		validate: function(value) { return inputNotEmpty(value, 'Author'); },
		filter: function(value) { return titleize(value); }
	}
}

function getProjectDescriptionPromptOptions() {
	return {
		type: 'input',
		name: 'projectDescription',
		message: 'What is the project description?',
		default: function () { return ''; }
	}
}

function getUserConfirmCopyPromptOptions() {
	return {
		type: 'confirm',
		name: 'isOkToCopyFiles',
		message: 'Ready to start setup! Press enter to confirm',
		default: true
	}
}

function inputNotEmpty(value, fieldName) {
	var isValid = (value !== '');

	return (isValid) ? true : fieldName + ' cannot be empty' ;
}

module.exports = promptOptionsApi;<|endoftext|>


<commit_before>// https://eslint.org/docs/user-guide/configuring

module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint'
  },
  env: {
    browser: true,
  },
  extends: [
    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
    // 'plugin:vue/essential',
    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
    'standard'
  ],
  // required to lint *.vue files
  plugins: [
    // 'vue'
  ],
  // add your custom rules here
  rules: {
    // allow async-await
    'generator-star-spacing': 'off',
    'semi': 'off',
    'no-extend-native': 'off',
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
  }
}
<commit_msg>Update eslintrc.js<commit_after>// https://eslint.org/docs/user-guide/configuring

module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint'
  },
  env: {
    browser: true,
    es6: true,
    jquery: true
  },
  extends: [
    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
    // 'plugin:vue/essential',
    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
    'standard'
  ],
  // required to lint *.vue files
  plugins: [
    // 'vue'
  ],
  // add your custom rules here
  rules: {
    // allow async-await
    'generator-star-spacing': 'off',
    semi: 'off',
    'no-extend-native': 'off',
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'comma-dangle': ['error', 'never'],
    'space-before-function-paren': [
      'error',
      {
        anonymous: 'always',
        named: 'never',
        asyncArrow: 'always'
      }
    ]
  }
};
<|endoftext|>


<commit_before>import Ember from 'ember';
var SigninValidator = Ember.Object.create({
    check: function (model) {
        var data = model.getProperties('identification', 'password'),
            validationErrors = [];

        if (!validator.isEmail(data.identification)) {
            validationErrors.push('Invalid Email');
        }

        if (!validator.isLength(data.password || '', 1)) {
            validationErrors.push('Please enter a password');
        }

        return validationErrors;
    }
});

export default SigninValidator;
<commit_msg>Provide a more intuitive error message on sign-in for missing email<commit_after>import Ember from 'ember';
var SigninValidator = Ember.Object.create({
    check: function (model) {
        var data = model.getProperties('identification', 'password'),
            validationErrors = [];

        if (validator.empty(data.identification)) {
            validationErrors.push('Please enter an email');
        } else if (!validator.isEmail(data.identification)) {
            validationErrors.push('Invalid Email');
        }

        if (!validator.isLength(data.password || '', 1)) {
            validationErrors.push('Please enter a password');
        }

        return validationErrors;
    }
});

export default SigninValidator;
<|endoftext|>


<commit_before>var Application = require('spectron').Application
var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
var path = require('path')

chai.should()
chai.use(chaiAsPromised)

var after = global.after
var before = global.before
var describe = global.describe
var it = global.it

describe('demo app', function () {
  this.timeout(30000)

  before(function () {
    this.app = new Application({
      path: path.join(__dirname, '..', 'node_modules', '.bin', 'electron'),
      args: [
        path.join(__dirname, '..')
      ],
      waitTimeout: 10000
    })
    return this.app.start()
  })

  before(function () {
    chaiAsPromised.transferPromiseness = this.app.client.transferPromiseness
  })

  after(function () {
    if (this.app && this.app.isRunning()) {
      return this.app.stop()
    }
  })

  it('opens a window displaying the about page and nav bar', function () {
    return this.app.client.waitUntilWindowLoaded()
      .getWindowCount().should.eventually.equal(1)
      .isWindowMinimized().should.eventually.be.false
      .isWindowDevToolsOpened().should.eventually.be.false
      .isWindowVisible().should.eventually.be.true
      .isWindowFocused().should.eventually.be.true
      .getWindowWidth().should.eventually.be.above(0)
      .getWindowHeight().should.eventually.be.above(0)
      .getTitle().should.eventually.equal('Electron API Demos')
      .isVisible('#about-view').should.eventually.be.true
      .isVisible('#index-view').should.eventually.be.true
  })

  describe('when clicking on a section from the nav bar', function () {
    it('shows the selected section in the main area', function () {
      return this.app.client.waitUntilWindowLoaded()
        .isVisible('#about-view').should.eventually.be.true
        .click('button[data-view="windows"]').pause(100)
        .waitForVisible('#windows-view')
        .isExisting('button.is-selected[data-view="windows"]').should.eventually.be.true
        .isVisible('#pdf-view').should.eventually.be.false
        .click('button[data-view="pdf"]').pause(100)
        .waitForVisible('#pdf-view')
        .isVisible('#windows-view').should.eventually.be.false
        .isExisting('button.is-selected[data-view="windows"]').should.eventually.be.false
        .isExisting('button.is-selected[data-view="pdf"]').should.eventually.be.true
    })
  })

  describe('when a task is clicked', function () {
    it('it expands', function () {
      var onlyFirstVisible = Array(20).fill(false)
      onlyFirstVisible[0] = true

      return this.app.client.waitUntilWindowLoaded()
        .click('button[data-view="windows"]')
        .waitForVisible('#windows-view')
        .click('.js-container-target')
        .waitForVisible('.toggle-content')
        .isVisible('.toggle-content').should.eventually.deep.equal(onlyFirstVisible)
    })
  })
})
<commit_msg>Update no of demos in spec<commit_after>var Application = require('spectron').Application
var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
var path = require('path')

chai.should()
chai.use(chaiAsPromised)

var after = global.after
var before = global.before
var describe = global.describe
var it = global.it

describe('demo app', function () {
  this.timeout(30000)

  before(function () {
    this.app = new Application({
      path: path.join(__dirname, '..', 'node_modules', '.bin', 'electron'),
      args: [
        path.join(__dirname, '..')
      ],
      waitTimeout: 10000
    })
    return this.app.start()
  })

  before(function () {
    chaiAsPromised.transferPromiseness = this.app.client.transferPromiseness
  })

  after(function () {
    if (this.app && this.app.isRunning()) {
      return this.app.stop()
    }
  })

  it('opens a window displaying the about page and nav bar', function () {
    return this.app.client.waitUntilWindowLoaded()
      .getWindowCount().should.eventually.equal(1)
      .isWindowMinimized().should.eventually.be.false
      .isWindowDevToolsOpened().should.eventually.be.false
      .isWindowVisible().should.eventually.be.true
      .isWindowFocused().should.eventually.be.true
      .getWindowWidth().should.eventually.be.above(0)
      .getWindowHeight().should.eventually.be.above(0)
      .getTitle().should.eventually.equal('Electron API Demos')
      .isVisible('#about-view').should.eventually.be.true
      .isVisible('#index-view').should.eventually.be.true
  })

  describe('when clicking on a section from the nav bar', function () {
    it('shows the selected section in the main area', function () {
      return this.app.client.waitUntilWindowLoaded()
        .isVisible('#about-view').should.eventually.be.true
        .click('button[data-view="windows"]').pause(100)
        .waitForVisible('#windows-view')
        .isExisting('button.is-selected[data-view="windows"]').should.eventually.be.true
        .isVisible('#pdf-view').should.eventually.be.false
        .click('button[data-view="pdf"]').pause(100)
        .waitForVisible('#pdf-view')
        .isVisible('#windows-view').should.eventually.be.false
        .isExisting('button.is-selected[data-view="windows"]').should.eventually.be.false
        .isExisting('button.is-selected[data-view="pdf"]').should.eventually.be.true
    })
  })

  describe('when a task is clicked', function () {
    it('it expands', function () {
      var onlyFirstVisible = Array(21).fill(false)
      onlyFirstVisible[0] = true

      return this.app.client.waitUntilWindowLoaded()
        .click('button[data-view="windows"]')
        .waitForVisible('#windows-view')
        .click('.js-container-target')
        .waitForVisible('.toggle-content')
        .isVisible('.toggle-content').should.eventually.deep.equal(onlyFirstVisible)
    })
  })
})
<|endoftext|>


<commit_before>var parallel = require('run-parallel')

function makeBuffer (num) {
  var buf = new Buffer(10)
  buf.fill(num)
  return buf
}

module.exports = function (test, Store) {
  test('basic put, then get', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, function (err, chunk) {
        t.error(err)
        t.deepEqual(chunk, new Buffer('0123456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('put invalid chunk length gives error', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123'), function (err) {
      t.ok(err instanceof Error)
      store.destroy(function (err) {
        t.error(err)
        t.end()
      })
    })
  })

  test('concurrent puts, then concurrent gets', function (t) {
    var store = new Store(10)

    function makePutTask (i) {
      return function (cb) {
        store.put(i, makeBuffer(i), cb)
      }
    }

    function makeGetTask (i) {
      return function (cb) {
        store.get(i, function (err, data) {
          if (err) return cb(err)
          t.deepEqual(data, makeBuffer(i))
          cb(null)
        })
      }
    }

    var tasks = []
    for (var i = 0; i < 100; i++) {
      tasks.push(makePutTask(i))
    }

    parallel(tasks, function (err) {
      t.error(err)

      tasks = []
      for (var i = 0; i < 100; i++) {
        tasks.push(makeGetTask(i))
      }

      parallel(tasks, function (err) {
        t.error(err)
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('interleaved puts and gets', function (t) {
    var store = new Store(10)
    var tasks = []

    function makeTask (i) {
      return function (cb) {
        store.put(i, makeBuffer(i), function (err) {
          if (err) return cb(err)
          store.get(i, function (err, data) {
            t.deepEqual(data, makeBuffer(i))
            cb(null)
          })
        })
      }
    }

    for (var i = 0; i < 100; i++) {
      tasks.push(makeTask(i))
    }

    parallel(tasks, function (err) {
      t.error(err)
      store.destroy(function (err) {
        t.error(err)
        t.end()
      })
    })
  })

  test('get with `offset` and `length` options', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, { offset: 2, length: 3 }, function (err, chunk) {
        t.error()
        t.deepEqual(chunk, new Buffer('234'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('test for sparsely populated support', function (t) {
    var store = new Store(10)
    store.put(10, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(10, function (err, chunk) {
        t.error(err)
        t.deepEqual(chunk, new Buffer('0123456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('test `put` without callback - error should be silent', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('01234'))
    store.destroy(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('test `put` without callback - success should be silent', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'))
    store.destroy(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('chunkLength property', function (t) {
    var store = new Store(10)
    t.equal(store.chunkLength, 10)
    store.destroy(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('test `get` on non-existent index', function (t) {
    var store = new Store(10)
    store.get(0, function (err, chunk) {
      t.ok(err instanceof Error)
      store.destroy(function (err) {
        t.error(err)
        t.end()
      })
    })
  })

  test('test empty store\'s `close` calls its callback', function (t) {
    var store = new Store(10)
    store.close(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('test non-empty store\'s `close` calls its callback', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'))
    store.close(function (err) {
      t.error(err)
      t.end()
    })
  })
}
<commit_msg>add more tests for different types of get opts<commit_after>var parallel = require('run-parallel')

function makeBuffer (num) {
  var buf = new Buffer(10)
  buf.fill(num)
  return buf
}

module.exports = function (test, Store) {
  test('basic put, then get', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, function (err, chunk) {
        t.error(err)
        t.deepEqual(chunk, new Buffer('0123456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('put invalid chunk length gives error', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123'), function (err) {
      t.ok(err instanceof Error)
      store.destroy(function (err) {
        t.error(err)
        t.end()
      })
    })
  })

  test('concurrent puts, then concurrent gets', function (t) {
    var store = new Store(10)

    function makePutTask (i) {
      return function (cb) {
        store.put(i, makeBuffer(i), cb)
      }
    }

    function makeGetTask (i) {
      return function (cb) {
        store.get(i, function (err, data) {
          if (err) return cb(err)
          t.deepEqual(data, makeBuffer(i))
          cb(null)
        })
      }
    }

    var tasks = []
    for (var i = 0; i < 100; i++) {
      tasks.push(makePutTask(i))
    }

    parallel(tasks, function (err) {
      t.error(err)

      tasks = []
      for (var i = 0; i < 100; i++) {
        tasks.push(makeGetTask(i))
      }

      parallel(tasks, function (err) {
        t.error(err)
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('interleaved puts and gets', function (t) {
    var store = new Store(10)
    var tasks = []

    function makeTask (i) {
      return function (cb) {
        store.put(i, makeBuffer(i), function (err) {
          if (err) return cb(err)
          store.get(i, function (err, data) {
            t.deepEqual(data, makeBuffer(i))
            cb(null)
          })
        })
      }
    }

    for (var i = 0; i < 100; i++) {
      tasks.push(makeTask(i))
    }

    parallel(tasks, function (err) {
      t.error(err)
      store.destroy(function (err) {
        t.error(err)
        t.end()
      })
    })
  })

  test('get with `offset` and `length` options', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, { offset: 2, length: 3 }, function (err, chunk) {
        t.error()
        t.deepEqual(chunk, new Buffer('234'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('get with null option', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, null, function (err, chunk) {
        t.error()
        t.deepEqual(chunk, new Buffer('0123456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('get with empty object option', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, {}, function (err, chunk) {
        t.error()
        t.deepEqual(chunk, new Buffer('0123456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('get with `offset` option', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, { offset: 2 }, function (err, chunk) {
        t.error()
        t.deepEqual(chunk, new Buffer('23456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('get with `length` option', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(0, { length: 5 }, function (err, chunk) {
        t.error()
        t.deepEqual(chunk, new Buffer('01234'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('test for sparsely populated support', function (t) {
    var store = new Store(10)
    store.put(10, new Buffer('0123456789'), function (err) {
      t.error(err)
      store.get(10, function (err, chunk) {
        t.error(err)
        t.deepEqual(chunk, new Buffer('0123456789'))
        store.destroy(function (err) {
          t.error(err)
          t.end()
        })
      })
    })
  })

  test('test `put` without callback - error should be silent', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('01234'))
    store.destroy(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('test `put` without callback - success should be silent', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'))
    store.destroy(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('chunkLength property', function (t) {
    var store = new Store(10)
    t.equal(store.chunkLength, 10)
    store.destroy(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('test `get` on non-existent index', function (t) {
    var store = new Store(10)
    store.get(0, function (err, chunk) {
      t.ok(err instanceof Error)
      store.destroy(function (err) {
        t.error(err)
        t.end()
      })
    })
  })

  test('test empty store\'s `close` calls its callback', function (t) {
    var store = new Store(10)
    store.close(function (err) {
      t.error(err)
      t.end()
    })
  })

  test('test non-empty store\'s `close` calls its callback', function (t) {
    var store = new Store(10)
    store.put(0, new Buffer('0123456789'))
    store.close(function (err) {
      t.error(err)
      t.end()
    })
  })
}
<|endoftext|>


<commit_before>/* global casper */

var dialogID = 'my-accessible-dialog';

casper.test.begin('Dialog window test suite', 37, function (test) {

  function testAriaHidden (isDialogOpen) {
    if (isDialogOpen === true) {
      test.assertDoesntExist('#main:not([aria-hidden])');
      test.assertExist('#main[aria-hidden="true"]');
      test.assertExist('#' + dialogID + ':not([aria-hidden])');
      test.assertDoesntExist('#' + dialogID + '[aria-hidden="true"]');
    } else {
      test.assertExist('#main:not([aria-hidden])');
      test.assertDoesntExist('#main[aria-hidden="true"]');
      test.assertDoesntExist('#' + dialogID + ':not([aria-hidden])');
      test.assertExist('#' + dialogID + '[aria-hidden="true"]');
    }
  }

  casper.start('http://edenspiekermann.github.io/a11y-dialog/', function () {
    this.page.onConsoleMessage = function (msg, lineNum, sourceId) {
      console.log('CONSOLE: ' + msg);
    };

    this.page.injectJs('./a11y-dialog.js');
    this.page.evaluateJavaScript('function () { window.m = new window.A11yDialog(document.getElementById("' + dialogID + '")); }');
    this.emit('page.loaded');
  });

  casper.on('page.loaded', function () {
    var dialog = '#' + dialogID;
    var opener = '[data-a11y-dialog-show="' + dialogID + '"]';
    var closer = dialog + ' [data-a11y-dialog-hide]';
    var overlay = dialog + ' > .dialog-overlay';

    this.then(function () {
      this.echo('\nTest dialog shape');
      test.assertEvalEquals(function () { return typeof window.a11yDialog; }, 'function', 'Dialog window constructor is being defined');
      test.assertEvalEquals(function () { return typeof m.hide; }, 'function', 'Dialog window instance has a `hide` method');
      test.assertEvalEquals(function () { return typeof m.show; }, 'function', 'Dialog window instance has a `show` method');
    });

    this.then(function () {
      this.echo('\nTest initial setup');
      test.assertExist(dialog, 'Dialog window element exists in the DOM');
      test.assertExist(opener, 'Dialog window opener element exists in the DOM');
      test.assertNotVisible(dialog, 'Dialog window is hidden by default');
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window opening');
      this.click(opener);
      testAriaHidden(true);
    });

    this.then(function () {
      this.echo('\nTest dialog window closing through overlay');
      this.click(overlay);
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window closing through closer');
      this.click(opener);
      this.click(closer);
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window closing through ESCAPE key');
      this.click(opener);
      this.page.sendEvent('keypress', this.page.event.key.Escape, null, null, 0);
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window opening through JS API');
      this.page.evaluateJavaScript('function () { window.m.show(); }');
      testAriaHidden(true);
    });

    this.then(function () {
      this.echo('\nTest dialog closing through JS API');
      this.page.evaluateJavaScript('function () { window.m.hide(); }');
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest focus on dialog window opening');
      this.click(opener);
      test.assertEvalEquals(function () {
        return document.activeElement.name;
      }, 'EMAIL', 'First focusable element is focused');
      this.click(closer);
    });

    this.then(function () {
      this.echo('\nTest focus trap');
      this.click(opener);
      this.page.sendEvent('keypress', this.page.event.key.Tab, null, null, 0x02000000);
      test.assertEvalEquals(function () {
        return document.activeElement.textContent;
      }, '×', 'Focus should loop inside dialog');
      this.click(closer);
    });

    this.then(function () {
      this.echo('\nTest focus on dialog window closing');
      this.page.sendEvent('keypress', this.page.event.key.Tab, null, null, 0); // Get into document
      this.page.sendEvent('keypress', this.page.event.key.Tab, null, null, 0);
      this.click(opener);
      this.click(closer);
      test.assertEvalEquals(function () {
        return document.activeElement.textContent;
      }, 'Get the code on GitHub', 'Focus should go back to where it was after dialog window closing');
    });
  });

  casper.run(function () {
    this.test.done();
    this.exit();
  });

});
<commit_msg>Fixed broken test<commit_after>/* global casper */

var dialogID = 'my-accessible-dialog';

casper.test.begin('Dialog window test suite', 37, function (test) {

  function testAriaHidden (isDialogOpen) {
    if (isDialogOpen === true) {
      test.assertDoesntExist('#main:not([aria-hidden])');
      test.assertExist('#main[aria-hidden="true"]');
      test.assertExist('#' + dialogID + ':not([aria-hidden])');
      test.assertDoesntExist('#' + dialogID + '[aria-hidden="true"]');
    } else {
      test.assertExist('#main:not([aria-hidden])');
      test.assertDoesntExist('#main[aria-hidden="true"]');
      test.assertDoesntExist('#' + dialogID + ':not([aria-hidden])');
      test.assertExist('#' + dialogID + '[aria-hidden="true"]');
    }
  }

  casper.start('http://edenspiekermann.github.io/a11y-dialog/', function () {
    this.page.onConsoleMessage = function (msg, lineNum, sourceId) {
      console.log('CONSOLE: ' + msg);
    };

    this.page.injectJs('./a11y-dialog.js');
    this.page.evaluateJavaScript('function () { window.m = new window.A11yDialog(document.getElementById("' + dialogID + '")); }');
    this.emit('page.loaded');
  });

  casper.on('page.loaded', function () {
    var dialog = '#' + dialogID;
    var opener = '[data-a11y-dialog-show="' + dialogID + '"]';
    var closer = dialog + ' [data-a11y-dialog-hide]';
    var overlay = dialog + ' > .dialog-overlay';

    this.then(function () {
      this.echo('\nTest dialog shape');
      test.assertEvalEquals(function () { return typeof window.A11yDialog; }, 'function', 'Dialog window constructor is being defined');
      test.assertEvalEquals(function () { return typeof m.hide; }, 'function', 'Dialog window instance has a `hide` method');
      test.assertEvalEquals(function () { return typeof m.show; }, 'function', 'Dialog window instance has a `show` method');
    });

    this.then(function () {
      this.echo('\nTest initial setup');
      test.assertExist(dialog, 'Dialog window element exists in the DOM');
      test.assertExist(opener, 'Dialog window opener element exists in the DOM');
      test.assertNotVisible(dialog, 'Dialog window is hidden by default');
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window opening');
      this.click(opener);
      testAriaHidden(true);
    });

    this.then(function () {
      this.echo('\nTest dialog window closing through overlay');
      this.click(overlay);
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window closing through closer');
      this.click(opener);
      this.click(closer);
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window closing through ESCAPE key');
      this.click(opener);
      this.page.sendEvent('keypress', this.page.event.key.Escape, null, null, 0);
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest dialog window opening through JS API');
      this.page.evaluateJavaScript('function () { window.m.show(); }');
      testAriaHidden(true);
    });

    this.then(function () {
      this.echo('\nTest dialog closing through JS API');
      this.page.evaluateJavaScript('function () { window.m.hide(); }');
      testAriaHidden(false);
    });

    this.then(function () {
      this.echo('\nTest focus on dialog window opening');
      this.click(opener);
      test.assertEvalEquals(function () {
        return document.activeElement.name;
      }, 'EMAIL', 'First focusable element is focused');
      this.click(closer);
    });

    this.then(function () {
      this.echo('\nTest focus trap');
      this.click(opener);
      this.page.sendEvent('keypress', this.page.event.key.Tab, null, null, 0x02000000);
      test.assertEvalEquals(function () {
        return document.activeElement.textContent;
      }, '×', 'Focus should loop inside dialog');
      this.click(closer);
    });

    this.then(function () {
      this.echo('\nTest focus on dialog window closing');
      this.page.sendEvent('keypress', this.page.event.key.Tab, null, null, 0); // Get into document
      this.page.sendEvent('keypress', this.page.event.key.Tab, null, null, 0);
      this.click(opener);
      this.click(closer);
      test.assertEvalEquals(function () {
        return document.activeElement.textContent;
      }, 'Get the code on GitHub', 'Focus should go back to where it was after dialog window closing');
    });
  });

  casper.run(function () {
    this.test.done();
    this.exit();
  });

});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jshint node:true */
/*global describe,it */
'use strict';

var chai,
    expect,
    IntlMessageFormat;

// This oddity is so that this file can be used for both client-side and
// server-side testing.  (On the client we've already loaded chai and
// IntlMessageFormat.)
if ('function' === typeof require) {
    chai = require('chai');
    IntlMessageFormat = require('../build/index.en.min.js');
    require('../locale-data/ar.js');
    require('../locale-data/pl.js');
}
expect = chai.expect;

describe('message resolvedOptions', function () {

    it('empty options', function () {
        var msg, o, p, pCount = 0;

        msg = new IntlMessageFormat('My name is ${name}');

        o = msg.resolvedOptions();

        for (p in o) {
            if (o.hasOwnProperty(p)) {
                pCount++;
            }
        }

        expect(pCount).to.equal(0);
    });
});

describe('message creation', function () {

    it('simple string formatting', function () {
        var msg, m;
        msg = new IntlMessageFormat('My name is ${first} {last}.');
        m = msg.format({
            first: 'Anthony',
            last: 'Pipkin'
        });
        expect(m).to.equal('My name is Anthony Pipkin.');
    });

    it('simple object formatting', function () {
        var msg, m;

        msg = new IntlMessageFormat(['I have ', 2, ' cars.']);

        m = msg.format();

        expect(m).to.equal('I have 2 cars.');

    });

    it('simple object with post processing tokens', function () {
        var msg, m;

        msg = new IntlMessageFormat(['${', 'company', '}', ' {', 'verb' ,'}.']);

        m = msg.format({
            company: 'Yahoo',
            verb: 'rocks'
        });

        expect(m).to.equal('Yahoo rocks.');

    });

    it ('complex object formatter', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal("Some text before Some messages for the default and text after");
    });

    it ('complex object formatter with invalid valueName', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        try {
            m = msg.format({
                jumper: 20
            });
        } catch (e) {
            var err = 'The valueName `numPeople` was not found.';
            expect(e).to.equal(err);
        }
    });

    it ('complex object formatter with offset', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            offset: 1,
            options: {
                one: 'Some message ${ph} with ${#} value',

                few: ['Optional prefix text for |few| ', {
                    type: 'select',
                    valueName: 'gender',
                    options: {
                        male: 'Text for male option with \' single quotes',
                        female: 'Text for female option with {}',
                        other: 'Text for default'
                    }
                }, ' optional postfix text'],

                other: 'Some messages for the default',

                '1': ['Optional prefix text ', {
                    type: 'select',
                    valueName: 'gender',
                    options: {
                        male: 'Text for male option with \' single quotes',
                        female: 'Text for female option with {}',
                        other: 'Text for default'
                    }
                }, ' optional postfix text'],
            }
        }, ' and text after'],
            'pl'    // this has the "few" rule that we need
        );
        m = msg.format({
            numPeople: 1,   // offset will move this to "2" so that the "few" group is used
            ph: 'whatever',
            gender: 'male'
        });
        expect(m).to.equal("Some text before Optional prefix text for |few| Text for male option with ' single quotes optional postfix text and text after");
    });

    it('Simple string formatter using a custom formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter d: ${num:d}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter d: 10');
    });

    it('Simple string formatter using an inline formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat([{
            valueName: 'str',
            formatter: function (val, locale) {
                return val.toString().split('').reverse().join('');
            }
        }]);
        m = msg.format({
            str: 'aardvark'
        });
        expect(m).to.equal('kravdraa');
    });

    it('Simple string formatter using a nonexistent formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter foo: ${num:foo}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter foo: 010');
    });

    it('Custom formatters with hidden inheritance', function () {
        var msg, m,
            Formatters = function () {
                this.d = function (val, locale) {
                    return val + '030';
                };
            },
            CustomFormatters = function () {
                this.f = function (val, locale) {
                    return val + '080';
                };
            };

        CustomFormatters.prototype = Formatters;
        CustomFormatters.prototype.constructor = CustomFormatters;

        msg = new IntlMessageFormat('d: ${num:d} / f: ${num:f}', null, new CustomFormatters());

        m = msg.format({
            num: 0
        });

        expect(m).to.equal('d: 0 / f: 0080');
    });

    it('broken pattern', function () {
       var msg, m;

        msg = new IntlMessageFormat('${name} ${formula}');

        msg.pattern = '${name} ${formula}';

        m = msg.format({
            name: 'apipkin'
        });

        expect(m).to.equal('apipkin ${formula}');

    });

});

describe('message creation for plurals', function () {
    var msg = new IntlMessageFormat(['I have ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                zero : 'zero points',
                one  : 'a point',
                two  : 'two points',
                few  : 'a few points',
                many : 'lots of points',
                other: 'some other amount of points'
            }
        }, '.'], 'ar');

    it('zero', function () {
        var m = msg.format({
            numPeople: 0
        });

        expect(m).to.equal('I have zero points.');
    });

    it('one', function () {
        var m = msg.format({
            numPeople: 1
        });

        expect(m).to.equal('I have a point.');
    });

    it('two', function () {
        var m = msg.format({
            numPeople: 2
        });

        expect(m).to.equal('I have two points.');
    });

    it('few', function () {
        var m = msg.format({
            numPeople: 5
        });

        expect(m).to.equal('I have a few points.');
    });

    it('many', function () {
        var m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal('I have lots of points.');
    });

    it('other', function () {
        var m = msg.format({
            numPeople: 100
        });

        expect(m).to.equal('I have some other amount of points.');
    });

});

describe('locale switching', function () {
    var simple = {
            en: [
                { valueName: 'NAME' },
                ' went to ',
                { valueName: 'CITY' },
                '.'
            ],
            fr: [
                { valueName: 'NAME' },
                ' est ',
                {
                    type: 'gender',
                    valueName: 'gender',
                    options: {
                        female: 'allée',
                        other: 'allé'
                    }
                },
                ' à ',
                { valueName: 'CITY' },
                '.'
            ]
        },

        complex = {
            en: '${TRAVELLERS} went to ${CITY}.',
            fr: [
                '${TRAVELLERS}',
                {
                    type: 'plural',
                    valueName: 'TRAVELLER_COUNT',
                    options: {
                        one: [' est ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allée',
                                other: 'allé'
                            }
                        }],
                        other: [' sont ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allées',
                                other: 'allés'
                            }
                        }]
                    }
                },
                ' à ',
                '${CITY}',
                '.'
            ]
        },

        maleObj = {
            NAME: 'Tony',
            CITY: 'Paris',
            gender: 'male'
        },
        femaleObj = {
            NAME: 'Jenny',
            CITY: 'Paris',
            gender: 'female'
        },

        maleTravelers = {
            TRAVELLERS: 'Lucas, Tony and Drew',
            TRAVELLER_COUNT: 3,
            GENDER: 'male',
            CITY: 'Paris'
        },

        femaleTravelers = {
            TRAVELLERS: 'Monica',
            TRAVELLER_COUNT: 1,
            GENDER: 'female',
            CITY: 'Paris'
        };

    it('en-US simple', function () {
        var msg = new IntlMessageFormat(simple.en, 'en-US');

        expect(msg.format(maleObj)).to.equal('Tony went to Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny went to Paris.');
    });

    it('fr-FR simple', function () {
        var msg = new IntlMessageFormat(simple.fr, 'fr-FR');

        expect(msg.format(maleObj)).to.equal('Tony est allé à Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny est allée à Paris.');
    });

    it('en-US complex', function () {
        var msg = new IntlMessageFormat(complex.en, 'en-US');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew went to Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica went to Paris.');
    });

    it('fr-FR complex', function () {
        var msg = new IntlMessageFormat(complex.fr, 'fr-FR');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew sont allés à Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica est allée à Paris.');
    });

});

describe('locale switching with counts', function () {

    var messages = {
            en: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                       one: 'One company',
                       other: '${#} companies'
                    }
                },
                ' published new books.'
            ],
            ru: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                        one: 'Одна компания опубликовала',
                        few: '${#} компании опубликовали',
                        many: '${#} компаний опубликовали',
                        other: '${#} компаний опубликовали'
                    }
                },
                ' новые книги.'
            ]
        };

    it('en-US', function () {
        var msg = new IntlMessageFormat(messages.en, 'en-US');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('One company published new books.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 companies published new books.');
    });

    it('en-US', function () {
        var msg = new IntlMessageFormat(messages.ru, 'ru-RU');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('Одна компания опубликовала новые книги.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 компании опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 компаний опубликовали новые книги.');
    });

});

<commit_msg>Completes ru-RU testing and removes erroneous 1 plural option.<commit_after>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jshint node:true */
/*global describe,it */
'use strict';

var chai,
    expect,
    IntlMessageFormat;

// This oddity is so that this file can be used for both client-side and
// server-side testing.  (On the client we've already loaded chai and
// IntlMessageFormat.)
if ('function' === typeof require) {
    chai = require('chai');
    IntlMessageFormat = require('../build/index.en.min.js');
    require('../locale-data/ar.js');
    require('../locale-data/pl.js');
}
expect = chai.expect;

describe('message resolvedOptions', function () {

    it('empty options', function () {
        var msg, o, p, pCount = 0;

        msg = new IntlMessageFormat('My name is ${name}');

        o = msg.resolvedOptions();

        for (p in o) {
            if (o.hasOwnProperty(p)) {
                pCount++;
            }
        }

        expect(pCount).to.equal(0);
    });
});

describe('message creation', function () {

    it('simple string formatting', function () {
        var msg, m;
        msg = new IntlMessageFormat('My name is ${first} {last}.');
        m = msg.format({
            first: 'Anthony',
            last: 'Pipkin'
        });
        expect(m).to.equal('My name is Anthony Pipkin.');
    });

    it('simple object formatting', function () {
        var msg, m;

        msg = new IntlMessageFormat(['I have ', 2, ' cars.']);

        m = msg.format();

        expect(m).to.equal('I have 2 cars.');

    });

    it('simple object with post processing tokens', function () {
        var msg, m;

        msg = new IntlMessageFormat(['${', 'company', '}', ' {', 'verb' ,'}.']);

        m = msg.format({
            company: 'Yahoo',
            verb: 'rocks'
        });

        expect(m).to.equal('Yahoo rocks.');

    });

    it ('complex object formatter', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal("Some text before Some messages for the default and text after");
    });

    it ('complex object formatter with invalid valueName', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        try {
            m = msg.format({
                jumper: 20
            });
        } catch (e) {
            var err = 'The valueName `numPeople` was not found.';
            expect(e).to.equal(err);
        }
    });

    it ('complex object formatter with offset', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            offset: 1,
            options: {
                one: 'Some message ${ph} with ${#} value',

                few: ['Optional prefix text for |few| ', {
                    type: 'select',
                    valueName: 'gender',
                    options: {
                        male: 'Text for male option with \' single quotes',
                        female: 'Text for female option with {}',
                        other: 'Text for default'
                    }
                }, ' optional postfix text'],

                other: 'Some messages for the default'

            }
        }, ' and text after'],
            'pl'    // this has the "few" rule that we need
        );
        m = msg.format({
            numPeople: 1,   // offset will move this to "2" so that the "few" group is used
            ph: 'whatever',
            gender: 'male'
        });
        expect(m).to.equal("Some text before Optional prefix text for |few| Text for male option with ' single quotes optional postfix text and text after");
    });

    it('Simple string formatter using a custom formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter d: ${num:d}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter d: 10');
    });

    it('Simple string formatter using an inline formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat([{
            valueName: 'str',
            formatter: function (val, locale) {
                return val.toString().split('').reverse().join('');
            }
        }]);
        m = msg.format({
            str: 'aardvark'
        });
        expect(m).to.equal('kravdraa');
    });

    it('Simple string formatter using a nonexistent formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter foo: ${num:foo}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter foo: 010');
    });

    it('Custom formatters with hidden inheritance', function () {
        var msg, m,
            Formatters = function () {
                this.d = function (val, locale) {
                    return val + '030';
                };
            },
            CustomFormatters = function () {
                this.f = function (val, locale) {
                    return val + '080';
                };
            };

        CustomFormatters.prototype = Formatters;
        CustomFormatters.prototype.constructor = CustomFormatters;

        msg = new IntlMessageFormat('d: ${num:d} / f: ${num:f}', null, new CustomFormatters());

        m = msg.format({
            num: 0
        });

        expect(m).to.equal('d: 0 / f: 0080');
    });

    it('broken pattern', function () {
       var msg, m;

        msg = new IntlMessageFormat('${name} ${formula}');

        msg.pattern = '${name} ${formula}';

        m = msg.format({
            name: 'apipkin'
        });

        expect(m).to.equal('apipkin ${formula}');

    });

});

describe('message creation for plurals', function () {
    var msg = new IntlMessageFormat(['I have ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                zero : 'zero points',
                one  : 'a point',
                two  : 'two points',
                few  : 'a few points',
                many : 'lots of points',
                other: 'some other amount of points'
            }
        }, '.'], 'ar');

    it('zero', function () {
        var m = msg.format({
            numPeople: 0
        });

        expect(m).to.equal('I have zero points.');
    });

    it('one', function () {
        var m = msg.format({
            numPeople: 1
        });

        expect(m).to.equal('I have a point.');
    });

    it('two', function () {
        var m = msg.format({
            numPeople: 2
        });

        expect(m).to.equal('I have two points.');
    });

    it('few', function () {
        var m = msg.format({
            numPeople: 5
        });

        expect(m).to.equal('I have a few points.');
    });

    it('many', function () {
        var m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal('I have lots of points.');
    });

    it('other', function () {
        var m = msg.format({
            numPeople: 100
        });

        expect(m).to.equal('I have some other amount of points.');
    });

});

describe('locale switching', function () {
    var simple = {
            en: [
                { valueName: 'NAME' },
                ' went to ',
                { valueName: 'CITY' },
                '.'
            ],
            fr: [
                { valueName: 'NAME' },
                ' est ',
                {
                    type: 'gender',
                    valueName: 'gender',
                    options: {
                        female: 'allée',
                        other: 'allé'
                    }
                },
                ' à ',
                { valueName: 'CITY' },
                '.'
            ]
        },

        complex = {
            en: '${TRAVELLERS} went to ${CITY}.',
            fr: [
                '${TRAVELLERS}',
                {
                    type: 'plural',
                    valueName: 'TRAVELLER_COUNT',
                    options: {
                        one: [' est ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allée',
                                other: 'allé'
                            }
                        }],
                        other: [' sont ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allées',
                                other: 'allés'
                            }
                        }]
                    }
                },
                ' à ',
                '${CITY}',
                '.'
            ]
        },

        maleObj = {
            NAME: 'Tony',
            CITY: 'Paris',
            gender: 'male'
        },
        femaleObj = {
            NAME: 'Jenny',
            CITY: 'Paris',
            gender: 'female'
        },

        maleTravelers = {
            TRAVELLERS: 'Lucas, Tony and Drew',
            TRAVELLER_COUNT: 3,
            GENDER: 'male',
            CITY: 'Paris'
        },

        femaleTravelers = {
            TRAVELLERS: 'Monica',
            TRAVELLER_COUNT: 1,
            GENDER: 'female',
            CITY: 'Paris'
        };

    it('en-US simple', function () {
        var msg = new IntlMessageFormat(simple.en, 'en-US');

        expect(msg.format(maleObj)).to.equal('Tony went to Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny went to Paris.');
    });

    it('fr-FR simple', function () {
        var msg = new IntlMessageFormat(simple.fr, 'fr-FR');

        expect(msg.format(maleObj)).to.equal('Tony est allé à Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny est allée à Paris.');
    });

    it('en-US complex', function () {
        var msg = new IntlMessageFormat(complex.en, 'en-US');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew went to Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica went to Paris.');
    });

    it('fr-FR complex', function () {
        var msg = new IntlMessageFormat(complex.fr, 'fr-FR');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew sont allés à Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica est allée à Paris.');
    });

});

describe('locale switching with counts', function () {

    var messages = {
            en: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                       one: 'One company',
                       other: '${#} companies'
                    }
                },
                ' published new books.'
            ],
            ru: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                        one: 'Одна компания опубликовала',
                        many: '${#} компаний опубликовали',
                        other: '${#} компаний опубликовали'
                    }
                },
                ' новые книги.'
            ]
        };

    it('en-US', function () {
        var msg = new IntlMessageFormat(messages.en, 'en-US');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('One company published new books.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 companies published new books.');
    });

    it('en-US', function () {
        var msg = new IntlMessageFormat(messages.ru, 'ru-RU');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('Одна компания опубликовала новые книги.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 компаний опубликовали новые книги.');
    });

});

<|endoftext|>