<commit_before>/* global docma, dust */
/* eslint max-depth:0, no-var:0, prefer-template:0, prefer-arrow-callback:0 */

// Note: This is for use in the browser. ES2015 rules don't apply here (yet).

// docma.web.filters
// https://github.com/onury/docma

'use strict';

(function () {

    dust.filters = dust.filters || {};

    dust.filters.$pt = function (str) {
        return docma.utils.parseTicks(str);
    };

    dust.filters.$pnl = function (str) {
        return docma.utils.parseNewLines(str, { keepIfSingle: true });
    };

    dust.filters.$pl = function (str) {
        return docma.utils.parseLinks(str);
    };

    dust.filters.$tl = function (str) {
        return docma.utils.trimLeft(str);
    };

    dust.filters.$p = function (str) {
        return docma.utils.parse(str, { keepIfSingle: true });
    };

    dust.filters.$nt = function (str) {
        return docma.utils.normalizeTabs(str);
    };

    dust.filters.$desc = function (symbol) {
        return docma.utils.parse(symbol.classdesc || symbol.description || '');
    };

    dust.filters.$def = function (param) {
        return param.optional ? String(param.defaultvalue) : '';
    };

    var reJSValues = (/true|false|null|undefined|Infinity|NaN|\d+|Number\.\w+|Math\.(PI|E|LN(2|10)|LOG(2|10)E|SQRT(1_)?2)|\[.*?]|\{.*?}|new [a-zA-Z]+.*|\/.+\/[gmiu]*|Date\.(now\(\)|UTC\(.*)|window|document/);
    dust.filters.$val = function (symbol) {
        var val = docma.utils.notate(symbol, 'meta.code.value');
        if (val === undefined) return '';
        if (typeof val !== 'string') return val;
        var types = docma.utils.notate(symbol, 'type.names') || [];
        // first char is NOT a single or double quote or tick
        if (!(/['"`]/).test(val.slice(0, 1))
                // types include "String"
                && types.indexOf('String') >= 0
                // only "String" type or value is NOT a JS non-string value/keyword
                && (types.length === 1 || reJSValues.indexOf(val) === -1)) {
            return '"' + val + '"';
        }
        return val;
    };

    dust.filters.$id = function (symbol) {
        var id;
        if (typeof symbol === 'string') {
            id = symbol;
        } else {
            var nw = docma.utils.isConstructor(symbol) ? 'new-' : '';
            id = nw + symbol.$longname; // docma.utils.getFullName(symbol);
        }
        return id.replace(/ /g, '-');
    };

})();
<commit_msg>add $tnl<commit_after>/* global docma, dust */
/* eslint max-depth:0, no-var:0, prefer-template:0, prefer-arrow-callback:0 */

// Note: This is for use in the browser. ES2015 rules don't apply here (yet).

// docma.web.filters
// https://github.com/onury/docma

'use strict';

(function () {

    dust.filters = dust.filters || {};

    dust.filters.$pt = function (str) {
        return docma.utils.parseTicks(str);
    };

    dust.filters.$pnl = function (str) {
        return docma.utils.parseNewLines(str, { keepIfSingle: true });
    };

    dust.filters.$pl = function (str) {
        return docma.utils.parseLinks(str);
    };

    dust.filters.$tl = function (str) {
        return docma.utils.trimLeft(str);
    };

    dust.filters.$tnl = function (str) {
        return docma.utils.trimNewLines(str);
    };

    dust.filters.$p = function (str) {
        return docma.utils.parse(str, { keepIfSingle: true });
    };

    dust.filters.$nt = function (str) {
        return docma.utils.normalizeTabs(str);
    };

    dust.filters.$desc = function (symbol) {
        return docma.utils.parse(symbol.classdesc || symbol.description || '');
    };

    dust.filters.$def = function (param) {
        return param.optional ? String(param.defaultvalue) : '';
    };

    var reJSValues = (/true|false|null|undefined|Infinity|NaN|\d+|Number\.\w+|Math\.(PI|E|LN(2|10)|LOG(2|10)E|SQRT(1_)?2)|\[.*?]|\{.*?}|new [a-zA-Z]+.*|\/.+\/[gmiu]*|Date\.(now\(\)|UTC\(.*)|window|document/);
    dust.filters.$val = function (symbol) {
        var val = docma.utils.notate(symbol, 'meta.code.value');
        if (val === undefined) return '';
        if (typeof val !== 'string') return val;
        var types = docma.utils.notate(symbol, 'type.names') || [];
        // first char is NOT a single or double quote or tick
        if (!(/['"`]/).test(val.slice(0, 1))
                // types include "String"
                && types.indexOf('String') >= 0
                // only "String" type or value is NOT a JS non-string value/keyword
                && (types.length === 1 || reJSValues.indexOf(val) === -1)) {
            return '"' + val + '"';
        }
        return val;
    };

    dust.filters.$id = function (symbol) {
        var id;
        if (typeof symbol === 'string') {
            id = symbol;
        } else {
            var nw = docma.utils.isConstructor(symbol) ? 'new-' : '';
            id = nw + symbol.$longname; // docma.utils.getFullName(symbol);
        }
        return id.replace(/ /g, '-');
    };

})();
<|endoftext|>


<commit_before>(function () {"use strict";})();
/**
 * Created by apizzimenti on 7/21/16.
 */

/**
 * @author Anthony Pizzimenti
 *
 * @desc Element for containing how-to information and making it visible (or invisible) to the player.
 *
 * @param element {string} String id for the HTML element that will serve as your guide (typically a button).
 * @param gameElement {string} String id for element that hosts the game canvas (the same name as when the Phaser game is initialized).
 * @param [styles=null] {object} Custom style overrides.
 *
 * @example
 * var guide;
 *
 * // no custom styles
 * guide = new Guide("guide", "gameCanvas")
 *
 * // custom styles
 * guide = new Guide("guide", "gameCanvas", {
 *    "color": "black",
 *    "text-align": "center"
 * });
 *
 * @class Animal
 * @constructor
 */

function Guide (element, gameElement, styles) {

    var _this = this;

    this.raw = {};
    this.raw.guideId = element;
    this.raw.guide = document.getElementById(element);
    this.raw.game = document.getElementById(gameElement);
    this.raw.canvas = this.raw.game.getElementsByTagName("canvas")[0];
    this.raw.guideHtml = this.raw.guide.innerHTML;
    this.raw.offsetTop = this.raw.canvas.offsetTop;
    this.raw.offsetLeft = this.raw.canvas.offsetLeft;
    this.raw.on = false;
    this.raw.guide.styles = styles || null;

    $(document).ready(() => {
        _this.guideElement = $(`#${element}`);

        _this.configureWindow();
        _this.button();
    });
}

/**
 * @author Anthony Pizzimenti
 *
 * @desc Generates a button on top of the game canvas for displaying help information.
 *
 * @this Guide
 */

Guide.prototype.button = function () {

    var button = document.createElement("button"),
        buttonText = document.createTextNode("i"),
        id = "guideButton",
        template = `#${id}`,
        _this = this;

    button.id = id;
    button.appendChild(buttonText);
    this.raw.game.appendChild(button);
    this.raw.guideButton = button;
    this.raw.guideButton.className = "guide-button";
    this.raw.guideButton.on = false;

    $(template).css({
        "top": _this.raw.offsetTop + 20,
        "left": _this.raw.offsetLeft + 20,
    });

    $(template).hover(() => {
       $(template).css({
           "cursor": "pointer"
       });
    });

    $(template).click(() => {

        if (!_this.raw.guideButton.on) {
            _this.raw.guideButton.on = true;
            $(`#${_this.raw.guideId}`).css({
                "display": "block"
            });
        } else {
            _this.raw.guideButton.on = false;
            $(`#${_this.raw.guideId}`).css({
                "display": "none"
            });
        }
    });
};

/**
 * @author Anthony Pizzimenti
 *
 * @desc Generates the guide window and its dimensions, positioning, style.
 *
 * @this Guide
 */

Guide.prototype.configureWindow = function () {

    var template = `#${this.raw.guideId}`,
        w = window.innerWidth / 2,
        h = window.innerHeight / 2,
        top = window.innerHeight / 4,
        left = window.innerWidth / 4,
        el = this.raw.guide;

    el.className = "guide";

    $(template).css({
        "display": "none",
        "left": left,
        "top": top,
        "width": w,
        "height": h
    });

    if (this.raw.guide.styles) {
        $(template).css(this.raw.guide.styles);
    }
};
<commit_msg>change styles around<commit_after>(function () {"use strict";})();
/**
 * Created by apizzimenti on 7/21/16.
 */

/**
 * @author Anthony Pizzimenti
 *
 * @desc Element for containing how-to information and making it visible (or invisible) to the player.
 *
 * @param element {string} String id for the HTML element that will serve as your guide..
 * @param gameElement {string} String id for element that hosts the game canvas (the same name as when the Phaser game is initialized).
 * @param [styles=null] {object} Custom style overrides.
 *
 * @example
 *
 * // index.html
 * // in your html, simply include an element containing guide information, like so:
 *
 * ...
 *

 *
Introduction

 *             Blah blah blah...
 *

 * ...
 *
 *
 * // .js file where game is located
 *
 * var guide;
 *
 * // no custom styles
 * guide = new Guide("guide", "gameCanvas")
 *
 * // custom styles
 * guide = new Guide("guide", "gameCanvas", {
 *    "color": "black",
 *    "text-align": "center"
 * });
 *
 * // check the test/ folder for a usable example.
 *
 * @class Animal
 * @constructor
 */

function Guide (element, gameElement, styles) {

    var _this = this;

    this.raw = {};
    this.raw.guideId = element;
    this.raw.guide = document.getElementById(element);
    this.raw.game = document.getElementById(gameElement);
    this.raw.canvas = this.raw.game.getElementsByTagName("canvas")[0];
    this.raw.guideHtml = this.raw.guide.innerHTML;
    this.raw.offsetTop = this.raw.canvas.offsetTop;
    this.raw.offsetLeft = this.raw.canvas.offsetLeft;
    this.raw.on = false;
    this.raw.guide.styles = styles || null;

    $(document).ready(() => {
        _this.guideElement = $(`#${element}`);

        _this.configureWindow();
        _this.button();
    });
}

/**
 * @author Anthony Pizzimenti
 *
 * @desc Generates a button on top of the game canvas for displaying help information.
 *
 * @this Guide
 */

Guide.prototype.button = function () {

    var button = document.createElement("button"),
        buttonText = document.createTextNode("i"),
        id = "guideButton",
        template = `#${id}`,
        _this = this;

    button.id = id;
    button.appendChild(buttonText);
    this.raw.game.appendChild(button);
    this.raw.guideButton = button;
    this.raw.guideButton.className = "guide-button";
    this.raw.guideButton.on = false;

    $(template).css({
        "top": _this.raw.offsetTop + 20,
        "left": _this.raw.offsetLeft + 20,
    });

    $(template).hover(() => {
       $(template).css({
           "cursor": "pointer"
       });
    });

    $(template).click(() => {

        if (!_this.raw.guideButton.on) {
            _this.raw.guideButton.on = true;
            $(`#${_this.raw.guideId}`).css({
                "display": "block"
            });
        } else {
            _this.raw.guideButton.on = false;
            $(`#${_this.raw.guideId}`).css({
                "display": "none"
            });
        }
    });
};

/**
 * @author Anthony Pizzimenti
 *
 * @desc Generates the guide window and its dimensions, positioning, style.
 *
 * @this Guide
 */

Guide.prototype.configureWindow = function () {

    var template = `#${this.raw.guideId}`,
        w = window.innerWidth / 2,
        h = window.innerHeight / 2,
        top = window.innerHeight / 4,
        left = window.innerWidth / 4,
        el = this.raw.guide;

    el.className = "guide";

    $(template).css({
        "display": "none",
        "left": left,
        "top": top,
        "width": w,
        "height": h
    });

    if (this.raw.guide.styles) {
        $(template).css(this.raw.guide.styles);
    }
};
<|endoftext|>


<commit_before>import Dexie from 'dexie';
import {module, stop, start, asyncTest, equal, ok} from 'QUnit';

module("open", {
    setup: function () {
        stop();
        Dexie.delete("TestDB").then(function () {
            start();
        }).catch(function (e) {
            ok(false, "Could not delete database");
        });
    },
    teardown: function () {
        stop(); Dexie.delete("TestDB").then(start);
    }
});

asyncTest("open, add and query data without transaction", 6, function () {
    var db = new Dexie("TestDB");
    db.version(1).stores({ employees: "++id,first,last" });
    ok(true, "Simple version() and stores() passed");
    db.open().catch(function (e) {
        ok(false, "Could not open database: " + (e.stack || e));
        start();
    });

    db.employees.add({ first: "David", last: "Fahlander" }).then(function () {
        ok(true, "Could add employee");
        db.employees.where("first").equals("David").toArray(function (a) {
            ok(true, "Could retrieve employee based on where() clause");
            var first = a[0].first;
            var last = a[0].last;
            ok(first == "David" && last == "Fahlander", "Could get the same object");
            equal(a.length, 1, "Length of returned answer is 1");
            ok(a[0].id, "Got an autoincremented id value from the object");
            db.close();
            start();
        });
    });
});

asyncTest("open, add and query data using transaction", function () {
    var db = new Dexie("TestDB");
    db.version(1).stores({ employees: "++id,first,last" });
    db.open().catch(function () {
        ok(false, "Could not open database");
        start();
    });

    db.transaction("rw", db.employees, function () {

        // Add employee
        db.employees.add({ first: "David", last: "Fahlander" });

        // Query employee
        db.employees.where("first").equals("David").toArray(function (a) {
            equal(a.length, 1, "Could retrieve employee based on where() clause");
            var first = a[0].first;
            var last = a[0].last;
            ok(first == "David" && last == "Fahlander", "Could get the same object");
            equal(a.length, 1, "Length of returned answer is 1");
            ok(a[0].id, "Got an autoincremented id value from the object");
        });
    }).catch(function (e) {
        ok(false, e);
    }).finally(function() {
        db.close();
        start();
    });
});

asyncTest("test-if-database-exists", 3, function () {
    var db = new Dexie("TestDB");
    var db2 = null;
    return db.open().then(function () {
        // Could open database without specifying any version. An existing database was opened.
        ok(false, "Expected database not to exist but it existed indeed");
        db.close();
    }).catch(function (err) {
        // An error happened. Database did not exist.
        ok(true, "Database did not exist");
        db = new Dexie("TestDB");
        db.version(1).stores({dummy: ""});
        return db.open();
    }).then(function () {
        // Database was created. Now open another instance to test if it exists
        ok(true, "Could create a dummy database");
        db2 = new Dexie("TestDB");
        return db2.open();
    }).then(function () {
        ok(true, "Dummy Database did exist.");
        db2.close();
    }).catch(function (err) {
        ok(false, "Error: " + err.stack || err);
    }).finally(function () {
        db.delete().then(function () {
            if (db2) return db2.delete();
        }).finally(start);
    });
});

asyncTest("open database without specifying version or schema", 10, function () {
    if (Dexie.Observable) {
        ok(false, "Dexie.Observable currently not compatible with this mode");
        return start();
    }
    var db = new Dexie("TestDB");
    var db2 = null;
    db.open().then(function () {
        ok(false, "Should not be able to open a non-existing database when not specifying any version schema");
    }).catch(function (err) {
        ok(true, "Got error when trying to open non-existing DB: " + err);
        // Create a non-empty database that we later on will open in other instance (see next then()-clause)...
        db = new Dexie("TestDB");
        db.version(1).stores({ friends: "++id,name", pets: "++,name,kind" });
        return db.open();
    }).then(function () {
        ok(true, "Could create TestDB with specified version schema.");
        db2 = new Dexie("TestDB"); // Opening another instans without specifying schema
        return db2.open().then(function () {
            equal(db2.tables.length, 2, "We got two tables in database");
            ok(db2.tables.every(function (table) { return table.name == "friends" || table.name == "pets" }), "db2 contains the tables friends and pets");
            equal(db2.table("friends").schema.primKey.name, "id", "Primary key of friends is 'id'");
            ok(true, "Primary key of friends is auto-incremented: " + db2.table("friends").schema.primKey.auto); // Just logging. Not important for functionality. I know this fails on IE11.
            equal(db2.table("friends").schema.indexes[0].name, "name", "First index of friends table is the 'name' index");
            ok(!db2.table("pets").schema.primKey.name, "Primary key of pets has no name (not inline)");
            ok(true, "Primary key of pets is auto-incremented: " + db2.table("pets").schema.primKey.auto); // Just logging. Not important for functionality. I know this fails on IE11.
            equal(db2.table("pets").schema.indexes.length, 2, "Pets table has two indexes");
        });
    }).catch(function (err) {
        ok(false, "Error: " + err);
    }).finally(function () {
        db.close();
        if (db2) db2.close();
        start();
    });
});

asyncTest("Dexie.getDatabaseNames", 11, function () {
    var defaultDatabases = [];
    var db1, db2;
    Dexie.getDatabaseNames(function (names) {
        defaultDatabases = [].slice.call(names, 0);
        ok(true, "Current databases: " + (defaultDatabases.length ? defaultDatabases.join(',') : "(none)"));
        db1 = new Dexie("TestDB1");
        db1.version(1).stores({});
        return db1.open();
    }).then(function () {
        // One DB created
        ok(true, "TestDB1 successfully created");
        return Dexie.getDatabaseNames();
    }).then(function (names) {
        equal(names.length, defaultDatabases.length + 1, "Another DB has been created");
        ok(names.indexOf("TestDB1") !== -1, "Database names now contains TestDB1");
        db2 = new Dexie("TestDB2");
        db2.version(1).stores({});
        return db2.open();
    }).then(function () {
        ok(true, "TestDB2 successfully created");
        return Dexie.getDatabaseNames();
    }).then(function (names) {
        equal(names.length, defaultDatabases.length + 2, "Yet another DB has been created");
        ok(names.indexOf("TestDB2") !== -1, "Database names now contains TestDB2");
        return db1.delete();
    }).then(function () {
        return Dexie.getDatabaseNames();
    }).then(function(names){
        equal(names.length, defaultDatabases.length + 1, "A database has been deleted");
        ok(!names.indexOf("TestDB1") !== -1, "TestDB1 not in database list anymore");
        return db2.delete();
    }).then(function () {
        return Dexie.getDatabaseNames();
    }).then(function (names) {
        equal(names.length, defaultDatabases.length, "All of our databases have been deleted");
        ok(!names.indexOf("TestDB2") !== -1, "TestDB2 not in database list anymore");
    }).catch(function (err) {
        ok(false, err.stack || err);
    }).finally(function () {
        (db1 ? db1.delete() : Dexie.Promise.resolve()).finally(function () {
            (db2 ? db2.delete() : Dexie.Promise.resolve()).finally(start);
        });
    });
});

asyncTest("Issue #76 Dexie inside Web Worker", function () {
    //
    // Imports to include from the web worker:
    //
    var imports = window.workerImports || ["../dist/dexie.js"];

    //
    // Code to execute in the web worker:
    //
    function CodeToExecuteInWebWorker(ok, done) {
        ok(true, "Could enter the web worker");

        Dexie.delete("codeFromWorker").then(function() {
            var db = new Dexie("codeFromWorker");
            ok(true, "Could create a Dexie instance from within a web worker");

            db.version(1).stores({ table1: "++" });
            ok(true, "Could define schema");

            db.open();
            ok(true, "Could open the database");

            return db.transaction('rw', db.table1, function() {
                ok(true, "Could create a transaction");
                db.table1.add({ name: "My first object" }).then(function(id) {
                    ok(true, "Could add object that got id " + id);
                }).catch(function(err) {
                    ok(false, "Got error: " + err);
                });
            });
        }).then(function () {
            ok(true, "Transaction committed");
        }).catch(function(err) {
            ok(false, "Transaction failed");
        }).finally(done);
    }

    //
    // Frameworking...
    //
    if (!window.Worker) {
        ok(false, "WebWorkers not supported");
        start();
        return;
    }

    var worker = new Worker(window.workerSource || "worker.js");
    worker.postMessage({
        imports: imports,
        code: CodeToExecuteInWebWorker.toString()
    });

    worker.onmessage = function(e) {
        switch (e.data[0]) {
        case "ok":
            ok(e.data[1], e.data[2]);
            break;
        case "done":
            worker.terminate();
            start();
            break;
        }
    }

    worker.onerror = function(e) {
        worker.terminate();
        ok(false, "Worker errored: " + e.message);
        start();
    };
});

asyncTest("Issue#100 - not all indexes are created", function () {
    var db = new Dexie("TestDB");
    db.version(20)
      .stores({
          t: 'id,displayName,*displayNameParts,isDeleted,countryRef,[countryRef+isDeleted],autoCreated,needsReview,[autoCreated+isDeleted],[needsReview+isDeleted],[autoCreated+needsReview+isDeleted],[autoCreated+countryRef+needsReview+isDeleted],[autoCreated+countryRef+needsReview+isDeleted],[autoCreated+robotsNoIndex+isDeleted],[autoCreated+needsReview+robotsNoIndex+isDeleted],[autoCreated+countryRef+robotsNoIndex+isDeleted],[autoCreated+countryRef+needsReview+robotsNoIndex+isDeleted]',
      });
    db.open().then(function() {
        return Dexie.Promise.all(
            db.t.orderBy("id").first(),
            db.t.orderBy("displayName").first(),
            db.t.orderBy("displayNameParts").first(),
            db.t.orderBy("isDeleted").first(),
            db.t.orderBy("countryRef").first(),
            db.t.orderBy("[countryRef+isDeleted]").first(),
            db.t.orderBy("autoCreated").first(),
            db.t.orderBy("needsReview").first(),
            db.t.orderBy("[autoCreated+isDeleted]").first(),
            db.t.orderBy("[needsReview+isDeleted]").first(),
            db.t.orderBy("[autoCreated+needsReview+isDeleted]").first(),
            db.t.orderBy("[autoCreated+countryRef+needsReview+isDeleted]").first(),
            db.t.orderBy("[autoCreated+robotsNoIndex+isDeleted]").first(),
            db.t.orderBy("[autoCreated+needsReview+robotsNoIndex+isDeleted]").first(),
            db.t.orderBy("[autoCreated+countryRef+robotsNoIndex+isDeleted]").first(),
            db.t.orderBy("[autoCreated+countryRef+needsReview+robotsNoIndex+isDeleted]").first()
        );
    }).then(function(res) {
        ok(false, "Should not succeed with creating the same index twice");
    }).catch(function(err) {
        ok(true, "Catched error trying to create duplicate indexes: " + err);
        return db.t.toArray();
    }).then(function(a) {
        ok(false, "Database should have failed here");
    }).catch(function(err) {
        ok(true, "Got exception when trying to work agains DB: " + err);
    }).then(function () {
        // Close the database and open dynamically to check that
        // it should not exist when failed to open.
        db.close();
        db = new Dexie("TestDB");
        return db.open();
    }).then(function() {
        ok(false, "Should not succeed to open the database. It should not have been created.");
        equal(db.tables.length, 0, "At least expect no tables to have been created on the database");
    }).catch(function(err) {
        ok(true, "Should not succeed to dynamically open db because it should not exist");
    }).finally(start);

});

asyncTest("Dexie.exists", function () {
    var db = null;
    Dexie.exists("TestDB").then(function(result) {
        equal(result, false, "Should not exist yet");
        db = new Dexie("TestDB");
        db.version(1).stores({
            some: "schema"
        });
        return db.open();
    }).then(function() {
        return Dexie.exists("TestDB");
    }).then(function(result) {
        equal(result, true, "Should exist now and has another open connection.");
        db.close();
        return Dexie.exists("TestDB");
    }).then(function(result) {
        equal(result, true, "Should still exist");
        return Dexie.delete("TestDB");
    }).then(function () {
        return Dexie.exists("TestDB");
    }).then(function(result) {
        equal(result, false, "Should have been deleted now");
    }).catch(function(e) {
        ok(false, "Error: " + e);
    }).finally(start);
});
<commit_msg>Added test for the new "no autoOpen" option in Dexie constructor as well as a test for bug fix of db.close() checked in 2 commits ago.<commit_after>import Dexie from 'dexie';
import {module, stop, start, asyncTest, equal, ok} from 'QUnit';

const async = Dexie.async;

module("open", {
    setup: function () {
        stop();
        Dexie.delete("TestDB").then(function () {
            start();
        }).catch(function (e) {
            ok(false, "Could not delete database");
        });
    },
    teardown: function () {
        stop(); Dexie.delete("TestDB").then(start);
    }
});

asyncTest("open, add and query data without transaction", 6, function () {
    var db = new Dexie("TestDB");
    db.version(1).stores({ employees: "++id,first,last" });
    ok(true, "Simple version() and stores() passed");
    db.open().catch(function (e) {
        ok(false, "Could not open database: " + (e.stack || e));
        start();
    });

    db.employees.add({ first: "David", last: "Fahlander" }).then(function () {
        ok(true, "Could add employee");
        db.employees.where("first").equals("David").toArray(function (a) {
            ok(true, "Could retrieve employee based on where() clause");
            var first = a[0].first;
            var last = a[0].last;
            ok(first == "David" && last == "Fahlander", "Could get the same object");
            equal(a.length, 1, "Length of returned answer is 1");
            ok(a[0].id, "Got an autoincremented id value from the object");
            db.close();
            start();
        });
    });
});

asyncTest("open, add and query data using transaction", function () {
    var db = new Dexie("TestDB");
    db.version(1).stores({ employees: "++id,first,last" });
    db.open().catch(function () {
        ok(false, "Could not open database");
        start();
    });

    db.transaction("rw", db.employees, function () {

        // Add employee
        db.employees.add({ first: "David", last: "Fahlander" });

        // Query employee
        db.employees.where("first").equals("David").toArray(function (a) {
            equal(a.length, 1, "Could retrieve employee based on where() clause");
            var first = a[0].first;
            var last = a[0].last;
            ok(first == "David" && last == "Fahlander", "Could get the same object");
            equal(a.length, 1, "Length of returned answer is 1");
            ok(a[0].id, "Got an autoincremented id value from the object");
        });
    }).catch(function (e) {
        ok(false, e);
    }).finally(function() {
        db.close();
        start();
    });
});

asyncTest("test-if-database-exists", 3, function () {
    var db = new Dexie("TestDB");
    var db2 = null;
    return db.open().then(function () {
        // Could open database without specifying any version. An existing database was opened.
        ok(false, "Expected database not to exist but it existed indeed");
        db.close();
    }).catch(Dexie.NoSuchDatabaseError, function (err) {
        // An error happened. Database did not exist.
        ok(true, "Database did not exist");
        db = new Dexie("TestDB");
        db.version(1).stores({dummy: ""});
        return db.open();
    }).then(function () {
        // Database was created. Now open another instance to test if it exists
        ok(true, "Could create a dummy database");
        db2 = new Dexie("TestDB");
        return db2.open();
    }).then(function () {
        ok(true, "Dummy Database did exist.");
        db2.close();
    }).catch(function (err) {
        ok(false, "Error: " + err.stack || err);
    }).finally(function () {
        db.delete().then(function () {
            if (db2) return db2.delete();
        }).finally(start);
    });
});

asyncTest("open database without specifying version or schema", 10, function () {
    if (Dexie.Observable) {
        ok(false, "Dexie.Observable currently not compatible with this mode");
        return start();
    }
    var db = new Dexie("TestDB");
    var db2 = null;
    db.open().then(function () {
        ok(false, "Should not be able to open a non-existing database when not specifying any version schema");
    }).catch(function (err) {
        ok(true, "Got error when trying to open non-existing DB: " + err);
        // Create a non-empty database that we later on will open in other instance (see next then()-clause)...
        db = new Dexie("TestDB");
        db.version(1).stores({ friends: "++id,name", pets: "++,name,kind" });
        return db.open();
    }).then(function () {
        ok(true, "Could create TestDB with specified version schema.");
        db2 = new Dexie("TestDB"); // Opening another instans without specifying schema
        return db2.open().then(function () {
            equal(db2.tables.length, 2, "We got two tables in database");
            ok(db2.tables.every(function (table) { return table.name == "friends" || table.name == "pets" }), "db2 contains the tables friends and pets");
            equal(db2.table("friends").schema.primKey.name, "id", "Primary key of friends is 'id'");
            ok(true, "Primary key of friends is auto-incremented: " + db2.table("friends").schema.primKey.auto); // Just logging. Not important for functionality. I know this fails on IE11.
            equal(db2.table("friends").schema.indexes[0].name, "name", "First index of friends table is the 'name' index");
            ok(!db2.table("pets").schema.primKey.name, "Primary key of pets has no name (not inline)");
            ok(true, "Primary key of pets is auto-incremented: " + db2.table("pets").schema.primKey.auto); // Just logging. Not important for functionality. I know this fails on IE11.
            equal(db2.table("pets").schema.indexes.length, 2, "Pets table has two indexes");
        });
    }).catch(function (err) {
        ok(false, "Error: " + err);
    }).finally(function () {
        db.close();
        if (db2) db2.close();
        start();
    });
});

asyncTest("Dexie.getDatabaseNames", 11, function () {
    var defaultDatabases = [];
    var db1, db2;
    Dexie.getDatabaseNames(function (names) {
        defaultDatabases = [].slice.call(names, 0);
        ok(true, "Current databases: " + (defaultDatabases.length ? defaultDatabases.join(',') : "(none)"));
        db1 = new Dexie("TestDB1");
        db1.version(1).stores({});
        return db1.open();
    }).then(function () {
        // One DB created
        ok(true, "TestDB1 successfully created");
        return Dexie.getDatabaseNames();
    }).then(function (names) {
        equal(names.length, defaultDatabases.length + 1, "Another DB has been created");
        ok(names.indexOf("TestDB1") !== -1, "Database names now contains TestDB1");
        db2 = new Dexie("TestDB2");
        db2.version(1).stores({});
        return db2.open();
    }).then(function () {
        ok(true, "TestDB2 successfully created");
        return Dexie.getDatabaseNames();
    }).then(function (names) {
        equal(names.length, defaultDatabases.length + 2, "Yet another DB has been created");
        ok(names.indexOf("TestDB2") !== -1, "Database names now contains TestDB2");
        return db1.delete();
    }).then(function () {
        return Dexie.getDatabaseNames();
    }).then(function(names){
        equal(names.length, defaultDatabases.length + 1, "A database has been deleted");
        ok(!names.indexOf("TestDB1") !== -1, "TestDB1 not in database list anymore");
        return db2.delete();
    }).then(function () {
        return Dexie.getDatabaseNames();
    }).then(function (names) {
        equal(names.length, defaultDatabases.length, "All of our databases have been deleted");
        ok(!names.indexOf("TestDB2") !== -1, "TestDB2 not in database list anymore");
    }).catch(function (err) {
        ok(false, err.stack || err);
    }).finally(function () {
        (db1 ? db1.delete() : Dexie.Promise.resolve()).finally(function () {
            (db2 ? db2.delete() : Dexie.Promise.resolve()).finally(start);
        });
    });
});

asyncTest("Issue #76 Dexie inside Web Worker", function () {
    //
    // Imports to include from the web worker:
    //
    var imports = window.workerImports || ["../dist/dexie.js"];

    //
    // Code to execute in the web worker:
    //
    function CodeToExecuteInWebWorker(ok, done) {
        ok(true, "Could enter the web worker");

        Dexie.delete("codeFromWorker").then(function() {
            var db = new Dexie("codeFromWorker");
            ok(true, "Could create a Dexie instance from within a web worker");

            db.version(1).stores({ table1: "++" });
            ok(true, "Could define schema");

            db.open();
            ok(true, "Could open the database");

            return db.transaction('rw', db.table1, function() {
                ok(true, "Could create a transaction");
                db.table1.add({ name: "My first object" }).then(function(id) {
                    ok(true, "Could add object that got id " + id);
                }).catch(function(err) {
                    ok(false, "Got error: " + err);
                });
            });
        }).then(function () {
            ok(true, "Transaction committed");
        }).catch(function(err) {
            ok(false, "Transaction failed");
        }).finally(done);
    }

    //
    // Frameworking...
    //
    if (!window.Worker) {
        ok(false, "WebWorkers not supported");
        start();
        return;
    }

    var worker = new Worker(window.workerSource || "worker.js");
    worker.postMessage({
        imports: imports,
        code: CodeToExecuteInWebWorker.toString()
    });

    worker.onmessage = function(e) {
        switch (e.data[0]) {
        case "ok":
            ok(e.data[1], e.data[2]);
            break;
        case "done":
            worker.terminate();
            start();
            break;
        }
    }

    worker.onerror = function(e) {
        worker.terminate();
        ok(false, "Worker errored: " + e.message);
        start();
    };
});

asyncTest("Issue#100 - not all indexes are created", function () {
    var db = new Dexie("TestDB");
    db.version(20)
      .stores({
          t: 'id,displayName,*displayNameParts,isDeleted,countryRef,[countryRef+isDeleted],autoCreated,needsReview,[autoCreated+isDeleted],[needsReview+isDeleted],[autoCreated+needsReview+isDeleted],[autoCreated+countryRef+needsReview+isDeleted],[autoCreated+countryRef+needsReview+isDeleted],[autoCreated+robotsNoIndex+isDeleted],[autoCreated+needsReview+robotsNoIndex+isDeleted],[autoCreated+countryRef+robotsNoIndex+isDeleted],[autoCreated+countryRef+needsReview+robotsNoIndex+isDeleted]',
      });
    db.open().then(function() {
        return Dexie.Promise.all(
            db.t.orderBy("id").first(),
            db.t.orderBy("displayName").first(),
            db.t.orderBy("displayNameParts").first(),
            db.t.orderBy("isDeleted").first(),
            db.t.orderBy("countryRef").first(),
            db.t.orderBy("[countryRef+isDeleted]").first(),
            db.t.orderBy("autoCreated").first(),
            db.t.orderBy("needsReview").first(),
            db.t.orderBy("[autoCreated+isDeleted]").first(),
            db.t.orderBy("[needsReview+isDeleted]").first(),
            db.t.orderBy("[autoCreated+needsReview+isDeleted]").first(),
            db.t.orderBy("[autoCreated+countryRef+needsReview+isDeleted]").first(),
            db.t.orderBy("[autoCreated+robotsNoIndex+isDeleted]").first(),
            db.t.orderBy("[autoCreated+needsReview+robotsNoIndex+isDeleted]").first(),
            db.t.orderBy("[autoCreated+countryRef+robotsNoIndex+isDeleted]").first(),
            db.t.orderBy("[autoCreated+countryRef+needsReview+robotsNoIndex+isDeleted]").first()
        );
    }).then(function(res) {
        ok(false, "Should not succeed with creating the same index twice");
    }).catch(function(err) {
        ok(true, "Catched error trying to create duplicate indexes: " + err);
        return db.t.toArray();
    }).then(function(a) {
        ok(false, "Database should have failed here");
    }).catch(function(err) {
        ok(true, "Got exception when trying to work agains DB: " + err);
    }).then(function () {
        // Close the database and open dynamically to check that
        // it should not exist when failed to open.
        db.close();
        db = new Dexie("TestDB");
        return db.open();
    }).then(function() {
        ok(false, "Should not succeed to open the database. It should not have been created.");
        equal(db.tables.length, 0, "At least expect no tables to have been created on the database");
    }).catch(function(err) {
        ok(true, "Should not succeed to dynamically open db because it should not exist");
    }).finally(start);

});

asyncTest("Dexie.exists", function () {
    var db = null;
    Dexie.exists("TestDB").then(function(result) {
        equal(result, false, "Should not exist yet");
        db = new Dexie("TestDB");
        db.version(1).stores({
            some: "schema"
        });
        return db.open();
    }).then(function() {
        return Dexie.exists("TestDB");
    }).then(function(result) {
        equal(result, true, "Should exist now and has another open connection.");
        db.close();
        return Dexie.exists("TestDB");
    }).then(function(result) {
        equal(result, true, "Should still exist");
        return Dexie.delete("TestDB");
    }).then(function () {
        return Dexie.exists("TestDB");
    }).then(function(result) {
        equal(result, false, "Should have been deleted now");
    }).catch(function(e) {
        ok(false, "Error: " + e);
    }).finally(start);
});

asyncTest("No auto-open", ()=> {
    let db = new Dexie("TestDB", {autoOpen: false});
    db.version(1).stores({foo: "id"});
    db.foo.toArray(res => {
        ok(false, "Should not get result. Should have failed.");
    }).catch(e => {
        ok(e instanceof Dexie.DatabaseClosedError, "Should catch DatabaseClosedError");
    }).then(() => {
        db.open();
        return db.foo.toArray();
    }).then(res => {
        equal(res.length, 0, "Got an answer now when opened.");
        db.close();
        let openPromise = db.open().then(()=>{
            debugger;
            ok(false, "Should not succeed to open because we closed it during the open sequence.")
        }).catch(e=> {
            ok(e instanceof Dexie.DatabaseClosedError, "Got DatabaseClosedError from the db.open() call.");
        });
        let queryPromise = db.foo.toArray().then(()=>{
            ok(false, "Should not succeed to query because we closed it during the open sequence.")
        }).catch(e=> {
            ok(e instanceof Dexie.DatabaseClosedError, "Got DatabaseClosedError when querying: " + e);
        });
        db.close();
        return Promise.all([openPromise, queryPromise]);
    }).catch(e => {
        ok(e instanceof Dexie.OpenFailedError);
    }).catch(e => {
        ok(false, e);
    }).finally(start);
});

asyncTest("db.close", ()=> {
    let db = new Dexie("TestDB");
    db.version(1).stores({foo: "id"});
    db.foo.toArray(res => {
        equal(res.length, 0, "Database auto-opened and I got a result from my query");
    }).then(() => {
        db.close();
        return db.foo.toArray();
    }).catch(e => {
        ok(e instanceof Dexie.DatabaseClosedError, "Should catch DatabaseClosedError");
        return db.open();
    }).then(()=>{
        return db.foo.toArray();
    }).then(res => {
        equal(res.length, 0, "Database re-opened and I got a result from my query");
    }).catch(e => {
        ok(false, e);
    }).finally(()=>{
        db.delete().catch(e=>console.error(e)).finally(start);
    });
});
<|endoftext|>


<commit_before>module('Path');

test('path.join(path)', function() {
	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);

	var path2 = new Path();
	path2.add(10, 0);
	path2.add(20, 10);

	path.join(path2);
	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 20, y: 10 } }');
	equals(function() {
		return paper.project.activeLayer.children.length;
	}, 1);

	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);

	var path2 = new Path();
	path2.add(20, 10);
	path2.add(10, 0);
	path.join(path2);
	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 20, y: 10 } }');

	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);

	var path2 = new Path();
	path2.add(30, 10);
	path2.add(40, 0);
	path.join(path2);
	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 30, y: 10 } },{ point: { x: 40, y: 0 } }');

	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);
	path.add(20, 10);

	var path2 = new Path();
	path2.add(0, 0);
	path2.add(10, 5);
	path2.add(20, 10);

	path.join(path2);

	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 20, y: 10 } },{ point: { x: 10, y: 5 } }');
	equals(function() {
		return path.closed;
	}, true);
});

