<commit_before>"use strict";

/*jslint white: true, todo: true */
/*global require: true, process: true, __dirname: true, console: true, JoelPurra: true */

var express = require('express'),
    cheerio = require("cheerio"),
    extend = require("extend"),
    callWithFirstInArray = require("../lib/callWithFirstInArray.js"),
    app = express(),
    JoelPurra = JoelPurra || {},
    port = process.env.PORT || 5000,
    // The database name has to be in the URI - refactor to use that instead of a separate variable
    mongoUri = process.env.MONGOLAB_URI || 'mongodb://localhost/claimid-dump',
    mongoDbName = "claimid-dump",
    dumpedDataVersion = 0,
    // TODO: break out lists of cache site to a module
    getClaimIdUrl = function(username) {
        // This function is modified client side code, and should be rewritten to more of a server side format.
        var claimIdBaseUrl = "http://claimid.com/",
            claimIdUrl = claimIdBaseUrl + username;

        return claimIdUrl;
    },
    getClaimIdCacheUrl = function(username) {
        // This function is modified client side code, and should be rewritten to more of a server side format.
        var googleCacheBaseUrl = "http://webcache.googleusercontent.com/search?q=cache:",

            encodeUrl = function(url) {
                return encodeURI(url);
            },

            claimIdUrl = getClaimIdUrl(username),

            url = googleCacheBaseUrl + encodeUrl(claimIdUrl);

        return url;
    },
    database = require("./data/data-layer-wrapper.js")({
        uri: mongoUri,
        databaseName: mongoDbName
    });

app.use(express.logger());

(function(namespace, pluginName) {
    // This function quite obviously is a modified client side plugin, and should be rewritten to more of a server side format.
    var $,

        dateFormatRx = /\d{4}-\d{2}-\d{2}/,

        internal = {
            extractLink: function() {
                var $this = $(this),
                    $link = $this.find(".taggedlink"),
                    who = $this.find(".info_link").text().split(" ")[0].split("|").map(function(str) {
                        return str.trim().split("\n")[0].trim();
                    }),
                    result = {
                        url: $link.attr("href"),
                        title: $link.text().trim(),
                        tags: $this.find("[rel~=tag]").map(function() {
                            return $(this).text();
                        }),
                        description: $this.find(".public_description").first().text(),
                        added: $this.find(".date_added").text().match(dateFormatRx)[0],
                        date: $this.find(".date").text(),
                        about: who[0],
                        by: who[1],
                        color: $this.find("a").first().find("img").attr("alt").replace("Star_", "")
                    };

                return result;
            },

            extractGroup: function() {
                var $this = $(this),
                    titleHtml = $this.find(".group_header").first().html(),
                    result = {
                        title: titleHtml.substring(0, titleHtml.indexOf("<")).trim(),
                        description: $this.find(".group_description .text").text(),
                        links: $this.find(".xfolkentry").map(internal.extractLink)
                    };

                return result;
            },

            getCachedDate: function() {
                try {
                    var div = $("div div").first();
                    var text = div.text();
                    var gmtSplit = text.split("GMT");
                    console.log("gmtSplit", gmtSplit)
                    var appearSplit = gmtSplit[0].trim().split("appeared on");
                    var dateTimeUtcValue = new Date(appearSplit[1].trim() + " GMT").valueOf();

                    return dateTimeUtcValue;
                } catch (e) {
                    console.error("Could not parse the cache date.")
                }

                return undefined;
            },

            getCachedUrl: function() {
                try {
                    var url = $("div div").first().find("a").first().attr("href");

                    return url;
                } catch (e) {
                    console.error("Could not parse the cache date.")
                }

                return undefined;
            },

            dump: function($context) {
                var groups = $(".display_group", $context),
                    result = {
                        cachedUrl: internal.getCachedUrl(),
                        cachedAt: internal.getCachedDate(),
                        groups: groups.length === 0 ? undefined : groups.map(internal.extractGroup)
                    };

                return result;
            }
        },

        plugin = {
            dump: function(cheerio, $context) {
                $ = cheerio;
                return internal.dump($context);
            }
        },

        init = function() {
            namespace[pluginName] = plugin;
        };

    init();

}(JoelPurra, "claimIdDump"));

app.get("/dump/", function(request, response, next) {
    function checkAndClean(str, disallowedRx, allowedRx) {
        if (disallowedRx.test(str) || !allowedRx.test(str)) {
            return null;
        }

        return str;
    }

    function checkAndCleanUsername(username) {
        var clean = checkAndClean(username, /[^a-z0-9\-]/i, /^[a-z0-9\-]{1,64}$/i);

        if (clean) {
            clean = clean.toLowerCase();
        }

        return clean;
    }

    function handleError(error) {
        throw error;
    }

    function sendForwardedHttpStatusCode(error, responseHttp) {
        if (typeof error === "number" && error >= 100 && error <= 999) {
            response.send(error);
            response.end();
        }
    }

    var username = checkAndCleanUsername(request.query.username),
        url = getClaimIdCacheUrl(username);

    if (!username) {
        response.send(422);
        response.end();
        return;
    }

    database.Users.getOrCreate(username)
        .fail(handleError)
        .done(function(user) {
            database.HttpCache.getLatestOneOrRequestAndCache(url, true)
                .fail(sendForwardedHttpStatusCode)
                .fail(handleError)
                .done(function(cachedRequest) {
                    database.Dumped.getLatestOne(user._id)
                        .fail(handleError)
                        .done(function(cachedDump) {
                            function getResult(user, cachedRequest, generatedAt, dumped) {
                                var meta = {
                                    username: user.username,
                                    generatedAt: generatedAt,
                                    cacheUrl: cachedRequest.url
                                },
                                    result = extend({}, meta, dumped);

                                return result;
                            }

                            function send(result) {
                                response.json(result);
                                response.end();
                            }

                            function handleCachedDump(fromCache) {
                                var result = fromCache.data;

                                send(result);
                            }

                            if (!cachedDump) {
                                if (!cachedRequest || !cachedRequest.response || !cachedRequest.response.statusCode || typeof cachedRequest.response.statusCode !== "number" || cachedRequest.response.statusCode !== 200) {
                                    sendForwardedHttpStatusCode(cachedRequest.response.statusCode, cachedRequest.response);
                                    return;
                                }

                                var $ = cheerio.load(cachedRequest.body),
                                    dumped = JoelPurra.claimIdDump.dump($),
                                    generatedAt = new Date().valueOf(),
                                    result = getResult(user, cachedRequest, generatedAt, dumped),
                                    toCache = {
                                        user_id: user._id,
                                        httpCache_id: cachedRequest._id,
                                        generatedAt: generatedAt,
                                        version: dumpedDataVersion,
                                        data: result
                                    };

                                database.Dumped.insert(toCache)
                                    .fail(handleError)
                                    .done(callWithFirstInArray(handleCachedDump));
                            } else {
                                handleCachedDump(cachedDump);
                            }
                        });
                });
        });
});

app.use(express.static(__dirname + '/../public'));

app.listen(port, function() {
    console.log("Listening on " + port);
});<commit_msg>Use path.resolve to get site root path<commit_after>"use strict";

/*jslint white: true, todo: true */
/*global require: true, process: true, __dirname: true, console: true, JoelPurra: true */

var express = require('express'),
    path = require("path"),
    cheerio = require("cheerio"),
    extend = require("extend"),
    callWithFirstInArray = require("../lib/callWithFirstInArray.js"),
    app = express(),
    JoelPurra = JoelPurra || {},
    port = process.env.PORT || 5000,
    // The database name has to be in the URI - refactor to use that instead of a separate variable
    mongoUri = process.env.MONGOLAB_URI || 'mongodb://localhost/claimid-dump',
    mongoDbName = "claimid-dump",
    dumpedDataVersion = 0,
    resolvePath = function() {
        var args = [].slice.call(arguments),
            parts = [__dirname].concat(args);

        return path.resolve.apply(path, parts);
    },
    // Path to static resources like index.html, css etcetera
    siteRootPath = resolvePath('..', 'public'),
    // TODO: break out lists of cache site to a module
    getClaimIdUrl = function(username) {
        // This function is modified client side code, and should be rewritten to more of a server side format.
        var claimIdBaseUrl = "http://claimid.com/",
            claimIdUrl = claimIdBaseUrl + username;

        return claimIdUrl;
    },
    getClaimIdCacheUrl = function(username) {
        // This function is modified client side code, and should be rewritten to more of a server side format.
        var googleCacheBaseUrl = "http://webcache.googleusercontent.com/search?q=cache:",

            encodeUrl = function(url) {
                return encodeURI(url);
            },

            claimIdUrl = getClaimIdUrl(username),

            url = googleCacheBaseUrl + encodeUrl(claimIdUrl);

        return url;
    },
    database = require("./data/data-layer-wrapper.js")({
        uri: mongoUri,
        databaseName: mongoDbName
    });

app.use(express.logger());

(function(namespace, pluginName) {
    // This function quite obviously is a modified client side plugin, and should be rewritten to more of a server side format.
    var $,

        dateFormatRx = /\d{4}-\d{2}-\d{2}/,

        internal = {
            extractLink: function() {
                var $this = $(this),
                    $link = $this.find(".taggedlink"),
                    who = $this.find(".info_link").text().split(" ")[0].split("|").map(function(str) {
                        return str.trim().split("\n")[0].trim();
                    }),
                    result = {
                        url: $link.attr("href"),
                        title: $link.text().trim(),
                        tags: $this.find("[rel~=tag]").map(function() {
                            return $(this).text();
                        }),
                        description: $this.find(".public_description").first().text(),
                        added: $this.find(".date_added").text().match(dateFormatRx)[0],
                        date: $this.find(".date").text(),
                        about: who[0],
                        by: who[1],
                        color: $this.find("a").first().find("img").attr("alt").replace("Star_", "")
                    };

                return result;
            },

            extractGroup: function() {
                var $this = $(this),
                    titleHtml = $this.find(".group_header").first().html(),
                    result = {
                        title: titleHtml.substring(0, titleHtml.indexOf("<")).trim(),
                        description: $this.find(".group_description .text").text(),
                        links: $this.find(".xfolkentry").map(internal.extractLink)
                    };

                return result;
            },

            getCachedDate: function() {
                try {
                    var div = $("div div").first();
                    var text = div.text();
                    var gmtSplit = text.split("GMT");
                    console.log("gmtSplit", gmtSplit)
                    var appearSplit = gmtSplit[0].trim().split("appeared on");
                    var dateTimeUtcValue = new Date(appearSplit[1].trim() + " GMT").valueOf();

                    return dateTimeUtcValue;
                } catch (e) {
                    console.error("Could not parse the cache date.")
                }

                return undefined;
            },

            getCachedUrl: function() {
                try {
                    var url = $("div div").first().find("a").first().attr("href");

                    return url;
                } catch (e) {
                    console.error("Could not parse the cache date.")
                }

                return undefined;
            },

            dump: function($context) {
                var groups = $(".display_group", $context),
                    result = {
                        cachedUrl: internal.getCachedUrl(),
                        cachedAt: internal.getCachedDate(),
                        groups: groups.length === 0 ? undefined : groups.map(internal.extractGroup)
                    };

                return result;
            }
        },

        plugin = {
            dump: function(cheerio, $context) {
                $ = cheerio;
                return internal.dump($context);
            }
        },

        init = function() {
            namespace[pluginName] = plugin;
        };

    init();

}(JoelPurra, "claimIdDump"));

app.get("/dump/", function(request, response, next) {
    function checkAndClean(str, disallowedRx, allowedRx) {
        if (disallowedRx.test(str) || !allowedRx.test(str)) {
            return null;
        }

        return str;
    }

    function checkAndCleanUsername(username) {
        var clean = checkAndClean(username, /[^a-z0-9\-]/i, /^[a-z0-9\-]{1,64}$/i);

        if (clean) {
            clean = clean.toLowerCase();
        }

        return clean;
    }

    function handleError(error) {
        throw error;
    }

    function sendForwardedHttpStatusCode(error, responseHttp) {
        if (typeof error === "number" && error >= 100 && error <= 999) {
            response.send(error);
            response.end();
        }
    }

    var username = checkAndCleanUsername(request.query.username),
        url = getClaimIdCacheUrl(username);

    if (!username) {
        response.send(422);
        response.end();
        return;
    }

    database.Users.getOrCreate(username)
        .fail(handleError)
        .done(function(user) {
            database.HttpCache.getLatestOneOrRequestAndCache(url, true)
                .fail(sendForwardedHttpStatusCode)
                .fail(handleError)
                .done(function(cachedRequest) {
                    database.Dumped.getLatestOne(user._id)
                        .fail(handleError)
                        .done(function(cachedDump) {
                            function getResult(user, cachedRequest, generatedAt, dumped) {
                                var meta = {
                                    username: user.username,
                                    generatedAt: generatedAt,
                                    cacheUrl: cachedRequest.url
                                },
                                    result = extend({}, meta, dumped);

                                return result;
                            }

                            function send(result) {
                                response.json(result);
                                response.end();
                            }

                            function handleCachedDump(fromCache) {
                                var result = fromCache.data;

                                send(result);
                            }

                            if (!cachedDump) {
                                if (!cachedRequest || !cachedRequest.response || !cachedRequest.response.statusCode || typeof cachedRequest.response.statusCode !== "number" || cachedRequest.response.statusCode !== 200) {
                                    sendForwardedHttpStatusCode(cachedRequest.response.statusCode, cachedRequest.response);
                                    return;
                                }

                                var $ = cheerio.load(cachedRequest.body),
                                    dumped = JoelPurra.claimIdDump.dump($),
                                    generatedAt = new Date().valueOf(),
                                    result = getResult(user, cachedRequest, generatedAt, dumped),
                                    toCache = {
                                        user_id: user._id,
                                        httpCache_id: cachedRequest._id,
                                        generatedAt: generatedAt,
                                        version: dumpedDataVersion,
                                        data: result
                                    };

                                database.Dumped.insert(toCache)
                                    .fail(handleError)
                                    .done(callWithFirstInArray(handleCachedDump));
                            } else {
                                handleCachedDump(cachedDump);
                            }
                        });
                });
        });
});

app.use(express.static(siteRootPath));

app.listen(port, function() {
    console.log("Listening on port", port);
    console.log("Serving site root from folder", siteRootPath);
});<|endoftext|>


<commit_before>import test                 from 'tape';
import Rx                   from 'rx'
import createRenderTarget   from './helper/createRenderTarget';
import {makeHistoryDriver}  from '@cycle/history';
import Navbar               from '../dialogue/navbar';
import Cycle                from '@cycle/core';
import {h,makeDOMDriver,mockDOMResponse} from '@cycle/dom';

test('Navbar tests', function(t) {
  t.plan(3);

  // mock the Main component and pass it the responses
  function mainComponent(responses) {
    let requests = Navbar(responses)
    return requests
  }

  // Pass Main through our RenderTarget
  let {sinks, sources} = Cycle.run(mainComponent, {
    DOM: makeDOMDriver(createRenderTarget()),
    url$: '/'
  });

  // Uncaught TypeError: drivers[_name2] is not a function

  sources.DOM.select('.myelementclass').events('click').subscribe(ev => {
    console.dir(ev.type)
    t.equal(ev.type, 'click');
  });
});
<commit_msg>trying again with click test<commit_after>import test                 from 'tape';
import Rx                   from 'rx'
import createRenderTarget   from './helper/createRenderTarget';
import {makeHistoryDriver}  from '@cycle/history';
import Navbar               from '../dialogue/navbar';
import Cycle                from '@cycle/core';
import {filterLinks} from '@cycle/history'
import {getUrl, extractValue, events} from '../utils/utils'
import {h,makeDOMDriver,mockDOMResponse} from '@cycle/dom';

test('Navbar tests', function(t) {
  t.plan(3);

  const intent = ({DOM}) => ({
    click$: events(
      DOM.select('.link'), [
        `click`,
        `touchstart`,
      ])
      .filter(filterLinks),
  })

  const model = ({click$}, {History}) => {
    return latestObj({
      url: click$
        .map(getUrl)
        .startWith(History.value.pathname),
    })
  }

  // mock the Main component and pass it the responses
  function mainComponent(responses) {
    let requests = Navbar(responses)
    return requests
  }

  const actions = intent(responses)
  const state$ = model(actions, responses)

  // Pass Main through our RenderTarget
  let {sinks, sources} = Cycle.run(mainComponent, {
    DOM: makeDOMDriver(createRenderTarget()),
    url$: extractValue(`url`, state$)
  });

  // Uncaught TypeError: drivers[_name2] is not a function

  sources.DOM.select('.myelementclass').events('click').subscribe(ev => {
    console.dir(ev.type)
    t.equal(ev.type, 'click');
  });
});
<|endoftext|>


<commit_before>var chalk = require('chalk');

var log = function log(value) {
  console.log(value);
};

log.green = function(value) {
  console.log(chalk.green(value));
};

log.blue = function(value) {
  console.log(chalk.blue(value));
};

log.red = function(value) {
  console.log(chalk.red(value));
};

log.yellow = function(value) {
  console.log(chalk.yellow(value));
};

log.magenta = function(value) {
  console.log(chalk.magenta(value));
};

log.cyan = function(value) {
  console.log(chalk.cyan(value));
};

log.white = function(value) {
  console.log(chalk.white(value));
};

log.gray = function(value) {
  console.log(chalk.gray(value));
};

module.exports = log;
<commit_msg>Add bower install command && Update README.MD<commit_after>var chalk = require('chalk');

var log = function log(value) {
   console.log(value);
};

log.green = function (value) {
   console.log(chalk.green(value));
};

log.blue = function (value) {
   console.log(chalk.blue(value));
};

log.red = function (value) {
   console.log(chalk.red(value));
};

log.yellow = function (value) {
   console.log(chalk.yellow(value));
};

log.magenta = function (value) {
   console.log(chalk.magenta(value));
};

log.cyan = function (value) {
   console.log(chalk.cyan(value));
};

log.white = function (value) {
   console.log(chalk.white(value));
};

log.gray = function (value) {
   console.log(chalk.gray(value));
};

module.exports = log;
<|endoftext|>


<commit_before>import express from 'express';

import f from '../util/format.js';
import db from '../util/database.js';

// middleware
import auth from '../middleware/auth.js';

const sensor = express.Router();

sensor.use(auth);

sensor.post('/unregister', (req, res) => {
    const body = req.body || null;
    if (body) {
        console.log(body);
        const {mac} = body;
        if (mac) {
            const query = db.format('DELETE FROM sensors WHERE mac = ?', [mac]);
            db.execute(query)
                .then((response) => {
                    console.log(response);
                    res.json(f.formatResponse(true));
                })
                .catch((error) => {
                    console.log(error);
                    res.json(f.formatResponse(false, 'Failed to remove sensor from database.'));
                });
        } else {
            res.json(f.formatResponse(false, 'Information not specified!'));
        }
    } else {
        res.json(f.formatResponse(false, 'Information not specified!'));
    }
});

sensor.post('/register', (req, res) => {
    const body = req.body || null;
    if (body) {
        console.log(body);
        const {userId, type, mac, name, active} = body;
        if (userId && type && mac && name && active !== undefined) {
            const query = db.format('INSERT INTO sensors(user_id, type, mac, name, active) VALUES(?, ?, ?, ?, ?)', [userId, type, mac, name, active]);
            db.execute(query)
                .then((response) => {
                    res.json(f.formatResponse(true, {sensorId: response.results.insertId}));
                })
                .catch((error) => {
                    if (error.errno === 1062) {
                        res.json(f.formatResponse(false, 'This sensor already exists in the database.'));
                    } else {
                        res.json(f.formatResponse(false));
                    }
                });
        } else {
            res.json(f.formatResponse(false, 'Information not specified!'));
        }
    } else {
        res.json(f.formatResponse(false, 'Information not specified!'));
    }
});