test('path.remove()', function() {
	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);
	path.add(20, 0);
	path.add(30, 0);

	path.removeSegment(0);
	equals(function() {
		return path.segments.length;
	}, 3);

	path.removeSegment(0);
	equals(function() {
		return path.segments.length;
	}, 2);

	path.removeSegments(0, 2);
	equals(function() {
		return path.segments.length;
	}, 0);

	path.remove();

	equals(function() {
		return paper.project.activeLayer.children.length;
	}, 0);
});

test('Is the path deselected after setting a new list of segments?', function() {
	var path = new Path([0, 0]);
	path.selected = true;
	equals(function() {
		return path.selected;
	}, true);
	equals(function() {
		return paper.project.selectedItems.length;
	}, 1);

	path.segments = [[0, 10]];
	equals(function() {
		return path.selected;
	}, false);
	equals(function() {
		return paper.project.selectedItems.length;
	}, 0);
});

test('Path#reverse', function() {
	var path = new Path.Circle([100, 100], 30);
	path.reverse();
	equals(path.segments.toString(), '{ point: { x: 100, y: 130 }, handleIn: { x: -16.56854, y: 0 }, handleOut: { x: 16.56854, y: 0 } },{ point: { x: 130, y: 100 }, handleIn: { x: 0, y: 16.56854 }, handleOut: { x: 0, y: -16.56854 } },{ point: { x: 100, y: 70 }, handleIn: { x: 16.56854, y: 0 }, handleOut: { x: -16.56854, y: 0 } },{ point: { x: 70, y: 100 }, handleIn: { x: 0, y: -16.56854 }, handleOut: { x: 0, y: 16.56854 } }');
});