export default sensor;
<commit_msg>Changed the sensor route to succesfully execute on a duplicate key<commit_after>import express from 'express';

import f from '../util/format.js';
import db from '../util/database.js';

// middleware
import auth from '../middleware/auth.js';

const sensor = express.Router();

sensor.use(auth);

sensor.post('/unregister', (req, res) => {
    const body = req.body || null;
    if (body) {
        console.log(body);
        const {mac} = body;
        if (mac) {
            const query = db.format('DELETE FROM sensors WHERE mac = ?', [mac]);
            db.execute(query)
                .then((response) => {
                    console.log(response);
                    res.json(f.formatResponse(true));
                })
                .catch((error) => {
                    console.log(error);
                    res.json(f.formatResponse(false, 'Failed to remove sensor from database.'));
                });
        } else {
            res.json(f.formatResponse(false, 'Information not specified!'));
        }
    } else {
        res.json(f.formatResponse(false, 'Information not specified!'));
    }
});

sensor.post('/register', (req, res) => {
    const body = req.body || null;
    if (body) {
        console.log(body);
        const {userId, type, mac, name, active} = body;
        if (userId && type && mac && name && active !== undefined) {
            const query = db.format('INSERT INTO sensors(user_id, type, mac, name, active) VALUES(?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), type = VALUES(type), mac = VALUES(mac), name = VALUES(name), active = VALUES(active)', [userId, type, mac, name, active]);
            db.execute(query)
                .then((response) => {
                    console.log(response.results);
                    const idQuery = db.format('SELECT sensor_id FROM sensors WHERE mac = ?', [mac]);
                    return db.execute(idQuery);
                })
                .then((response) => {
                    res.json(f.formatResponse(true, {sensorId: response.results[0].sensor_id}));
                })
                .catch((error) => {
                    console.log(error);
                    if (error.errno === 1062) {
                        res.json(f.formatResponse(false, 'This sensor is already registered in the database.'));
                    } else {
                        res.json(f.formatResponse(false));
                    }
                });
        } else {
            res.json(f.formatResponse(false, 'Information not specified!'));
        }
    } else {
        res.json(f.formatResponse(false, 'Information not specified!'));
    }
});

export default sensor;
<|endoftext|>


<commit_before>'use strict'

var dgram = require('dgram')
var StunClient = require('../src/stun_client')
var transports = require('../src/transports')

var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
var expect = chai.expect
chai.use(chaiAsPromised)
chai.should()

var argv = require('yargs')
  .usage('Usage: $0 [params]')
  .demand('a')
  .default('a', 'stun.l.google.com')
  .alias('a', 'addr')
  .nargs('a', 1)
  .describe('a', 'STUN server address')
  .demand('p')
  .default('p', '19302')
  .alias('p', 'port')
  .nargs('p', 1)
  .describe('p', 'STUN server port')
  .default('l', 'debug')
  .choices('l', ['info', 'debug', 'warn', 'error', 'verbose', 'silly'])
  .alias('l', 'log')
  .nargs('l', 1)
  .describe('l', 'Log level')
  .help('h')
  .alias('h', 'help')
  .argv

var stunAddr = argv.addr
var stunPort = argv.port
var socketPort = 12345

describe('#STUN operations', function () {
  this.timeout(5000)

  it('should execute STUN bind operation over UDP socket using promises', function (done) {
    // create socket
    var socket = dgram.createSocket('udp4')
    socket.on('message', function (message, rinfo) { //
      done(new Error('message callback should not be fired'))
    })
    socket.on('error', function (error) {
      done(error)
    })
    socket.on('listening', function () {
      // create stun client and pass socket over
      var transport = new transports.UDP(socket)
      var client = new StunClient(stunAddr, stunPort, transport)
      client.bindP()
        .then(function (mappedAddress) {
          // verify the mapped address
          expect(mappedAddress).not.to.be.undefined
          expect(mappedAddress).to.have.property('address')
          expect(mappedAddress).to.have.property('port')
          client.close()
          // check the socket's event listeners (should not include any STUN client handler)
          expect(socket.listeners('message').length).to.equal(1)
          expect(socket.listeners('error').length).to.equal(1)
          done()
        })
    })
    socket.bind(socketPort)
  })

  it('should execute STUN bind operation over TCP socket using callbacks', function (done) {
    var transport = new transports.TCP()
    var client = new StunClient(stunAddr, stunPort, transport)
    // if something fails
    var onFailure = function (error) {
      done(error)
    }
    // check bind results
    var onBindSuccess = function (mappedAddress) {
      expect(mappedAddress).not.to.be.undefined
      expect(mappedAddress).to.have.property('address')
      expect(mappedAddress).to.have.property('port')
      // expect(mappedAddress.address).to.equal(testGW)
      client.close()
      done()
    }
    // execute bind operation
    client.bind(onBindSuccess, onFailure)
  })

  it('should execute STUN bind operation over unspecified UDP socket using promises', function () {
    // create stun client and pass socket over
    var client = new StunClient(stunAddr, stunPort)
    return client.bindP()
      .then(function (mappedAddress) {
        // verify the mapped address
        expect(mappedAddress).not.to.be.undefined
        expect(mappedAddress).to.have.property('address')
        expect(mappedAddress).to.have.property('port')
        client.close()
      })
  })
})
<commit_msg>removed redundant argv option<commit_after>'use strict'

var dgram = require('dgram')
var StunClient = require('../src/stun_client')
var transports = require('../src/transports')

var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
var expect = chai.expect
chai.use(chaiAsPromised)
chai.should()

var argv = require('yargs')
  .usage('Usage: $0 [params]')
  .demand('a')
  .default('a', 'stun.l.google.com')
  .alias('a', 'addr')
  .nargs('a', 1)
  .describe('a', 'STUN server address')
  .demand('p')
  .default('p', '19302')
  .alias('p', 'port')
  .nargs('p', 1)
  .describe('p', 'STUN server port')
  .help('h')
  .alias('h', 'help')
  .argv

var stunAddr = argv.addr
var stunPort = argv.port
var socketPort = 12345

describe('#STUN operations', function () {
  this.timeout(5000)

  it('should execute STUN bind operation over UDP socket using promises', function (done) {
    // create socket
    var socket = dgram.createSocket('udp4')
    socket.on('message', function (message, rinfo) { //
      done(new Error('message callback should not be fired'))
    })
    socket.on('error', function (error) {
      done(error)
    })
    socket.on('listening', function () {
      // create stun client and pass socket over
      var transport = new transports.UDP(socket)
      var client = new StunClient(stunAddr, stunPort, transport)
      client.bindP()
        .then(function (mappedAddress) {
          // verify the mapped address
          expect(mappedAddress).not.to.be.undefined
          expect(mappedAddress).to.have.property('address')
          expect(mappedAddress).to.have.property('port')
          client.close()
          // check the socket's event listeners (should not include any STUN client handler)
          expect(socket.listeners('message').length).to.equal(1)
          expect(socket.listeners('error').length).to.equal(1)
          done()
        })
    })
    socket.bind(socketPort)
  })

  it('should execute STUN bind operation over TCP socket using callbacks', function (done) {
    var transport = new transports.TCP()
    var client = new StunClient(stunAddr, stunPort, transport)
    // if something fails
    var onFailure = function (error) {
      done(error)
    }
    // check bind results
    var onBindSuccess = function (mappedAddress) {
      expect(mappedAddress).not.to.be.undefined
      expect(mappedAddress).to.have.property('address')
      expect(mappedAddress).to.have.property('port')
      // expect(mappedAddress.address).to.equal(testGW)
      client.close()
      done()
    }
    // execute bind operation
    client.bind(onBindSuccess, onFailure)
  })

  it('should execute STUN bind operation over unspecified UDP socket using promises', function () {
    // create stun client and pass socket over
    var client = new StunClient(stunAddr, stunPort)
    return client.bindP()
      .then(function (mappedAddress) {
        // verify the mapped address
        expect(mappedAddress).not.to.be.undefined
        expect(mappedAddress).to.have.property('address')
        expect(mappedAddress).to.have.property('port')
        client.close()
      })
  })
})
<|endoftext|>


<commit_before>var path = require('path'),
    mockFs = require('mock-fs'),
    TestNode = require('enb/lib/test/mocks/test-node'),
    levelsTech = require('../../techs/levels'),
    filesTech = require('../../techs/files');

describe('techs', function () {
    describe('files', function () {
        afterEach(function () {
            mockFs.restore();
        });

        it('must get block file by bemdecl', function (done) {
            mockFs({
                blocks: {
                    block: {
                        'block.ext': ''
                    }
                },
                bundle: {}
            });

            var bundle = new TestNode('bundle'),
                bemdecl = { blocks: [{ name: 'block' }] };

            bundle.runTech(levelsTech, { levels: ['blocks'] })
                .then(function (levels) {
                    bundle.provideTechData('?.levels', levels);
                    bundle.provideTechData('?.bemdecl.js', bemdecl);

                    return bundle.runTechAndGetResults(filesTech, {
                        depsFile: '?.bemdecl.js'
                    });
                })
                .then(function (result) {
                    var files = result['bundle.files'],
                        file = files.getByName('block.ext')[0];

                    file.name.must.be('block.ext');
                })
                .then(done, done);
        });

        it('must support deps as array', function (done) {
            mockFs({
                blocks: {
                    block: {
                        'block.ext': ''
                    }
                },
                bundle: {}
            });

            var bundle = new TestNode('bundle'),
                deps = [{ block: 'block' }];

            bundle.runTech(levelsTech, { levels: ['blocks'] })
                .then(function (levels) {
                    bundle.provideTechData('?.levels', levels);
                    bundle.provideTechData('?.deps.js', deps);

                    return bundle.runTechAndGetResults(filesTech);
                })
                .then(function (result) {
                    var files = result['bundle.files'],
                        file = files.getByName('block.ext')[0];

                    file.name.must.be('block.ext');
                })
                .then(done, done);
        });

        it('must get block file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            'block.ext': ''
                        }
                    }
                },
                deps = [{ block: 'block' }],
                files = ['blocks/block/block.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get boolean mod of block file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_bool-mod': {
                                'block_bool-mod.ext': ''
                            }
                        }
                    }
                },
                deps = [{ block: 'block', mod: 'bool-mod', val: true }],
                files = ['blocks/block/_bool-mod/block_bool-mod.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get block mod file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_mod-name': {
                                'block_mod-name_mod-val.ext': ''
                            }
                        }
                    }
                },
                deps = [{
                    block: 'block',
                    mod: 'mod-name',
                    val: 'mod-val'
                }],
                files = ['blocks/block/_mod-name/block_mod-name_mod-val.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get elem file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                'block__elem-name.ext': ''
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name' }],
                files = ['blocks/block/__elem-name/block__elem-name.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get boolean mod of elem file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_bool-mod': {
                                    'block__elem-name_bool-mod.ext': ''
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'bool-mod', val: true }],
                files = ['blocks/block/__elem-name/_bool-mod/block__elem-name_bool-mod.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get elem mod file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_mod-name': {
                                    'block__elem-name_mod-name_mod-val.ext': ''
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'mod-name', val: 'mod-val' }],
                files = ['blocks/block/__elem-name/_mod-name/block__elem-name_mod-name_mod-val.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get block dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            'block.ext': {}
                        }
                    }
                },
                deps = [{ block: 'block' }],
                files = ['blocks/block/block.ext'];

            hasDirs(scheme, deps, files, done);
        });

        it('must get boolean mod of block dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_bool-mod': {
                                'block_bool-mod.ext': {}
                            }
                        }
                    }
                },
                deps = [{ block: 'block', mod: 'bool-mod', val: true }],
                dirs = ['blocks/block/_bool-mod/block_bool-mod.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get block mod dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_mod-name': {
                                'block_mod-name_mod-val.ext': {}
                            }
                        }
                    }
                },
                deps = [{
                    block: 'block',
                    mod: 'mod-name',
                    val: 'mod-val'
                }],
                dirs = ['blocks/block/_mod-name/block_mod-name_mod-val.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get elem dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                'block__elem-name.ext': {}
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name' }],
                dirs = ['blocks/block/__elem-name/block__elem-name.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get boolean mod of elem dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_bool-mod': {
                                    'block__elem-name_bool-mod.ext': {}
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'bool-mod', val: true }],
                dirs = ['blocks/block/__elem-name/_bool-mod/block__elem-name_bool-mod.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get elem mod dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_mod-name': {
                                    'block__elem-name_mod-name_mod-val.ext': {}
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'mod-name', val: 'mod-val' }],
                dirs = ['blocks/block/__elem-name/_mod-name/block__elem-name_mod-name_mod-val.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get boolean mod & key-val mod by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_mod-name': {
                                'block_mod-name.ext': '',
                                'block_mod-name_mod-val.ext': ''
                            }
                        }
                    }
                },
                deps = [
                    { block: 'block', mod: 'mod-name' },
                    { block: 'block', mod: 'mod-name', val: 'mod-val' }
                ],
                files = [
                    'blocks/block/_mod-name/block_mod-name.ext',
                    'blocks/block/_mod-name/block_mod-name_mod-val.ext'
                ];

            hasFiles(scheme, deps, files, done);
        });

        it('must get files from levels', function (done) {
            var scheme = {
                    'level-1': {
                        block: {
                            'block.ext': ''
                        }
                    },
                    'level-2': {
                        block: {
                            'block.ext': ''
                        }
                    }
                },
                deps = [{ block: 'block' }],
                files = [
                    'level-1/block/block.ext',
                    'level-2/block/block.ext'
                ];

            hasFiles(scheme, deps, files, done);
        });
    });
});

function getEntityFiles(fsScheme, deps, filetype) {
    var levels = Object.keys(fsScheme);

    fsScheme['bundle'] = {};

    mockFs(fsScheme);

    var bundle = new TestNode('bundle');

    return bundle.runTech(levelsTech, { levels: levels })
        .then(function (levels) {
            bundle.provideTechData('?.levels', levels);
            bundle.provideTechData('?.deps.js', { deps: deps });

            return bundle.runTechAndGetResults(filesTech);
        })
        .then(function (result) {
            return result['bundle.' + filetype];
        });
}

function has(fsScheme, deps, filenames, filetype, done) {
    return getEntityFiles(fsScheme, deps, filetype)
        .then(function (files) {
            files.items.must.have.length(filenames.length);

            filenames.forEach(function (filename, i) {
                var fullname = path.resolve(filename);

                files.items[i].fullname.must.be(fullname);
            });
        })
        .then(done, done);
}

function hasFiles(fsScheme, deps, filenames, done) {
    has(fsScheme, deps, filenames, 'files', done);
}

function hasDirs(fsScheme, deps, filenames, done) {
    has(fsScheme, deps, filenames, 'dirs', done);
}
<commit_msg>Added test for case with order of entities<commit_after>var path = require('path'),
    mockFs = require('mock-fs'),
    TestNode = require('enb/lib/test/mocks/test-node'),
    levelsTech = require('../../techs/levels'),
    filesTech = require('../../techs/files');

describe('techs', function () {
    describe('files', function () {
        afterEach(function () {
            mockFs.restore();
        });

        it('must get block file by bemdecl', function (done) {
            mockFs({
                blocks: {
                    block: {
                        'block.ext': ''
                    }
                },
                bundle: {}
            });

            var bundle = new TestNode('bundle'),
                bemdecl = { blocks: [{ name: 'block' }] };

            bundle.runTech(levelsTech, { levels: ['blocks'] })
                .then(function (levels) {
                    bundle.provideTechData('?.levels', levels);
                    bundle.provideTechData('?.bemdecl.js', bemdecl);

                    return bundle.runTechAndGetResults(filesTech, {
                        depsFile: '?.bemdecl.js'
                    });
                })
                .then(function (result) {
                    var files = result['bundle.files'],
                        file = files.getByName('block.ext')[0];

                    file.name.must.be('block.ext');
                })
                .then(done, done);
        });

        it('must support deps as array', function (done) {
            mockFs({
                blocks: {
                    block: {
                        'block.ext': ''
                    }
                },
                bundle: {}
            });

            var bundle = new TestNode('bundle'),
                deps = [{ block: 'block' }];

            bundle.runTech(levelsTech, { levels: ['blocks'] })
                .then(function (levels) {
                    bundle.provideTechData('?.levels', levels);
                    bundle.provideTechData('?.deps.js', deps);

                    return bundle.runTechAndGetResults(filesTech);
                })
                .then(function (result) {
                    var files = result['bundle.files'],
                        file = files.getByName('block.ext')[0];

                    file.name.must.be('block.ext');
                })
                .then(done, done);
        });

        it('must keep order of entities', function (done) {
            mockFs({
                blocks: {
                    'block-1': {
                        'block-1.ext-1': '',
                        'block-1.ext-2': ''
                    },
                    'block-2': {
                        'block-2.ext-1': '',
                        'block-2.ext-2': ''
                    }
                },
                bundle: {}
            });

            var bundle = new TestNode('bundle'),
                deps = [
                    { block: 'block-1' },
                    { block: 'block-2' }
                ],
                files = [
                    'block-1.ext-1',
                    'block-1.ext-2',
                    'block-2.ext-1',
                    'block-2.ext-2'
                ];

            bundle.runTech(levelsTech, { levels: ['blocks'] })
                .then(function (levels) {
                    bundle.provideTechData('?.levels', levels);
                    bundle.provideTechData('?.deps.js', deps);

                    return bundle.runTechAndGetResults(filesTech);
                })
                .then(function (result) {
                    var FileList = result['bundle.files'],
                        filenames = FileList.getBySuffix(['ext-1', 'ext-2']).map(function (fileInfo) {
                            return fileInfo.name;
                        });

                    filenames.must.eql(files);
                })
                .then(done, done);
        });

        it('must get block file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            'block.ext': ''
                        }
                    }
                },
                deps = [{ block: 'block' }],
                files = ['blocks/block/block.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get boolean mod of block file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_bool-mod': {
                                'block_bool-mod.ext': ''
                            }
                        }
                    }
                },
                deps = [{ block: 'block', mod: 'bool-mod', val: true }],
                files = ['blocks/block/_bool-mod/block_bool-mod.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get block mod file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_mod-name': {
                                'block_mod-name_mod-val.ext': ''
                            }
                        }
                    }
                },
                deps = [{
                    block: 'block',
                    mod: 'mod-name',
                    val: 'mod-val'
                }],
                files = ['blocks/block/_mod-name/block_mod-name_mod-val.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get elem file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                'block__elem-name.ext': ''
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name' }],
                files = ['blocks/block/__elem-name/block__elem-name.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get boolean mod of elem file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_bool-mod': {
                                    'block__elem-name_bool-mod.ext': ''
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'bool-mod', val: true }],
                files = ['blocks/block/__elem-name/_bool-mod/block__elem-name_bool-mod.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get elem mod file by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_mod-name': {
                                    'block__elem-name_mod-name_mod-val.ext': ''
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'mod-name', val: 'mod-val' }],
                files = ['blocks/block/__elem-name/_mod-name/block__elem-name_mod-name_mod-val.ext'];

            hasFiles(scheme, deps, files, done);
        });

        it('must get block dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            'block.ext': {}
                        }
                    }
                },
                deps = [{ block: 'block' }],
                files = ['blocks/block/block.ext'];

            hasDirs(scheme, deps, files, done);
        });

        it('must get boolean mod of block dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_bool-mod': {
                                'block_bool-mod.ext': {}
                            }
                        }
                    }
                },
                deps = [{ block: 'block', mod: 'bool-mod', val: true }],
                dirs = ['blocks/block/_bool-mod/block_bool-mod.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get block mod dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_mod-name': {
                                'block_mod-name_mod-val.ext': {}
                            }
                        }
                    }
                },
                deps = [{
                    block: 'block',
                    mod: 'mod-name',
                    val: 'mod-val'
                }],
                dirs = ['blocks/block/_mod-name/block_mod-name_mod-val.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get elem dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                'block__elem-name.ext': {}
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name' }],
                dirs = ['blocks/block/__elem-name/block__elem-name.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get boolean mod of elem dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_bool-mod': {
                                    'block__elem-name_bool-mod.ext': {}
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'bool-mod', val: true }],
                dirs = ['blocks/block/__elem-name/_bool-mod/block__elem-name_bool-mod.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get elem mod dir by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '__elem-name': {
                                '_mod-name': {
                                    'block__elem-name_mod-name_mod-val.ext': {}
                                }
                            }
                        }
                    }
                },
                deps = [{ block: 'block', elem: 'elem-name', mod: 'mod-name', val: 'mod-val' }],
                dirs = ['blocks/block/__elem-name/_mod-name/block__elem-name_mod-name_mod-val.ext'];

            hasDirs(scheme, deps, dirs, done);
        });

        it('must get boolean mod & key-val mod by deps', function (done) {
            var scheme = {
                    blocks: {
                        block: {
                            '_mod-name': {
                                'block_mod-name.ext': '',
                                'block_mod-name_mod-val.ext': ''
                            }
                        }
                    }
                },
                deps = [
                    { block: 'block', mod: 'mod-name' },
                    { block: 'block', mod: 'mod-name', val: 'mod-val' }
                ],
                files = [
                    'blocks/block/_mod-name/block_mod-name.ext',
                    'blocks/block/_mod-name/block_mod-name_mod-val.ext'
                ];

            hasFiles(scheme, deps, files, done);
        });

        it('must get files from levels', function (done) {
            var scheme = {
                    'level-1': {
                        block: {
                            'block.ext': ''
                        }
                    },
                    'level-2': {
                        block: {
                            'block.ext': ''
                        }
                    }
                },
                deps = [{ block: 'block' }],
                files = [
                    'level-1/block/block.ext',
                    'level-2/block/block.ext'
                ];

            hasFiles(scheme, deps, files, done);
        });
    });
});