<commit_msg>Change Path#removeSegments(from, to) test to fail and add a todo questioning if its behaviour is correct. Also add a failing Path#removeSegments() test.<commit_after>module('Path');

test('path.join(path)', function() {
	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);

	var path2 = new Path();
	path2.add(10, 0);
	path2.add(20, 10);

	path.join(path2);
	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 20, y: 10 } }');
	equals(function() {
		return paper.project.activeLayer.children.length;
	}, 1);

	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);

	var path2 = new Path();
	path2.add(20, 10);
	path2.add(10, 0);
	path.join(path2);
	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 20, y: 10 } }');

	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);

	var path2 = new Path();
	path2.add(30, 10);
	path2.add(40, 0);
	path.join(path2);
	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 30, y: 10 } },{ point: { x: 40, y: 0 } }');

	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);
	path.add(20, 10);

	var path2 = new Path();
	path2.add(0, 0);
	path2.add(10, 5);
	path2.add(20, 10);

	path.join(path2);

	equals(path.segments.toString(), '{ point: { x: 0, y: 0 } },{ point: { x: 10, y: 0 } },{ point: { x: 20, y: 10 } },{ point: { x: 10, y: 5 } }');
	equals(function() {
		return path.closed;
	}, true);
});

test('path.remove()', function() {
	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);
	path.add(20, 0);
	path.add(30, 0);

	path.removeSegment(0);
	equals(function() {
		return path.segments.length;
	}, 3);

	path.removeSegment(0);
	equals(function() {
		return path.segments.length;
	}, 2);

	// TODO: shouldn't this remove two segments? The segments from index 0 till
	// index 1?
	path.removeSegments(0, 1);
	equals(function() {
		return path.segments.length;
	}, 0);

	path.remove();

	equals(function() {
		return paper.project.activeLayer.children.length;
	}, 0);
});

test('path.removeSegments()', function() {
	var path = new Path();
	path.add(0, 0);
	path.add(10, 0);
	path.add(20, 0);
	path.add(30, 0);

	path.removeSegments();
	equals(function() {
		return path.segments.length;
	}, 0);
});

test('Is the path deselected after setting a new list of segments?', function() {
	var path = new Path([0, 0]);
	path.selected = true;
	equals(function() {
		return path.selected;
	}, true);
	equals(function() {
		return paper.project.selectedItems.length;
	}, 1);

	path.segments = [[0, 10]];
	equals(function() {
		return path.selected;
	}, false);
	equals(function() {
		return paper.project.selectedItems.length;
	}, 0);
});

test('Path#reverse', function() {
	var path = new Path.Circle([100, 100], 30);
	path.reverse();
	equals(path.segments.toString(), '{ point: { x: 100, y: 130 }, handleIn: { x: -16.56854, y: 0 }, handleOut: { x: 16.56854, y: 0 } },{ point: { x: 130, y: 100 }, handleIn: { x: 0, y: 16.56854 }, handleOut: { x: 0, y: -16.56854 } },{ point: { x: 100, y: 70 }, handleIn: { x: 16.56854, y: 0 }, handleOut: { x: -16.56854, y: 0 } },{ point: { x: 70, y: 100 }, handleIn: { x: 0, y: -16.56854 }, handleOut: { x: 0, y: 16.56854 } }');
});