function getEntityFiles(fsScheme, deps, filetype) {
    var levels = Object.keys(fsScheme);

    fsScheme['bundle'] = {};

    mockFs(fsScheme);

    var bundle = new TestNode('bundle');

    return bundle.runTech(levelsTech, { levels: levels })
        .then(function (levels) {
            bundle.provideTechData('?.levels', levels);
            bundle.provideTechData('?.deps.js', { deps: deps });

            return bundle.runTechAndGetResults(filesTech);
        })
        .then(function (result) {
            return result['bundle.' + filetype];
        });
}

function has(fsScheme, deps, filenames, filetype, done) {
    return getEntityFiles(fsScheme, deps, filetype)
        .then(function (files) {
            files.items.must.have.length(filenames.length);

            filenames.forEach(function (filename, i) {
                var fullname = path.resolve(filename);

                files.items[i].fullname.must.be(fullname);
            });
        })
        .then(done, done);
}

function hasFiles(fsScheme, deps, filenames, done) {
    has(fsScheme, deps, filenames, 'files', done);
}

function hasDirs(fsScheme, deps, filenames, done) {
    has(fsScheme, deps, filenames, 'dirs', done);
}
<|endoftext|>


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

SAF.Dictionary = function () {
    'use strict';

    var store = {};
    var length = 0;

    /**
     *
     * @type {{none: number, ascending: number, descending: number}}
     */
    this.sortOptions = {
        none:  0,
        ascending: 1,
        descending: 2
    };

    /**
     *
     * @param key
     * @param value
     * @returns {SAF.Dictionary}
     */
    this.add = function (key, value) {
        if (typeof value !== 'undefined') {
            if (typeof (!store.hasOwnProperty(key))) {
                length++;
                store[key] = value;
            }
        }

        return this;
    };

    /**
     *
     * @param dictionary
     */
    this.merge = function (dictionary) {
        var keys = dictionary.keys(this.sortOptions.none);

        for (var i = 0; i < keys.length; i++) {
            var value = dictionary.find(keys[i]);
            this.add(keys[i], value);
        }
    };

    /**
     *
     * @param key
     * @returns {SAF.Dictionary}
     */
    this.remove = function (key) {
        if (typeof store.hasOwnProperty(key)) {
            length--;
            delete store[key];
        }

        return this;
    };

    /**
     *
     * @param key
     * @returns {*}
     */
    this.find = function (key) {
        return (store.hasOwnProperty(key)) ? store[key] : null;
    };

    /**
     *
     * @param key
     * @returns {boolean}
     */
    this.contains = function (key) {
        return store.hasOwnProperty(key);
    };

    /**
     *
     */
    this.clear = function () {
        for (var key in store) {
            if (store.hasOwnProperty(key)) {
                length--;
                delete store[key];
            }
        }
    };

    /**
     *
     * @returns {number}
     */
    this.count = function () {
        return length;
    };

    /**
     *
     * @param sortOption
     * @returns {Array}
     */
    this.keys = function (sortOption) {
        var array = [];

        for (var key in store) {
            if (store.hasOwnProperty(key)) {
                array.push(key);
            }
        }

        if (sortOption !== this.sortOptions.none) {
            array.sort();

            if (sortOption === this.sortOptions.descending) {
                array.reverse();
            }
        }

        return array;
    };

    /**
     *
     * @returns {*}
     */
    this.toString = function () {
        return JSON.stringify(store);
    };
};<commit_msg>Adding documentation<commit_after>var SAF = SAF || {};

SAF.Dictionary = function () {
    'use strict';

    var store = {};
    var length = 0;

    /**
     * Options for controlling the sort direction
     *
     * @type {{none: number, ascending: number, descending: number}}
     */
    this.sortOptions = {
        none:  0,
        ascending: 1,
        descending: 2
    };

    /**
     * Add an item to the collection
     *
     * @param key
     * @param value
     * @returns {SAF.Dictionary}
     */
    this.add = function (key, value) {
        if (typeof value !== 'undefined') {
            if (typeof (!store.hasOwnProperty(key))) {
                length++;
                store[key] = value;
            }
        }

        return this;
    };

    /**
     * Merge two dictionary objects
     *
     * @param dictionary
     */
    this.merge = function (dictionary) {
        var keys = dictionary.keys(this.sortOptions.none);

        for (var i = 0; i < keys.length; i++) {
            var value = dictionary.find(keys[i]);
            this.add(keys[i], value);
        }
    };

    /**
     * Remove an item from the collection based on its key
     *
     * @param key
     * @returns {SAF.Dictionary}
     */
    this.remove = function (key) {
        if (typeof store.hasOwnProperty(key)) {
            length--;
            delete store[key];
        }

        return this;
    };

    /**
     * Find an item in the collection based on its key
     *
     * @param key
     * @returns {*}
     */
    this.find = function (key) {
        return (store.hasOwnProperty(key)) ? store[key] : null;
    };

    /**
     * Determine whether the collection has the specified key
     *
     * @param key
     * @returns {boolean}
     */
    this.contains = function (key) {
        return store.hasOwnProperty(key);
    };

    /**
     * Clear all items form the collection
     */
    this.clear = function () {
        for (var key in store) {
            if (store.hasOwnProperty(key)) {
                length--;
                delete store[key];
            }
        }
    };

    /**
     * Returns he number of items in the collection
     *
     * @returns {number}
     */
    this.count = function () {
        return length;
    };

    /**
     * Returns a list of keys . . . sorted if specified
     *
     * @param sortOption
     * @returns {Array}
     */
    this.keys = function (sortOption) {
        var array = [];

        for (var key in store) {
            if (store.hasOwnProperty(key)) {
                array.push(key);
            }
        }

        if (sortOption !== this.sortOptions.none) {
            array.sort();

            if (sortOption === this.sortOptions.descending) {
                array.reverse();
            }
        }

        return array;
    };

    /**
     * Serializes the collection
     * @returns {*}
     */
    this.toString = function () {
        return JSON.stringify(store);
    };
};<|endoftext|>


<commit_before>var test = require("tape")

module.exports = testDomElement