<|endoftext|>


<commit_before>"use strict";

const assert = require("assert");
const _ = require("lodash");
const theme = require("../lib/theme");

describe("theme", () => {

  it("should generate next themes", () => {

    const themes = theme.generateThemes(
      [
        "ココア",
        "チノ",
        "リゼ",
        "千夜",
        "シャロ",
        "マヤ",
        "メグ",
        "青山ブルーマウンテン",
        "モカ"
      ],
      "ココア",
      "タカヒロ",
      ["青山ブルーマウンテン"]
    );

    assert(Array.isArray(themes));
    assert.strictEqual(themes.length, 4);
    assert.strictEqual(themes[0], "ココア");
    assert.strictEqual(themes[3], "タカヒロ");

    // check duplicated values
    assert.strictEqual(_.filter(
      themes,
      (value, index, iteratee) => _.includes(iteratee, value, index + 1)
    ).length, 0);

    assert.strictEqual(_.intersection(
      themes.slice(1, -1),
      ["ココア", "タカヒロ", "青山ブルーマウンテン"]
    ).length, 0);

    assert.strictEqual(_.difference(
      themes,
      [
        "ココア",
        "チノ",
        "リゼ",
        "千夜",
        "シャロ",
        "マヤ",
        "メグ",
        "青山ブルーマウンテン",
        "モカ",
        "タカヒロ"
      ]
    ).length, 0);

  });

  it("should generate next sequence", () => {

    const seq = theme.getNextSequence(
      ["モカ"],
      ["モカ", "あんこ", "ティッピー", "ワイルドギース"]
    );

    assert(Array.isArray(seq));
    assert.notStrictEqual(seq[0], "モカ");

  });

  it("should generate next sequence 2", () => {

    const seq = theme.getNextSequence(
      ["モカ", "あんこ"],
      ["モカ", "あんこ", "ティッピー", "ワイルドギース"]
    );

    assert(Array.isArray(seq));
    assert.deepEqual(seq, ["あんこ"]);

  });

});
<commit_msg>Fix theme test<commit_after>"use strict";

const assert = require("assert");
const _ = require("lodash");
const theme = require("../lib/theme");

describe("theme", () => {

  it("should generate next themes", () => {

    const themes = theme.generateThemes(
      [
        "ココア",
        "チノ",
        "リゼ",
        "千夜",
        "シャロ",
        "マヤ",
        "メグ",
        "青山ブルーマウンテン",
        "モカ"
      ],
      "ココア",
      "タカヒロ",
      ["青山ブルーマウンテン"]
    );

    assert(Array.isArray(themes));
    assert.strictEqual(themes.length, 4);
    assert.strictEqual(themes[0], "ココア");
    assert.strictEqual(themes[3], "タカヒロ");

    // check duplicated values
    assert.strictEqual(_.filter(
      themes,
      (value, index, iteratee) => _.includes(iteratee, value, index + 1)
    ).length, 0);

    assert.strictEqual(_.intersection(
      themes.slice(1, -1),
      ["ココア", "タカヒロ", "青山ブルーマウンテン"]
    ).length, 0);

    assert.strictEqual(_.difference(
      themes,
      [
        "ココア",
        "チノ",
        "リゼ",
        "千夜",
        "シャロ",
        "マヤ",
        "メグ",
        "青山ブルーマウンテン",
        "モカ",
        "タカヒロ"
      ]
    ).length, 0);

  });

  it("should generate next sequence", () => {

    const seq = theme.getNextSequence(
      ["モカ"],
      ["モカ", "あんこ", "ティッピー", "ワイルドギース"]
    );

    assert(Array.isArray(seq));
    assert.notStrictEqual(seq[0], "モカ");

    const seq2 = theme.getNextSequence(
      ["モカ", "あんこ"],
      ["モカ", "あんこ", "ティッピー", "ワイルドギース"]
    );

    assert(Array.isArray(seq2));
    assert.deepEqual(seq2, ["あんこ"]);

  });

});
<|endoftext|>


<commit_before>const Thing = require('../dist/Thing.umd');
const _ = require('underscore');

global.expect = require('chai').expect;

// require('babel/register');

(function setup () {
  beforeEach(function() {

    global.thing1 = {
      name: 'Light', // The display name for the thing.
      id: 'Light',
      username: 'YourUsernameHere', // The username of the account you want this device to be added to.
      properties: {
        state: 'off',
        lightconditions: function () {
          return 'unset';
        }
      },
      actions: [ // A list of action objects with ids
        {
          name: 'On', // Display name for the action
          description: 'Turns the light on.', // Optional description
          id: 'turn_light_on', // A unique id
          schedule: 'at 9:00am', // Optional scheduling using later.js
          event: 'Light turned on', // Optional event to emit when called.
          function: function () {
            // The implementation of the action.
            return 'Light on.';
          }
        },
        {
          name: 'off',
          id: 'turn_light_off',
          schedule: 'at 8:30pm',
          event: 'Light turned off',
          function: function () {
            return 'Light off.';
          }
        },
        {
          name: 'Log light data', // Events get a display name like actions
          id: 'light_data', // Events also get an id that is unique to the device
          type: 'light', // Currently need for visualization component... HACK.
          template: 'sensor',
          schedule: 'every 1 second', // Events should have a schedule option that determines how often to check for conditions.
          function: function () {
            // function should return the event to emit when it should be emited.
            return 10;
          }
        }
      ],
      events: [
        {
          name: 'It\'s dark.',
          id: 'dark',
          on: 'light_data', // Hook into an action.
          function: function () {
            return;
          }
        },
        {
          name: 'It\'s light.',
          id: 'light',
          on: 'light_data', // Hook into an action.
          function: function () {
            return;
          }
        }
      ]
    };

    global.thing2 = {
      name: 'Light', // The display name for the thing.
      id: 'Light',
      username: 'YourUsernameHere', // The username of the account you want this device to be added to.
      properties: { // These can be updated by the API.
        state: 'off',
        lightconditions: function () {
          return 'unset';
        }
      },
      actions: { // a list of action objects with keys
        turn_light_on: {
          name: 'On', // Display name for the action
          description: 'Turns the light on.', // Optional description
          schedule: 'at 9:00am', // Optional scheduling using later.js
          event: 'Light turned on', // Optional event to emit when called.
          function: function () {
            // The implementation of the action.
            return 'Light on.';
          }
        },
        turn_light_off: {
          name: 'off',
          schedule: 'at 8:30pm',
          event: 'Light turned off',
          function: function () {
            return 'Light off.';
          }
        },
        light_data: {
          name: 'Log light data', // Events get a display name like actions
          type: 'light', // Currently need for visualization component... HACK.
          template: 'sensor',
          schedule: 'every 1 second', // Events should have a schedule option that determines how often to check for conditions.
          function: function () {
            return 10;
          }
        }
      },
      events: {
        dark: {
          name: 'It\'s dark.',
          on: 'light_data', // Hook into an action.
          function: function () {
            return;
          }
        },
        light: {
          name: 'It\'s light.',
          on: 'light_data',
          function: function () {
            return;
          }
        }
      }
    }
  });

  afterEach(function() {
    delete global.thing1;
    delete global.thing2;
  });
})();

describe('Thing test', () => {
  beforeEach(() => {
    // global.testThing = new Thing(thing1);
    global.testThing2 = new Thing(thing2);
  });

  it('should have cloned metadata', () => {
    // expect(testThing.name).to.equal('Light');
    // expect(testThing.id).to.equal('Light');
    // expect(testThing.username).to.equal('YourUsernameHere');
    expect(testThing2.name).to.equal('Light');
    expect(testThing2.id).to.equal('Light');
    expect(testThing2.username).to.equal('YourUsernameHere');
  });

  describe('ACTIONS', () => {
    it('should register actions in the config object', () => {
      // expect(_.allKeys(testThing.actions).length).to.equal(3);
      expect(_.allKeys(testThing2.actions).length).to.equal(3);
    });

    it('should return the right action object when given an action id.', () => {
      // var action = testThing.getAction('light_data');
      var action2 = testThing2.getAction('light_data')
      // console.log(action2);
      // expect(action.name).to.equal('Log light data');
      expect(action2.name).to.equal('Log light data');
    });

    it('should be able to call a registered action.', () => {
      expect(testThing2.callAction('turn_light_on')).to.equal('Light on.');
    });

    it('should emit an event when an action is called', () => {
      var event = false;
      testThing2.on('turn_light_on', () => {
        return event = true;
      });
      testThing2.callAction('turn_light_on');
      expect(event).to.equal(true);
    });
  });

  describe('EVENTS', () => {
    it('should register events in the config object', () => {
      expect(_.allKeys(testThing2.events).length).to.equal(2);
    });

    it('should return the right event object when given an id.', () => {
      // var component = testThing.getEvent('dark');
      var component2 = testThing2.getEvent('dark');
      // expect(component.name).to.equal('It\'s dark.');
      expect(component2.name).to.equal('It\'s dark.');
    });
  });

  describe('PROPERTIES', () => {
    // Maybe killing this...
    // it('should update a component property correctly', () => {
    //   testThing.updateComponentProperty('turn_light_on', 'schedule', 'at 9:30am')
    //   expect(testThing.getAction('turn_light_on').schedule).to.equal('at 9:30am');
    // });

    // Note: testThing 2 has experimental support for properties
    it('should initialize correctly', () => {
      expect(testThing2.getProperty('lightconditions')).to.equal('unset');
    });

    // Note: testThing 2 has experimental support for properties
    it('should set a property', () => {
      testThing2.setProperty('lightconditions', 'dark');
      expect(testThing2.getProperty('lightconditions')).to.equal('dark');
    });

    it('should emit an event when a property is set', () => {
      var event = false;
      testThing2.on('property-updated', () => {
        return event = true;
      });
      testThing2.setProperty('lightconditions', 'light');
      expect(testThing2.getProperty('lightconditions')).to.equal('light');
      expect(event).to.equal(true);
    });

  });

  afterEach(() => {
    delete global.testThing2;
  });
});
<commit_msg>Clean up tests.<commit_after>const Thing = require('../dist/Thing.umd');
const _ = require('underscore');

global.expect = require('chai').expect;

(function setup () {
  beforeEach(function() {

    global.thing = {
      name: 'Light', // The display name for the thing.
      id: 'Light',
      username: 'YourUsernameHere', // The username of the account you want this device to be added to.
      properties: { // These can be updated by the API.
        state: 'off',
        lightconditions: function () {
          return 'unset';
        }
      },
      actions: { // a list of action objects with keys
        turn_light_on: {
          name: 'On', // Display name for the action
          description: 'Turns the light on.', // Optional description
          schedule: 'at 9:00am', // Optional scheduling using later.js
          event: 'Light turned on', // Optional event to emit when called.
          function: function () {
            // The implementation of the action.
            return 'Light on.';
          }
        },
        turn_light_off: {
          name: 'off',
          schedule: 'at 8:30pm',
          event: 'Light turned off',
          function: function () {
            return 'Light off.';
          }
        },
        light_data: {
          name: 'Log light data', // Events get a display name like actions
          type: 'light', // Currently need for visualization component... HACK.
          template: 'sensor',
          schedule: 'every 1 second', // Events should have a schedule option that determines how often to check for conditions.
          function: function () {
            return 10;
          }
        }
      },
      events: {
        dark: {
          name: 'It\'s dark.',
          on: 'light_data', // Hook into an action.
          function: function () {
            return;
          }
        },
        light: {
          name: 'It\'s light.',
          on: 'light_data',
          function: function () {
            return;
          }
        }
      }
    }
  });

  afterEach(function() {
    delete global.thing;
  });
})();

describe('Thing test', () => {
  beforeEach(() => {
    global.testThing = new Thing(thing);
  });

  it('should have cloned metadata', () => {
    expect(testThing.name).to.equal('Light');
    expect(testThing.id).to.equal('Light');
    expect(testThing.username).to.equal('YourUsernameHere');
  });

  describe('ACTIONS', () => {
    it('should register actions in the config object', () => {
      expect(_.allKeys(testThing.actions).length).to.equal(3);
    });

    it('should return the right action object when given an action id.', () => {
      var action = testThing.getAction('light_data')
      expect(action.name).to.equal('Log light data');
    });

    it('should be able to call a registered action.', () => {
      expect(testThing.callAction('turn_light_on')).to.equal('Light on.');
    });

    it('should emit an event when an action is called', () => {
      var event = false;
      testThing.on('turn_light_on', () => {
        return event = true;
      });
      testThing.callAction('turn_light_on');
      expect(event).to.equal(true);
    });
  });

  describe('EVENTS', () => {
    it('should register events in the config object', () => {
      expect(_.allKeys(testThing.events).length).to.equal(2);
    });

    it('should return the right event object when given an id.', () => {
      var component = testThing.getEvent('dark');
      expect(component.name).to.equal('It\'s dark.');
    });
  });

  describe('PROPERTIES', () => {
    it('should initialize correctly', () => {
      expect(testThing.getProperty('lightconditions')).to.equal('unset');
    });

    it('should set a property', () => {
      testThing.setProperty('lightconditions', 'dark');
      expect(testThing.getProperty('lightconditions')).to.equal('dark');
    });

    it('should emit an event when a property is set', () => {
      var event = false;
      testThing.on('property-updated', () => {
        return event = true;
      });
      testThing.setProperty('lightconditions', 'light');
      expect(testThing.getProperty('lightconditions')).to.equal('light');
      expect(event).to.equal(true);
    });

  });

  afterEach(() => {
    delete global.testThing;
  });
});
<|endoftext|>


<commit_before>var assert = require('chai').assert,
    doesMQMatch = require('../').match;

describe('#doesMQMatch() media `type`', function () {
    describe('Type', function(){
        it('should return true for a correct match', function(){
            assert.equal(doesMQMatch('screen and (color)', {type: 'screen', color: 1}), true);
        });

        it('should return true for when type === all', function(){
            assert.equal(doesMQMatch('screen and (min-width: 48em)', {type: 'all', width: 1000}), true);
        });

        it('should return false for an incorrect match', function(){
            assert.equal(doesMQMatch('screen and (min-width: 48em)', {type: 'handheld'}), false);
        });

        it('should return true when no type values are passed in', function(){
            assert.equal(doesMQMatch('screen and (min-width: 48em)', {width: 1000}), true);
        });
    });
});