function testDomElement(document) {

    var cleanup = require('./cleanup')(document)

    test("can getElementsByClassName", function(assert) {
        function append_div(classNames, parent) {
            var div = document.createElement("div")
            div.className = classNames
            parent.appendChild(div)
            return div
        }

        function assertMatch(classNames, expectedElements, parent) {
            var parent = parent || document
            var result = parent.getElementsByClassName(classNames)
            assert.equal(result.length, expectedElements.length)
            for (var i = 0; i < expectedElements.length; i++) {
                assert.notEqual(expectedElements.indexOf(result[i]), -1)
            }
        }

        var divA   = append_div("A", document.body)
        var divB   = append_div("B", document.body)
        var divC   = append_div("C", document.body)

        var divA1  = append_div("A1",  divA)
        var divA2  = append_div("A2",  divA)
        var divB1  = append_div("B1",  divB)
        var divB2  = append_div("B2",  divB)
        var divB2a = append_div("B2a", divB2)
        var divB2b = append_div("B2b", divB2)

        assertMatch("A",    [divA])
        assertMatch("B",    [divB])
        assertMatch("C",    [divC])
        assertMatch("A1",   [divA1])
        assertMatch("A2",   [divA2])
        assertMatch("B1",   [divB1])
        assertMatch("B2",   [divB2])
        assertMatch("B2a",  [divB2a])
        assertMatch("B2b",  [divB2b])

        assertMatch("A1",   [divA1], divA)
        assertMatch("A2",   [divA2], divA)
        assertMatch("A1",   [], divB)
        assertMatch("A2",   [], divC)
        assertMatch("B1",   [divB1], divB)
        assertMatch("B2",   [divB2], divB)
        assertMatch("B2a",  [divB2a], divB)
        assertMatch("B2a",  [divB2a], divB2)
        assertMatch("B2b",  [], divA)

        cleanup()
        assert.end()
    })

    test("does not serialize innerText as an attribute", function(assert) {
      var div = document.createElement("div")
      div.innerText = "Test <&>"
      assert.equal(div.toString(), "
Test <&>
")
      cleanup()
      assert.end()
    })

    test("does not serialize innerHTML as an attribute", function(assert) {
      var div = document.createElement("div")
      div.innerHTML = "Test "
      assert.equal(div.toString(), "
Test
")
      cleanup()
      assert.end()
    })

    test("can getElementsByTagName", function(assert) {
        var parent = document.createElement("div")
        var child1 = document.createElement("span")
        var child2 = document.createElement("span")

        child1.id = "foo"
        child2.id = "bar"

        child1.appendChild(child2)
        parent.appendChild(child1)

        var elems = parent.getElementsByTagName("SPAN")

        assert.equal(elems.length, 2)
        assert.equal(elems[0].id, "foo")
        assert.equal(elems[1].id, "bar")

        cleanup()
        assert.end()
    })

    test("can getElementsByTagName with *", function(assert) {
        var e1 = document.createElement("div")
        var e2 = document.createElement("p")
        var e3 = document.createElement("span")

        e1.appendChild(e2)
        e2.appendChild(e3)
        // non-elements should be ignored
        e3.appendChild(document.createTextNode('foo'))
        e3.appendChild(document.createComment('bar'))

        var elems = e1.getElementsByTagName("*")

        assert.equal(elems.length, 2)
        assert.equal(elems[0].tagName, "P")
        assert.equal(elems[1].tagName, "SPAN")

        cleanup()
        assert.end()
    })

    test("getElement* methods can be passed to map()", function(assert) {
        var container = document.createElement("div")
        var e1 = document.createElement("div")
        var e2 = document.createElement("span")
        container.appendChild(e1)
        container.appendChild(e2)

        assert.deepEqual(
            ["div", "span"].map(container.getElementsByTagName.bind(container)),
            [[e1], [e2]]
        )

        e1.className = "foo"
        e2.className = "bar"

        assert.deepEqual(
            ["foo", "bar"].map(container.getElementsByClassName.bind(container)),
            [[e1], [e2]]
        )

        cleanup()
        assert.end()
    })

    test("can serialize comment nodes", function(assert) {
        var div = document.createElement("div")
        div.appendChild(document.createComment("test"))
        assert.equal(div.toString(), "

")
        cleanup()
        assert.end()
    })

    test("can serialize style property", function(assert) {
        var div = document.createElement("div")
        div.style.fontSize = "16px"
        assert.equal(div.toString(), "

")
        cleanup();
        assert.end()
    })

    test("can serialize style as a string", function(assert) {
      var div = document.createElement("div")
      div.setAttribute('style', 'display: none')
      assert.equal(div.toString(), "

")
      cleanup()
      assert.end()
    })

    test("can serialize text nodes", function(assert) {
        var div = document.createElement("div")
        div.appendChild(document.createTextNode('<test> "&'))
        assert.equal(div.toString(), '
<test> "&
')
        cleanup()
        assert.end()
    })

    test("escapes serialized attribute values", function(assert) {
        var div = document.createElement("div")
        div.setAttribute("data-foo", '
"&')
        assert.equal(div.toString(), '

')
        cleanup()
        assert.end()
    })

    test("can check if an element contains another", function(assert) {
        var parent = document.createElement("div")
        var sibling = document.createElement("div")
        var child1 = document.createElement("div")
        var child2 = document.createElement("div")

        child1.appendChild(child2)
        parent.appendChild(child1)

        assert.equal(parent.contains(parent), true)
        assert.equal(parent.contains(sibling), false)
        assert.equal(parent.contains(child1), true)
        assert.equal(parent.contains(child2), true)

        cleanup()
        assert.end()
    })

    test("can handle non string attribute values", function(assert) {
        var div = document.createElement("div")
        div.setAttribute("data-number", 100)
        div.setAttribute("data-boolean", true)
        div.setAttribute("data-null", null)
        assert.equal(div.toString(), '

')
        cleanup()
        assert.end()
    })
}
<commit_msg>Add test for #43<commit_after>var test = require("tape")

module.exports = testDomElement

function testDomElement(document) {

    var cleanup = require('./cleanup')(document)

    test("can getElementsByClassName", function(assert) {
        function append_div(classNames, parent) {
            var div = document.createElement("div")
            div.className = classNames
            parent.appendChild(div)
            return div
        }

        function assertMatch(classNames, expectedElements, parent) {
            var parent = parent || document
            var result = parent.getElementsByClassName(classNames)
            assert.equal(result.length, expectedElements.length)
            for (var i = 0; i < expectedElements.length; i++) {
                assert.notEqual(expectedElements.indexOf(result[i]), -1)
            }
        }

        var divA   = append_div("A", document.body)
        var divB   = append_div("B", document.body)
        var divC   = append_div("C", document.body)

        var divA1  = append_div("A1",  divA)
        var divA2  = append_div("A2",  divA)
        var divB1  = append_div("B1",  divB)
        var divB2  = append_div("B2",  divB)
        var divB2a = append_div("B2a", divB2)
        var divB2b = append_div("B2b", divB2)

        assertMatch("A",    [divA])
        assertMatch("B",    [divB])
        assertMatch("C",    [divC])
        assertMatch("A1",   [divA1])
        assertMatch("A2",   [divA2])
        assertMatch("B1",   [divB1])
        assertMatch("B2",   [divB2])
        assertMatch("B2a",  [divB2a])
        assertMatch("B2b",  [divB2b])

        assertMatch("A1",   [divA1], divA)
        assertMatch("A2",   [divA2], divA)
        assertMatch("A1",   [], divB)
        assertMatch("A2",   [], divC)
        assertMatch("B1",   [divB1], divB)
        assertMatch("B2",   [divB2], divB)
        assertMatch("B2a",  [divB2a], divB)
        assertMatch("B2a",  [divB2a], divB2)
        assertMatch("B2b",  [], divA)

        cleanup()
        assert.end()
    })

    test("does not serialize innerText as an attribute", function(assert) {
      var div = document.createElement("div")
      div.innerText = "Test <&>"
      assert.equal(div.toString(), "
Test <&>
")
      cleanup()
      assert.end()
    })

    test("does not serialize innerHTML as an attribute", function(assert) {
      var div = document.createElement("div")
      div.innerHTML = "Test "
      assert.equal(div.toString(), "
Test
")
      cleanup()
      assert.end()
    })

    test("can getElementsByTagName", function(assert) {
        var parent = document.createElement("div")
        var child1 = document.createElement("span")
        var child2 = document.createElement("span")

        child1.id = "foo"
        child2.id = "bar"

        child1.appendChild(child2)
        parent.appendChild(child1)

        var elems = parent.getElementsByTagName("SPAN")

        assert.equal(elems.length, 2)
        assert.equal(elems[0].id, "foo")
        assert.equal(elems[1].id, "bar")

        cleanup()
        assert.end()
    })

    test("can getElementsByTagName with *", function(assert) {
        var e1 = document.createElement("div")
        var e2 = document.createElement("p")
        var e3 = document.createElement("span")

        e1.appendChild(e2)
        e2.appendChild(e3)
        // non-elements should be ignored
        e3.appendChild(document.createTextNode('foo'))
        e3.appendChild(document.createComment('bar'))

        var elems = e1.getElementsByTagName("*")

        assert.equal(elems.length, 2)
        assert.equal(elems[0].tagName, "P")
        assert.equal(elems[1].tagName, "SPAN")

        cleanup()
        assert.end()
    })

    test("getElement* methods can be passed to map()", function(assert) {
        var container = document.createElement("div")
        var e1 = document.createElement("div")
        var e2 = document.createElement("span")
        container.appendChild(e1)
        container.appendChild(e2)

        assert.deepEqual(
            ["div", "span"].map(container.getElementsByTagName.bind(container)),
            [[e1], [e2]]
        )

        e1.className = "foo"
        e2.className = "bar"

        assert.deepEqual(
            ["foo", "bar"].map(container.getElementsByClassName.bind(container)),
            [[e1], [e2]]
        )

        cleanup()
        assert.end()
    })

    test("can serialize comment nodes", function(assert) {
        var div = document.createElement("div")
        div.appendChild(document.createComment("test"))
        assert.equal(div.toString(), "

")
        cleanup()
        assert.end()
    })

    test("can serialize style property", function(assert) {
        var div = document.createElement("div")
        div.style.fontSize = "16px"
        assert.equal(div.toString(), "

")
        cleanup();
        assert.end()
    })

    test("can serialize style as a string", function(assert) {
      var div = document.createElement("div")
      div.setAttribute('style', 'display: none')
      assert.equal(div.toString(), "

")
      cleanup()
      assert.end()
    })

    test("can serialize text nodes", function(assert) {
        var div = document.createElement("div")
        div.appendChild(document.createTextNode('<test> "&'))
        assert.equal(div.toString(), '
<test> "&
')
        cleanup()
        assert.end()
    })

    test("escapes serialized attribute values", function(assert) {
        var div = document.createElement("div")
        div.setAttribute("data-foo", '
"&')
        assert.equal(div.toString(), '

')
        cleanup()
        assert.end()
    })

    test("can check if an element contains another", function(assert) {
        var parent = document.createElement("div")
        var sibling = document.createElement("div")
        var child1 = document.createElement("div")
        var child2 = document.createElement("div")

        child1.appendChild(child2)
        parent.appendChild(child1)

        assert.equal(parent.contains(parent), true)
        assert.equal(parent.contains(sibling), false)
        assert.equal(parent.contains(child1), true)
        assert.equal(parent.contains(child2), true)

        cleanup()
        assert.end()
    })

    test("can handle non string attribute values", function(assert) {
        var div = document.createElement("div")
        div.setAttribute("data-number", 100)
        div.setAttribute("data-boolean", true)
        div.setAttribute("data-null", null)
        assert.equal(div.toString(), '

')
        cleanup()
        assert.end()
    })

    test("can serialize textarea correctly", function(assert) {
        var input = document.createElement("textarea")
        input.setAttribute("name", "comment")
        input.innerHTML = "user input here"
        assert.equal(input.toString(), '<textarea name="comment">user input here</textarea>')
        cleanup()
        assert.end()
    })
}
<|endoftext|>


<commit_before>var fs = require('fs');

var units = require('./units.json');
var ai = require('./ai.js');
var abbrevs = require('./abbrevs.js');

function isUnit(unit) {
    return (units[unit].supply > 0);
}

function defaultExpansion() {
    with (ai) {
        start_town();
        build_finish(1, town_hall);

        for (var i = 1; i <= 8; i += 1) {
            build_finish(i, peon);
        }

        build_start(1, gas);

        for (var i = 1; i <= 20; i += 1) {
            build_finish(i, peon);
        }

        stop();
    }
}

var parseArray = function parseArray(lines) {
    var owned = {};
    var supplyFromUnits = 0;

    lines.forEach(function (line) {
        var supply = line[0];
        var unit = line[1];
        var ret = "";

        if(!owned[unit]) {
            owned[unit] = 0;
        }
        owned[unit] += 1;

        var waitForWorker = supply - supplyFromUnits;

        ai.build_start(waitForWorker, ai.peon);

        if (isUnit(unit)) {
            supplyFromUnits += parseInt(units[unit].supply);

            ai.train(owned[unit], unit);
        } else if (unit == 'Terran Command Center' || unit == 'Zerg Hatchery' || unit == 'Protoss Nexus') {
            ai.expand(1, defaultExpansion);
        } else {
            ai.build_start(owned[unit], unit);
        }
    });
};

exports.parseArray = parseArray;

var parseFromFile = function (filename) {
    var builds = {};

    fs.readFileSync(filename, 'utf-8').split('#').forEach(function(buildText) {
        var lines = buildText.split('\n');

        // Clean up white space
        lines.forEach(function (line, i) {
            lines[i] = lines[i].replace(/^ +/, '');
            lines[i] = lines[i].replace(/ +$/, '');
            lines[i] = lines[i].replace(/  +$/, ' ');
        });

        var name = lines.splice(0,1)[0];

        lines = lines.filter(function (line) {
            return parseInt(line) > 0;
        });

        var buildArray = [];

        lines.forEach(function (line) {
            var supply = parseInt(line);
            var unit = abbrevs.expand(line.replace(supply, ''));

            buildArray.push([supply, unit]);
        });

        builds[name] = function() {
            parseArray(buildArray);
        };
    });

    return builds;
}

exports.parseFromFile = parseFromFile;<commit_msg>added parser for race options<commit_after>var fs = require('fs');

var units = require('./units.json');
var ai = require('./ai.js');
var abbrevs = require('./abbrevs.js');

function isUnit(unit) {
    return (units[unit].supply > 0);
}

function defaultExpansion() {
    with (ai) {
        start_town();
        build_finish(1, town_hall);

        for (var i = 1; i <= 8; i += 1) {
            build_finish(i, peon);
        }

        build_start(1, gas);

        for (var i = 1; i <= 20; i += 1) {
            build_finish(i, peon);
        }

        stop();
    }
}

var parseArray = function parseArray(lines) {
    var owned = {};
    var supplyFromUnits = 0;

    lines.forEach(function (line) {
        var supply = line[0];
        var unit = line[1];
        var ret = "";

        if(!owned[unit]) {
            owned[unit] = 0;
        }
        owned[unit] += 1;

        var waitForWorker = supply - supplyFromUnits;

        ai.build_start(waitForWorker, ai.peon);

        if (isUnit(unit)) {
            supplyFromUnits += parseInt(units[unit].supply);

            ai.train(owned[unit], unit);
        } else if (unit == 'Terran Command Center' || unit == 'Zerg Hatchery' || unit == 'Protoss Nexus') {
            ai.expand(1, defaultExpansion);
        } else {
            ai.build_start(owned[unit], unit);
        }
    });
};

exports.parseArray = parseArray;

var parseFromFile = function (filename) {
    var builds = {};

    fs.readFileSync(filename, 'utf-8').split('\n#').forEach(function(buildText) {
        var options = {};
        var lines = buildText.split('\n');

        // Clean up white space
        lines.forEach(function (line, i) {
            lines[i] = lines[i].replace(/^ +/, '');
            lines[i] = lines[i].replace(/ +$/, '');
            lines[i] = lines[i].replace(/  +$/, ' ');
        });

        var name = lines.splice(0,1)[0];
        var matchups

        if(!name.match(/\(.*\)/)) {
            matchups = 'vT, vZ, vP'
        } else {
            matchups = name.replace(/.*\((.*)\)/, '$1');
        }

        options.versus = {
            terran: !!matchups.match(/vt/i),
            zerg: !!matchups.match(/vz/i),
            protoss: !!matchups.match(/vp/i)
        };

        lines = lines.filter(function (line) {
            return parseInt(line) > 0;
        });

        var buildArray = [];

        lines.forEach(function (line) {
            var supply = parseInt(line);
            var unit = abbrevs.expand(line.replace(supply, ''));

            buildArray.push([supply, unit]);
        });

        builds[name] = function() {
            parseArray(buildArray);
        };
    });

    return builds;
}

exports.parseFromFile = parseFromFile;<|endoftext|>


<commit_before>/*jshint browser:true */
/*global require, define, QUnit, test, asyncTest, ok, strictEqual, deepEqual, start, stop, throws, jasmine */
define(["helpers", "jasq"], function (helpers, jasq) {
  "use strict";

  var
    isFunction = helpers.isFunction,
    each = helpers.each,

    globalMethodNames = ["describe", "xdescribe", "it", "xit"],

    whenJasmineLoaded = function (onJasmineLoaded) {
      if (window.jasmine) { return onJasmineLoaded(); }
      require(["vendor/jasmine/jasmine.js"], function () { onJasmineLoaded(); });
    };

  ////////////////////////////////////
  ////////////////////////////////////

  // How jasq behaves when Jasmine not loaded
  QUnit.module("Environment (Jasmine not loaded)");

  test("jasmine globals (" + globalMethodNames.join(", ") + ") are not available", 4, function () {
    if (window.jasmine) { throw "This test requires that Jasmine hasn't loaded"; }

    each(globalMethodNames, function (methodName) {
      ok(!window[methodName], "'" + methodName + "' is not globally available");
    });
  });

  test("no jasmine globals (" + globalMethodNames.join(", ") + ") are exposed on jasq", 4, function () {
    if (window.jasmine) { throw "This test requires that Jasmine hasn't loaded"; }

    each(globalMethodNames, function (methodName) {
      ok(!jasq[methodName], "'" + methodName + "' is not exposed on jasq");
    });
  });

  test("attempting to apply/reset globals throws", 2, function () {
    if (window.jasmine) { throw "This test requires that Jasmine hasn't loaded"; }

    throws(function () { jasq.applyGlobals(); }, "attempting to apply globals throws");
    throws(function () { jasq.resetGlobals(); }, "attempting to reset globals throws");
  });

  ////////////////////////////////////
  ////////////////////////////////////

  // How jasq and its globals should be exported when loaded after Jasmine
  QUnit.module("Environment (Jasmine loaded)");

  asyncTest("applying will expose the jasq-version of Jasmine globals (globally and on jasq)", 12, function () {
    whenJasmineLoaded(function () {
      jasq.applyGlobals();

      each(globalMethodNames, function (methodName) {
        ok(isFunction(window[methodName]), "'" + methodName + "' is globally available ..");
        strictEqual(window[methodName].isJasq, true, ".. is jasq-version ..");
        strictEqual(jasq[methodName], window[methodName], ".. and is also exposed on jasq");
      });

      start();
    });
  });

  asyncTest("globals may be reset and re-applied", 16, function () {
      whenJasmineLoaded(function () {
        jasq.applyGlobals();

        jasq.resetGlobals();

        each(globalMethodNames, function (methodName) {
          ok(isFunction(window[methodName]), "after reset, '" + methodName + "' is globally available ..");
          ok(!window[methodName].isJasq, ".. and is not jasq-version");
        });

        jasq.applyGlobals();

        each(globalMethodNames, function (methodName) {
          ok(isFunction(window[methodName]), "after patch, '" + methodName + "' is globally available ..");
          strictEqual(window[methodName].isJasq, true, ".. and is jasq-version");
        });

        start();
      });
  });

});
<commit_msg>Fix late-jasmine tests<commit_after>/*jshint browser:true */
/*global require, define, QUnit, test, asyncTest, ok, strictEqual, deepEqual, start, throws, jasmineRequire */
define(["helpers", "jasq"], function (helpers, jasq) {
  "use strict";

  var
    isFunction = helpers.isFunction,
    each = helpers.each,

    globalMethodNames = ["describe", "xdescribe", "it", "xit"],

    whenJasmineLoaded = function (onJasmineLoaded) {
      if (window.jasmine) {
        return onJasmineLoaded();
      }

      require(["vendor/jasmine/2.0.2/jasmine.js"], function () {
        window.jasmine = jasmineRequire.core(jasmineRequire);
        var env = window.jasmine.getEnv();
        var jasmineInterface = jasmineRequire.interface(window.jasmine, env);
        for (var prop in jasmineInterface) {
          if (jasmineInterface.hasOwnProperty(prop)) {
            window[prop] = jasmineInterface[prop];
          }
        }

        onJasmineLoaded();
      });
    };

  ////////////////////////////////////
  ////////////////////////////////////

  // How jasq behaves when Jasmine not loaded
  QUnit.module("Environment (Jasmine not loaded)");

  test("jasmine globals (" + globalMethodNames.join(", ") + ") are not available", 4, function () {
    if (window.jasmine) { throw "This test requires that Jasmine hasn't loaded"; }

    each(globalMethodNames, function (methodName) {
      ok(!window[methodName], "'" + methodName + "' is not globally available");
    });
  });

  test("no jasmine globals (" + globalMethodNames.join(", ") + ") are exposed on jasq", 4, function () {
    if (window.jasmine) { throw "This test requires that Jasmine hasn't loaded"; }

    each(globalMethodNames, function (methodName) {
      ok(!jasq[methodName], "'" + methodName + "' is not exposed on jasq");
    });
  });

  test("attempting to apply/reset globals throws", 2, function () {
    if (window.jasmine) { throw "This test requires that Jasmine hasn't loaded"; }

    throws(function () { jasq.applyGlobals(); }, "attempting to apply globals throws");
    throws(function () { jasq.resetGlobals(); }, "attempting to reset globals throws");
  });

  ////////////////////////////////////
  ////////////////////////////////////

  // How jasq and its globals should be exported when loaded after Jasmine
  QUnit.module("Environment (Jasmine loaded)");

  asyncTest("applying will expose the jasq-version of Jasmine globals (globally and on jasq)", 12, function () {
    whenJasmineLoaded(function () {
      jasq.applyGlobals();

      each(globalMethodNames, function (methodName) {
        ok(isFunction(window[methodName]), "'" + methodName + "' is globally available ..");
        strictEqual(window[methodName].isJasq, true, ".. is jasq-version ..");
        strictEqual(jasq[methodName], window[methodName], ".. and is also exposed on jasq");
      });

      start();
    });
  });

  asyncTest("globals may be reset and re-applied", 16, function () {
      whenJasmineLoaded(function () {
        jasq.applyGlobals();

        jasq.resetGlobals();

        each(globalMethodNames, function (methodName) {
          ok(isFunction(window[methodName]), "after reset, '" + methodName + "' is globally available ..");
          ok(!window[methodName].isJasq, ".. and is not jasq-version");
        });

        jasq.applyGlobals();

        each(globalMethodNames, function (methodName) {
          ok(isFunction(window[methodName]), "after patch, '" + methodName + "' is globally available ..");
          strictEqual(window[methodName].isJasq, true, ".. and is jasq-version");
        });

        start();
      });
  });

});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';

// classnames
import classNames from 'classnames';

// Images
import SlackIcon from './SlackIcon';
import './SlackFeedback.scss';

const propTypes = {
  channel: PropTypes.string.isRequired,
  onSubmit: PropTypes.func.isRequired,
  sending: PropTypes.bool,
  user: PropTypes.string,
  emoji: PropTypes.string,
  buttonText: PropTypes.string
};

const defaultProps = {
  sending: false,
  user: 'Unknown User',
  emoji: ':speaking_head_in_silhouette:',
  buttonText: 'Slack Feedback'
};

const types = [
  { value: 'bug', label: 'Bug' },
  { value: 'improvement', label: 'Improvement' },
  { value: 'feature', label: 'Feature Request' }
];

class SlackFeedback extends Component {
  constructor(props) {
    super(props);

    this.state = {
      active: false,
      sendURL: true,
      sent: false,
      error: false,
      selectedType: 'Bug'
    };
  }

  toggle() {
    if (this.state.active) {
      this.close();
    } else {
      this.activate();
    }
  }

  activate() {
    this.setState({
      active: !this.state.active
    });

    document.addEventListener('click', this.handleClickOutside.bind(this));
  }

  handleClickOutside(e) {
    if (!this.refs.SlackFeedback.contains(e.target)) {
      this.close();
    }
  }

  close() {
    this.setState({
      active: false
    });

    document.removeEventListener('click', this.handleClickOutside.bind(this));
  }

  toggleSendURL() {
    this.setState({ sendURL: !this.state.sendURL });
  }

  selectType(e) {
    this.setState({ selectedType: e.target.innerText });
  }

  error(err) {
    console.warn(err);

    this.setState({
      sending: false,
      error: true
    }, () => {
      setTimeout(() => {
        this.setState({ error: false })
      }, 5 * 1000);
    });
  }

  sent() {
    this.setState({
      sending: false,
      sent: true
    }, () => {
      setTimeout(() => {
        this.setState({ sent: false })
      }, 5 * 1000);
    });
  }

  send() {
    var { selectedType, sendURL } = this.state;

    var message = this.refs.message.value;
    var level;

    this.setState({ sending: true });

    if (sendURL) message += `\n <${document.location.href}>`;

    switch (selectedType) {
      case 'Bug':
        level = 'danger';
        break;
      case 'Feature':
        level = 'good';
        break;
      case 'Improvement':
        level = 'warning';
        break;
    }

    var body = {
      channel: this.props.channel,
      username: this.props.user,
      icon_emoji: this.props.emoji,
      attachments: [
        {
          fallback: `Feedback (${selectedType})`,
          color: level,
          title: selectedType,
          title_link: document.location.href,
          text: message,
          footer: 'React Slack Feedback',
          // ts: new Date().getTime()
        }
      ]
    };

    this.props.onSubmit.call(this, body);
  }

  render() {
    var {
      active,
      sending,
      sent,
      error,
      sendURL,
      selectedType
    } = this.state;

    var submitText = 'Send Feedback';

    if (sent) submitText = 'Sent!';
    if (sending && !sent) submitText = 'Sending Feedback...';
    if (error) submitText = 'Error!';

    return (

            <SlackIcon /> Send Feedback to Slack

close

            Channel
            <input class="SlackFeedback--input" value={this.props.channel} disabled />

            Feedback Type

Bug

Feature

Improvement

            Your Message
            <textarea ref="message" class="SlackFeedback--textarea" placeholder="Message..." />

              <input id="sendURL" class="SlackFeedback--checkbox" type="checkbox" checked={sendURL} onChange={::this.toggleSendURL} />
              Send URL with Feedback

            <button
              class={classNames('submit', { sent, error, disabled: sending })}
              onClick={::this.send}>
              {submitText}
            </button>

          <SlackIcon /> {this.props.buttonText}

    );
  }
}

SlackFeedback.propTypes = propTypes;
SlackFeedback.defaultProps = defaultProps;

export default SlackFeedback;
<commit_msg>disableImageUpload<commit_after>import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';

// classnames
import classNames from 'classnames';

// Images
import SlackIcon from './SlackIcon';
import './SlackFeedback.scss';

const propTypes = {
  channel: PropTypes.string.isRequired,
  onSubmit: PropTypes.func.isRequired,
  sending: PropTypes.bool,
  user: PropTypes.string,
  emoji: PropTypes.string,
  buttonText: PropTypes.string,
  disableImageUpload: PropTypes.bool
};

const defaultProps = {
  sending: false,
  user: 'Unknown User',
  emoji: ':speaking_head_in_silhouette:',
  buttonText: 'Slack Feedback',
  disableImageUpload: false
};

const types = [
  { value: 'bug', label: 'Bug' },
  { value: 'improvement', label: 'Improvement' },
  { value: 'feature', label: 'Feature Request' }
];

class SlackFeedback extends Component {
  constructor(props) {
    super(props);

    this.state = {
      active: false,
      sendURL: true,
      sent: false,
      error: false,
      selectedType: 'Bug'
    };
  }

  toggle() {
    if (this.state.active) {
      this.close();
    } else {
      this.activate();
    }
  }

  activate() {
    this.setState({
      active: !this.state.active
    });

    document.addEventListener('click', this.handleClickOutside.bind(this));
  }

  handleClickOutside(e) {
    if (!this.refs.SlackFeedback.contains(e.target)) {
      this.close();
    }
  }

  close() {
    this.setState({
      active: false
    });

    document.removeEventListener('click', this.handleClickOutside.bind(this));
  }

  toggleSendURL() {
    this.setState({ sendURL: !this.state.sendURL });
  }

  selectType(e) {
    this.setState({ selectedType: e.target.innerText });
  }

  error(err) {
    console.warn(err);

    this.setState({
      sending: false,
      error: true
    }, () => {
      setTimeout(() => {
        this.setState({ error: false })
      }, 5 * 1000);
    });
  }

  sent() {
    this.setState({
      sending: false,
      sent: true
    }, () => {
      setTimeout(() => {
        this.setState({ sent: false })
      }, 5 * 1000);
    });
  }

  send() {
    var { selectedType, sendURL } = this.state;

    var message = this.refs.message.value;
    var level;

    this.setState({ sending: true });

    if (sendURL) message += `\n <${document.location.href}>`;

    switch (selectedType) {
      case 'Bug':
        level = 'danger';
        break;
      case 'Feature':
        level = 'good';
        break;
      case 'Improvement':
        level = 'warning';
        break;
    }

    var body = {
      channel: this.props.channel,
      username: this.props.user,
      icon_emoji: this.props.emoji,
      attachments: [
        {
          fallback: `Feedback (${selectedType})`,
          color: level,
          title: selectedType,
          title_link: document.location.href,
          text: message,
          footer: 'React Slack Feedback',
          // ts: new Date().getTime()
        }
      ]
    };

    this.props.onSubmit.call(this, body);
  }

  render() {
    var {
      active,
      sending,
      sent,
      error,
      sendURL,
      selectedType
    } = this.state;

    var submitText = 'Send Feedback';

    if (sent) submitText = 'Sent!';
    if (sending && !sent) submitText = 'Sending Feedback...';
    if (error) submitText = 'Error!';

    return (

            <SlackIcon /> Send Feedback to Slack

close

            Channel
            <input class="SlackFeedback--input" value={this.props.channel} disabled />

            Feedback Type

Bug

Feature

Improvement

            Your Message
            <textarea ref="message" class="SlackFeedback--textarea" placeholder="Message..." />

              <input id="sendURL" class="SlackFeedback--checkbox" type="checkbox" checked={sendURL} onChange={::this.toggleSendURL} />
              Send URL with Feedback

            <button
              class={classNames('submit', { sent, error, disabled: sending })}
              onClick={::this.send}>
              {submitText}
            </button>

          <SlackIcon /> {this.props.buttonText}

    );
  }
}

SlackFeedback.propTypes = propTypes;
SlackFeedback.defaultProps = defaultProps;

export default SlackFeedback;
<|endoftext|>