describe('#doesMQMatch() `not` operator', function () {
    describe('Type', function(){
        it('should return false when it matches up', function(){
            assert.equal(doesMQMatch('not screen and (color)', {type: 'screen', color: 1}), false);
        });

        it('should not disrupt an OR query', function(){
            assert.equal(doesMQMatch('not screen and (color), screen and (min-height: 48em)', {type: 'screen', height: 1000}), true);
        });

        it('should return false for when type === all', function(){
            assert.equal(doesMQMatch('not all and (min-width: 48em)', {type: 'all', width: 1000}), false);
        });

        it('should return true for inverted value', function(){
            assert.equal(doesMQMatch('not screen and (min-width: 48em)', {width: '24em'}), true);
        });
    });
});

describe('#doesMQMatch() Media Features', function(){
    describe('Width', function(){
        it('should return true for a width higher than a min-width', function(){
            assert.equal(doesMQMatch('(min-width: 48em)', {width: '80em'}), true);
        });

        it('should return false for a width higher than a min-width', function(){
            assert.equal(doesMQMatch('(min-width: 48em)', {width: '20em'}), false);
        });

        it('should return false when no width values are passed in', function(){
            assert.equal(doesMQMatch('(min-width: 48em)', {resolution: 72}), false);
        });

        it('should return true with multiple properties', function(){
            assert.equal(doesMQMatch('(min-width: 48em) and (color)', {width: '60em'}), true);
        });

        it('should convert units properly', function(){
            assert.equal(doesMQMatch('(min-width: 30em) and (color)', {width: 1024}), true);
        });
    });

    describe('Height', function(){
        it('should return true for a height higher than a min-height', function(){
            assert.equal(doesMQMatch('(min-height: 48em)', {height: '80em'}), true);
        });

        it('should return false for a height higher than a min-height', function(){
            assert.equal(doesMQMatch('(min-height: 48em)', {height: '20em'}), false);
        });

        it('should return false when no height values are passed in', function(){
            assert.equal(doesMQMatch('(min-height: 48em)', {resolution: 72}), false);
        });

        it('should return true with multiple properties', function(){
            assert.equal(doesMQMatch('(min-height: 48em) and (color)', {height: '60em'}), true);
        });

        it('should convert units properly', function(){
            assert.equal(doesMQMatch('(min-height: 30em) and (color)', {height: 1024}), true);
        });
    });

    describe('Device-Width', function(){
        it('should return true for a device-width higher than a min-device-width', function(){
            assert.equal(doesMQMatch('(min-device-width: 48em)', {'device-width': '80em'}), true);
        });

        it('should return false for a device-width higher than a min-device-width', function(){
            assert.equal(doesMQMatch('(min-device-width: 48em)', {'device-width': '20em'}), false);
        });

        it('should return false when no device-width values are passed in', function(){
            assert.equal(doesMQMatch('(min-device-width: 48em)', {resolution: 72}), false);
        });

        it('should return true with multiple properties', function(){
            assert.equal(doesMQMatch('(min-device-width: 48em) and (color)', {'device-width': '60em'}), true);
        });

        it('should convert units properly', function(){
            assert.equal(doesMQMatch('(min-device-width: 30em) and (color)', {'device-width': 1024}), true);
        });
    });

    describe('Device-Height', function(){
        it('should return true for a device-height higher than a min-device-height', function(){
            assert.equal(doesMQMatch('(min-device-height: 48em)', {'device-height': '80em'}), true);
        });

        it('should return false for a device-height higher than a min-device-height', function(){
            assert.equal(doesMQMatch('(min-device-height: 48em)', {'device-height': '20em'}), false);
        });

        it('should return false when no device-height values are passed in', function(){
            assert.equal(doesMQMatch('(min-device-height: 48em)', {resolution: 72}), false);
        });

        it('should return true with multiple properties', function(){
            assert.equal(doesMQMatch('(min-device-height: 48em) and (color)', {'device-height': '60em'}), true);
        });

        it('should convert units properly', function(){
            assert.equal(doesMQMatch('(min-device-height: 30em) and (color)', {'device-height': 1024}), true);
        });
    });

    describe('Color', function () {
        it('should return true for a color higher than a min-color', function(){
            assert.equal(doesMQMatch('(min-color: 2)', {color: 3 }), true);
        });

        it('should return false for a color higher than a max-color', function(){
            assert.equal(doesMQMatch('(max-color: 2)', {color: 4 }), false);
        });

        it('should return false if color isnt passed in', function(){
            assert.equal(doesMQMatch('max-width: 767px and (color)', {width: 300}), false);
        });

        it('should work for undefined color values', function(){
            assert.equal(doesMQMatch('(color)', {color: 4 }), true);
            assert.equal(doesMQMatch('(color)', {color: 0 }), false);
        });
    });

    describe('Color-Index', function () {
        it('should return true for a color-index higher than a min-color-index', function(){
            assert.equal(doesMQMatch('(min-color-index: 1)', {'color-index': 256 }), true);
        });

        it('should return false for a color-index higher than a max-color-index', function(){
            assert.equal(doesMQMatch('(max-color-index: 256)', {'color-index': 512 }), false);
        });

        it('should return false if color-index isnt passed in', function(){
            assert.equal(doesMQMatch('max-width: 767px and (color-index)', {width: 300}), false);
        });

        it('should work for undefined color-index values', function(){
            assert.equal(doesMQMatch('(color-index)', {'color-index': 1 }), true);
            assert.equal(doesMQMatch('(color-index)', {'color-index': 0 }), false);
        });
    });

    describe('Monochrome', function () {
        it('should return true for a monochrome higher than a min-monochrome', function(){
            assert.equal(doesMQMatch('(min-monochrome: 1)', {monochrome: 3 }), true);
        });

        it('should return false for a monochrome higher than a max-monochrome', function(){
            assert.equal(doesMQMatch('(max-monochrome: 3)', {monochrome: 4 }), false);
        });

        it('should return false if monochrome isnt passed in', function(){
            assert.equal(doesMQMatch('max-width: 767px and (monochrome)', {width: 300}), false);
        });

        it('should work for undefined monochrome values', function(){
            assert.equal(doesMQMatch('(monochrome)', {'monochrome': 3 }), true);
            assert.equal(doesMQMatch('(monochrome)', {'monochrome': 0 }), false);
        });
    });

    describe('Resolution', function () {
        it('should return true for a resolution higher than a min-resolution', function(){
            assert.equal(doesMQMatch('(min-resolution: 50dpi)', {resolution: 72 }), true);
        });

        it('should return false for a resolution higher than a max-resolution', function(){
            assert.equal(doesMQMatch('(max-resolution: 72dpi)', {resolution: 300 }), false);
        });

        it('should return false if resolution isnt passed in', function(){
            assert.equal(doesMQMatch('(max-resolution: 72dpi)', {width: 300}), false);
        });

        it('should convert units properly', function(){
            assert.equal(doesMQMatch('(min-resolution: 72dpi)', {resolution: '75dpcm' }), false);
        });
    });

    describe('Aspect-Ratio', function () {
        it('should return true for an aspect-ratio higher than a min-aspect-ratio', function(){
            assert.equal(doesMQMatch('(min-aspect-ratio: 4/3)', {'aspect-ratio': '16/9' }), true);
        });

        it('should return false for an aspect-ratio higher than a max-aspect-ratio', function(){
            assert.equal(doesMQMatch('(max-aspect-ratio: 4/3)', {'aspect-ratio': '16/9' }), false);
        });

        it('should return false if aspect-ratio isnt passed in', function(){
            assert.equal(doesMQMatch('(max-aspect-ratio: 72dpi)', {width: 300}), false);
        });

        it('should work with strings and numbers', function(){
            assert.equal(doesMQMatch('(min-aspect-ratio: 2560/1440)', {'aspect-ratio': 4/3 }), false);
        });
    });

    describe('Scan', function () {
        it('should return true for a correct match', function(){
            assert.equal(doesMQMatch('tv and (scan: progressive)', {scan: 'progressive' }), true);
        });

        it('should return false for an incorrect match', function(){
            assert.equal(doesMQMatch('tv and (scan: progressive)', {scan: 'interlace' }), false);
        });
    });

    describe('Orientation', function () {
        it('should return true for a correct match', function(){
            assert.equal(doesMQMatch('screen and (orientation: portrait)', {orientation: 'portrait' }), true);
        });

        it('should return false for an incorrect match', function(){
            assert.equal(doesMQMatch('screen and (orientation: landscape)', {orientation: 'portrait' }), false);
        });

        it('should return false if orientation isnt passed in', function(){
            assert.equal(doesMQMatch('screen and (orientation: landscape)', {width: '50em' }), false);
        });
    });

    describe('Grid', function () {
        it('should return true for a correct match', function(){
            assert.equal(doesMQMatch('handheld and (grid)', {grid: true }), true);
        });

        it('should return false if grid isnt passed in', function(){
            assert.equal(doesMQMatch('tv and (grid)', {scan: 'interlace' }), false);
        });

        it('should return false if grid is explictly set to false', function(){
            assert.equal(doesMQMatch('tv and (grid)', {scan: 'interlace', grid: false }), false);
        });
    });
});

describe('#doesMQMatch() Integration Tests', function () {
    describe('Real World Use Cases (mostly AND)', function(){
        it('should return true because of width and type match', function(){
            assert.equal(doesMQMatch('screen and (min-width: 767px)', {type: 'screen', width: 980}), true);
        });

        it('should return true because of width is within bounds', function(){
            assert.equal(doesMQMatch('screen and (min-width: 767px) and (max-width: 979px)', {type: 'screen', width: 800}), true);
        });

        it('should return false because width is out of bounds', function(){
            assert.equal(doesMQMatch('screen and (min-width: 767px) and (max-width: 979px)', {type: 'screen', width: 980}), false);
        });

        it('should return false since monochrome is not specified', function(){
            assert.equal(doesMQMatch('screen and (monochrome)', {width: 980}), false);
        });

        it('should return true since color > 0', function(){
            assert.equal(doesMQMatch('screen and (color)', {type: 'all', color: 1}), true);
        });

        it('should return false since color = 0', function(){
            assert.equal(doesMQMatch('screen and (color)', {type: 'all', color: 0}), false);
        });

    });

    describe('Grouped Media Queries (OR)', function(){
        it('should return true because of color', function(){
            assert.equal(doesMQMatch('screen and (min-width: 767px), screen and (color)', {type: 'screen', color: 1}), true);
        });

        it('should return true because of width and type', function(){
            assert.equal(doesMQMatch('screen and (max-width: 1200px), handheld and (monochrome)', {type: 'screen', width: 1100}), true);
        });

        it('should return false because of monochrome mis-match', function(){
            assert.equal(doesMQMatch('screen and (max-width: 1200px), handheld and (monochrome)', {type: 'screen', monochrome: 0}), false);
        });

    });
});

<commit_msg>add 100% test coverage<commit_after>/* global describe, it */
'use strict';

/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/

var expect = require('chai').expect,
    doesMQMatch = require('../').match;

describe('mediaQuery.match()', function () {

    describe('Equality Check', function(){

        it('Orientation: should return true for a correct match (===)', function () {
            expect(doesMQMatch('(orientation: portrait)', {orientation: 'portrait' })).to.equal(true);
        });

        it('Orientation: should return false for an incorrect match (===)', function () {
            expect(doesMQMatch('(orientation: landscape)', {orientation: 'portrait' })).to.equal(false);
        });

        it('Scan: should return true for a correct match (===)', function () {
            expect(doesMQMatch('(scan: progressive)', {scan: 'progressive' })).to.equal(true);
        });

        it('Scan: should return false for an incorrect match (===)', function () {
            expect(doesMQMatch('(scan: progressive)', {scan: 'interlace' })).to.equal(false);
        });

        it('Width: should return true for a correct match', function(){
            expect(doesMQMatch('(width: 800px)', {width: 800})).to.equal(true);
        });

        it('Width: should return false for an incorrect match', function(){
            expect(doesMQMatch('(width: 800px)', {width: 900})).to.equal(false);
        });
    });

    describe('Length Check', function(){

        describe('Width', function () {
            it('should return true for a width higher than a min-width', function(){
                expect(doesMQMatch('(min-width: 48em)', {width: '80em'})).to.equal(true);
            });

            it('should return false for a width lower than a min-width', function(){
                expect(doesMQMatch('(min-width: 48em)', {width: '20em'})).to.equal(false);
            });

            it('should return false when no width value is specified', function(){
                expect(doesMQMatch('(min-width: 48em)', {resolution: 72})).to.equal(false);
            });
        });

        describe('Different Units', function () {
            it('should work with ems', function(){
                expect(doesMQMatch('(min-width: 500px)', {width: '48em'})).to.equal(true);
            });

            it('should work with rems', function(){
                expect(doesMQMatch('(min-width: 500px)', {width: '48rem'})).to.equal(true);
            });

            it('should work with cm', function(){
                expect(doesMQMatch('(max-height: 1000px)', {height: '20cm'})).to.equal(true);
            });

            it('should work with mm', function(){
                expect(doesMQMatch('(max-height: 1000px)', {height: '200mm'})).to.equal(true);
            });

            it('should work with inch', function(){
                expect(doesMQMatch('(max-height: 1000px)', {height: '20in'})).to.equal(false);
            });

            it('should work with pt', function(){
                expect(doesMQMatch('(max-height: 1000px)', {height: '850pt'})).to.equal(false);
            });

            it('should work with pc', function(){
                expect(doesMQMatch('(max-height: 1000px)', {height: '60pc'})).to.equal(true);
            });
        });

    });

    describe('Resolution Check', function(){

        it('should return true for a resolution match', function(){
            expect(doesMQMatch('(resolution: 50dpi)', {resolution: 50 })).to.equal(true);
        });

        it('should return true for a resolution higher than a min-resolution', function(){
            expect(doesMQMatch('(min-resolution: 50dpi)', {resolution: 72 })).to.equal(true);
        });

        it('should return false for a resolution higher than a max-resolution', function(){
            expect(doesMQMatch('(max-resolution: 72dpi)', {resolution: 300 })).to.equal(false);
        });

        it('should return false if resolution isnt passed in', function(){
            expect(doesMQMatch('(min-resolution: 72dpi)', {width: 300 })).to.equal(false);
        });

        it('should convert units properly', function(){
            expect(doesMQMatch('(min-resolution: 72dpi)', {resolution: '75dpcm' })).to.equal(false);
            expect(doesMQMatch('(resolution: 192dpi)', {resolution: '2dppx' })).to.equal(true);
        });
    });

    describe('Aspect Ratio Check', function(){

        it('should return true for an aspect-ratio higher than a min-aspect-ratio', function(){
            expect(doesMQMatch('(min-aspect-ratio: 4/3)', {'aspect-ratio': '16/9' })).to.equal(true);
        });

        it('should return false for an aspect-ratio higher than a max-aspect-ratio', function(){
            expect(doesMQMatch('(max-aspect-ratio: 4/3)', {'aspect-ratio': '16/9' })).to.equal(false);
        });

        it('should return false if aspect-ratio isnt passed in', function(){
            expect(doesMQMatch('(max-aspect-ratio: 72dpi)', {width: 300})).to.equal(false);
        });

        it('should work numbers', function(){
            expect(doesMQMatch('(min-aspect-ratio: 2560/1440)', {'aspect-ratio': 4/3 })).to.equal(false);
        });
    });

    describe('Grid/Color/Color-Index/Monochrome', function(){

        it('should return true for a correct match', function(){
            expect(doesMQMatch('(grid)', {grid: 1})).to.equal(true);
            expect(doesMQMatch('(color)', {color: 1})).to.equal(true);
            expect(doesMQMatch('(color-index: 3)', {'color-index': 3})).to.equal(true);
            expect(doesMQMatch('(monochrome)', {monochrome: 1})).to.equal(true);

        });

        it('should return false for an incorrect match', function(){
            expect(doesMQMatch('(grid)', {grid: 0})).to.equal(false);
            expect(doesMQMatch('(color)', {color: 0})).to.equal(false);
            expect(doesMQMatch('(color-index: 3)', {'color-index': 2})).to.equal(false);
            expect(doesMQMatch('(monochrome)', {monochrome: 0})).to.equal(false);
            expect(doesMQMatch('(monochrome)', {monochrome: 'foo'})).to.equal(false);
        });

    });

    describe('Type', function(){

        it('should return true for a correct match', function(){
            expect(doesMQMatch('screen', {type: 'screen'})).to.equal(true);
        });

        it('should return false for an incorrect match', function(){
            expect(doesMQMatch('screen and (color:1)', {type: 'tv', color: 1})).to.equal(false);
        });

        it('should return false for a media query without a type when type is specified in the value object', function(){
            expect(doesMQMatch('(min-width: 500px)', {type: 'screen'})).to.equal(false);
        });

        it('should return true for a media query without a type when type is not specified in the value object', function(){
            expect(doesMQMatch('(min-width: 500px)', {width: 700})).to.equal(true);
        });
    });

    describe('Not', function(){

        it('should return false when theres a match on a `not` query', function(){
            expect(doesMQMatch('not screen and (color)', {type: 'screen', color: 1})).to.equal(false);
        });

        it('should not disrupt an OR query', function(){
            expect(doesMQMatch('not screen and (color), screen and (min-height: 48em)', {type: 'screen', height: 1000})).to.equal(true);
        });

        it('should return false for when type === all', function(){
            expect(doesMQMatch('not all and (min-width: 48em)', {type: 'all', width: 1000})).to.equal(false);
        });

        it('should return true for inverted value', function(){
            expect(doesMQMatch('not screen and (min-width: 48em)', {width: '24em'})).to.equal(true);
        });
    });

    describe('#doesMQMatch() Integration Tests', function () {
        describe('Real World Use Cases (mostly AND)', function(){
            it('should return true because of width and type match', function(){
                expect(doesMQMatch('screen and (min-width: 767px)', {type: 'screen', width: 980})).to.equal(true);
            });

            it('should return true because of width is within bounds', function(){
                expect(doesMQMatch('screen and (min-width: 767px) and (max-width: 979px)', {type: 'screen', width: 800})).to.equal(true);
            });

            it('should return false because width is out of bounds', function(){
                expect(doesMQMatch('screen and (min-width: 767px) and (max-width: 979px)', {type: 'screen', width: 980})).to.equal(false);
            });

            it('should return false since monochrome is not specified', function(){
                expect(doesMQMatch('screen and (monochrome)', {width: 980})).to.equal(false);
            });

            it('should return true since color > 0', function(){
                expect(doesMQMatch('screen and (color)', {type: 'screen', color: 1})).to.equal(true);
            });

            it('should return false since color = 0', function(){
                expect(doesMQMatch('screen and (color)', {type: 'all', color: 0})).to.equal(false);
            });

        });

        describe('Grouped Media Queries (OR)', function(){
            it('should return true because of color', function(){
                expect(doesMQMatch('screen and (min-width: 767px), screen and (color)', {type: 'screen', color: 1})).to.equal(true);
            });

            it('should return true because of width and type', function(){
                expect(doesMQMatch('screen and (max-width: 1200px), handheld and (monochrome)', {type: 'screen', width: 1100})).to.equal(true);
            });

            it('should return false because of monochrome mis-match', function(){
                expect(doesMQMatch('screen and (max-width: 1200px), handheld and (monochrome)', {type: 'screen', monochrome: 0})).to.equal(false);
            });

        });
    });
});

<|endoftext|>