<commit_before>/** @ignore */
const Command = require('./../Command');

class StatsCommand extends Command {
    constructor() {
        super('!', 'stats', [], {
            middleware: [
                'throttle.channel:1,5'
            ]
        });
    }

    onCommand(sender, message, args) {
        let members  = this.getMemberStats();
        let channels = this.getChannelStats();
        let author = bot.Users.find(user => { return user.id === '88739639380172800' });
        let description = 'Created by Senither#8023 using the Discordie framework!';

        if (app.cache.has('github.commits')) {
            description = '**Latest changes:**\n';

            app.cache.get('github.commits').slice(0, 3).forEach(commit => {
                description += `[\`${commit.sha.substr(0, 7)}\`](${commit.html_url}) ${commit.commit.message}\n`;
            });
        }

        message.channel.sendMessage('', false, {
            timestamp: new Date,
            color: 0x3498db,
            url: 'https://discordapp.com/invite/gt2FWER',
            title: 'Official Bot Server Invite',
            description: description.trim(),
            author: {
                icon_url: `https://cdn.discordapp.com/avatars/${author.id}/${author.avatar}.png?size=256`,
                name: `${author.username}#${author.discriminator}`
            },
            fields: [
                {
                    name: 'Members',
                    value: [
                        members.totalMembers + ' Total',
                        members.totalOnline + ' Online',
                        members.uniqueMembers + ' Unique',
                        members.uniqueOnline + ' Unique online',
                    ].join('\n'),
                    inline: true
                },
                {
                    name: 'Channels',
                    value: [
                        channels.totalChannels + ' Total',
                        channels.textChannels + ' Text',
                        channels.voiceChannels + ' Voice',
                    ].join('\n'),
                    inline: true
                },
                {
                    name: 'Uptime',
                    value: this.getProcessUptime(),
                    inline: true
                },
                {
                    name: 'Servers',
                    value: bot.Guilds.length,
                    inline: true
                },
                {
                    name: 'Commands Run',
                    value: app.bot.statistics.commands,
                    inline: true
                },
                {
                    name: 'Memory Usage',
                    value: this.getSystemMemoryUsage(),
                    inline: true
                }
            ],
            footer: {
                text: `Created using NodeJS and the Discordie framework`
            }
        });
    }

    getChannelStats() {
        return app.cache.remember('bot.stats.channels', 60, () => {
            let channels = bot.Channels.toArray();
            let textChannels = channels.reduce((a, channel) => {
                return (channel.constructor.name == 'ITextChannel') ? a + 1 : a;
            }, 0);

            return {
                totalChannels: channels.length,
                textChannels: textChannels,
                voiceChannels: channels.length - textChannels
            };
        });
    }

    getMemberStats() {
        return app.cache.remember('bot.stats.members', 60, () => {
            let guildMembers = bot.Guilds.map(guild => { return guild.members });

            return {
                totalMembers: guildMembers.reduce((a, b) => { return a + b.length }, 0),
                totalOnline: guildMembers.reduce((a, b) => {
                    return a + b.reduce((c, member) => {
                        return (member.status == 'offline') ? c : c + 1;
                    }, 0);
                }, 0),

                uniqueMembers: bot.Users.length,
                uniqueOnline: bot.Users.toArray().reduce((a, member) => {
                    return (member.status == 'offline') ? a : a + 1;
                }, 0)
            };
        });
    }

    getProcessUptime() {
        let seconds = process.uptime();

        let d = Math.floor(seconds / 86400);
        let h = Math.floor((seconds % 86400) / 3600);
        let m = Math.floor(((seconds % 86400) % 3600) / 60);
        let s = Math.floor(((seconds % 86400) % 3600) % 60);

        if (d > 0) {
            return `${d}d ${h}h ${m}m ${s}s`;
        }

        if (h > 0) {
            return `${h}h ${m}m ${s}s`;
        }

        if (m > 0) {
            return `${m}m ${s}s`;
        }

        return `${s}s`;
    }

    getSystemMemoryUsage() {
        let memoryInBytes = process.memoryUsage().heapTotal - process.memoryUsage().heapUsed;
        let sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];

        let k = 1000;
        let i = Math.floor(Math.log(memoryInBytes) / Math.log(k));

        return parseFloat((memoryInBytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
}

module.exports = StatsCommand;
<commit_msg>Fix commit messages in the stats command<commit_after>/** @ignore */
const Command = require('./../Command');

class StatsCommand extends Command {
    constructor() {
        super('!', 'stats', [], {
            middleware: [
                'throttle.channel:1,5'
            ]
        });
    }

    onCommand(sender, message, args) {
        let members  = this.getMemberStats();
        let channels = this.getChannelStats();
        let author = bot.Users.find(user => { return user.id === '88739639380172800' });
        let description = 'Created by Senither#8023 using the Discordie framework!';

        if (app.cache.has('github.commits')) {
            description = '**Latest changes:**\n';

            app.cache.get('github.commits').slice(0, 3).forEach(commit => {
                let message = commit.commit.message.split('\n')[0];
                description += `[\`${commit.sha.substr(0, 7)}\`](${commit.html_url}) ${message}\n`;
            });
        }

        message.channel.sendMessage('', false, {
            timestamp: new Date,
            color: 0x3498db,
            url: 'https://discordapp.com/invite/gt2FWER',
            title: 'Official Bot Server Invite',
            description: description.trim(),
            author: {
                icon_url: `https://cdn.discordapp.com/avatars/${author.id}/${author.avatar}.png?size=256`,
                name: `${author.username}#${author.discriminator}`
            },
            fields: [
                {
                    name: 'Members',
                    value: [
                        members.totalMembers + ' Total',
                        members.totalOnline + ' Online',
                        members.uniqueMembers + ' Unique',
                        members.uniqueOnline + ' Unique online',
                    ].join('\n'),
                    inline: true
                },
                {
                    name: 'Channels',
                    value: [
                        channels.totalChannels + ' Total',
                        channels.textChannels + ' Text',
                        channels.voiceChannels + ' Voice',
                    ].join('\n'),
                    inline: true
                },
                {
                    name: 'Uptime',
                    value: this.getProcessUptime(),
                    inline: true
                },
                {
                    name: 'Servers',
                    value: bot.Guilds.length,
                    inline: true
                },
                {
                    name: 'Commands Run',
                    value: app.bot.statistics.commands,
                    inline: true
                },
                {
                    name: 'Memory Usage',
                    value: this.getSystemMemoryUsage(),
                    inline: true
                }
            ],
            footer: {
                text: `Created using NodeJS and the Discordie framework`
            }
        });
    }

    getChannelStats() {
        return app.cache.remember('bot.stats.channels', 60, () => {
            let channels = bot.Channels.toArray();
            let textChannels = channels.reduce((a, channel) => {
                return (channel.constructor.name == 'ITextChannel') ? a + 1 : a;
            }, 0);

            return {
                totalChannels: channels.length,
                textChannels: textChannels,
                voiceChannels: channels.length - textChannels
            };
        });
    }

    getMemberStats() {
        return app.cache.remember('bot.stats.members', 60, () => {
            let guildMembers = bot.Guilds.map(guild => { return guild.members });

            return {
                totalMembers: guildMembers.reduce((a, b) => { return a + b.length }, 0),
                totalOnline: guildMembers.reduce((a, b) => {
                    return a + b.reduce((c, member) => {
                        return (member.status == 'offline') ? c : c + 1;
                    }, 0);
                }, 0),

                uniqueMembers: bot.Users.length,
                uniqueOnline: bot.Users.toArray().reduce((a, member) => {
                    return (member.status == 'offline') ? a : a + 1;
                }, 0)
            };
        });
    }

    getProcessUptime() {
        let seconds = process.uptime();

        let d = Math.floor(seconds / 86400);
        let h = Math.floor((seconds % 86400) / 3600);
        let m = Math.floor(((seconds % 86400) % 3600) / 60);
        let s = Math.floor(((seconds % 86400) % 3600) % 60);

        if (d > 0) {
            return `${d}d ${h}h ${m}m ${s}s`;
        }

        if (h > 0) {
            return `${h}h ${m}m ${s}s`;
        }

        if (m > 0) {
            return `${m}m ${s}s`;
        }

        return `${s}s`;
    }

    getSystemMemoryUsage() {
        let memoryInBytes = process.memoryUsage().heapTotal - process.memoryUsage().heapUsed;
        let sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];

        let k = 1000;
        let i = Math.floor(Math.log(memoryInBytes) / Math.log(k));

        return parseFloat((memoryInBytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
}

module.exports = StatsCommand;
<|endoftext|>


<commit_before>'use strict';

angular.module('snotes30App')
.service('ArchiveService', function ($rootScope, $q, Restangular) {
  var archive = Restangular.all('archive');

  this.getList = function () {
    return archive.getList()
  };

  this.getRecentList = function () {
    return archive.getList();
  };
});
<commit_msg>archive: add recent list<commit_after>'use strict';

angular.module('snotes30App')
.service('ArchiveService', function ($rootScope, $q, Restangular) {
  var archive = Restangular.all('archive');

  this.getList = function () {
    return archive.getList()
  };

  this.getRecentList = function () {
    return archive.getList({type: 'recent'});
  };
});
<|endoftext|>


<commit_before>'use strict';

const conf = global.conf;
const pubDir = global.conf.ui.paths.public;
const srcDir = global.conf.ui.paths.source;

const gulp = require('gulp');
const plugins = require('gulp-load-plugins')();

const utils = require('../core/lib/utils');

gulp.task('tcp-ip-reload:listen', function () {
  plugins.refresh.listen({port: conf.livereload_port});
});

gulp.task('tcp-ip-reload:assetsScripts', function () {
  return gulp.src(utils.pathResolve(pubDir.root) + '/!(_styles|patterns|styleguide)/**')
    .pipe(plugins.refresh());
});

gulp.task('tcp-ip-reload:index', function () {
  return gulp.src(utils.pathResolve(pubDir.root) + '/index.html')
    .pipe(plugins.refresh());
});

gulp.task('tcp-ip-reload:injectStyles', function () {
  return gulp.src(utils.pathResolve(pubDir.css) + '/**/*.css')
    .pipe(plugins.refresh());
});

gulp.task('tcp-ip-reload:watch', function () {
  // Need delay in order for launch to succeed consistently.
  setTimeout(function () {
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.images)}, ['patternlab:copy']);
    gulp.watch('_data.json', {cwd: utils.pathResolve(srcDir.data)}, ['data']);
    gulp.watch('listitems.json', {cwd: utils.pathResolve(srcDir.data)}, ['patternlab:build']);
    gulp.watch('annotations.json', {cwd: utils.pathResolve(srcDir.annotations)}, ['patternlab:build']);
    gulp.watch('**/*.mustache', {cwd: utils.pathResolve(srcDir.meta)}, ['patternlab:build']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.patterns)}, ['data']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.js)}, ['patternlab:copy']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.css)}, ['patternlab:copy-styles']);
    gulp.watch('static/**', {cwd: utils.pathResolve(srcDir.root)}, ['patternlab:copy']);
    gulp.watch('!(_styles|patterns|styleguide)/**', {cwd: utils.pathResolve(pubDir.root)}, ['tcp-ip-reload:assetsScripts']);
    gulp.watch('**/*.css', {cwd: utils.pathResolve(pubDir.css)}, ['tcp-ip-reload:injectStyles']);
    gulp.watch('index.html', {cwd: utils.pathResolve(pubDir.root)}, ['tcp-ip-reload:index']);
  }, conf.timeout_main);
});
<commit_msg>more general gulp.watch<commit_after>'use strict';

const conf = global.conf;
const pubDir = global.conf.ui.paths.public;
const srcDir = global.conf.ui.paths.source;

const gulp = require('gulp');
const plugins = require('gulp-load-plugins')();

const utils = require('../core/lib/utils');

gulp.task('tcp-ip-reload:listen', function () {
  plugins.refresh.listen({port: conf.livereload_port});
});

gulp.task('tcp-ip-reload:assetsScripts', function () {
  return gulp.src(utils.pathResolve(pubDir.root) + '/!(_styles|patterns|styleguide)/**')
    .pipe(plugins.refresh());
});

gulp.task('tcp-ip-reload:index', function () {
  return gulp.src(utils.pathResolve(pubDir.root) + '/index.html')
    .pipe(plugins.refresh());
});

gulp.task('tcp-ip-reload:injectStyles', function () {
  return gulp.src(utils.pathResolve(pubDir.css) + '/**/*.css')
    .pipe(plugins.refresh());
});

gulp.task('tcp-ip-reload:watch', function () {
  // Need delay in order for launch to succeed consistently.
  setTimeout(function () {
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.images)}, ['patternlab:copy']);
    gulp.watch('_data.json', {cwd: utils.pathResolve(srcDir.data)}, ['data']);
    gulp.watch('listitems.json', {cwd: utils.pathResolve(srcDir.data)}, ['patternlab:build']);
    gulp.watch('annotations.json', {cwd: utils.pathResolve(srcDir.annotations)}, ['patternlab:build']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.meta)}, ['patternlab:build']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.patterns)}, ['data']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.js)}, ['patternlab:copy']);
    gulp.watch('**', {cwd: utils.pathResolve(srcDir.css)}, ['patternlab:copy-styles']);
    gulp.watch('static/**', {cwd: utils.pathResolve(srcDir.root)}, ['patternlab:copy']);
    gulp.watch('!(_styles|patterns|styleguide)/**', {cwd: utils.pathResolve(pubDir.root)}, ['tcp-ip-reload:assetsScripts']);
    gulp.watch('**', {cwd: utils.pathResolve(pubDir.css)}, ['tcp-ip-reload:injectStyles']);
    gulp.watch('index.html', {cwd: utils.pathResolve(pubDir.root)}, ['tcp-ip-reload:index']);
  }, conf.timeout_main);
});
<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.factories')
    .factory('cvEvaluator', function (stem, storageAccess) {
        var evaluateAllCv = function () {
            var allCv = storageAccess.getAllCV();
            var jobDesc = storageAccess.getJobDescription();

            var stemmedJobDescription = stemJobDesc(jobDesc);
            var stemmedAllCv = allCv.map(function(cv) {return stemCv(cv);});

            var rankedCvs = [];
            //to change to suit new structure of cv
            //essential and preferredSkills is now an array of objects, where the key is the name of the skill, and value is the priority
            //TODO: adapt this to new format
            //stemmedAllCv.forEach(function (stemmedCv) {
            //    // evaluate minimum requirements
            //    //to give different weightage
            //    //parse essential skills and preferred skills for now
            //    var essentialSkillsMatch = findMatchingWords(stemmedJobDescription.essentialSkills, stemmedCv.skill)
            //        + findMatchingWords(stemmedJobDescription.essentialSkills, stemmedCv.experience);
            //    console.log("cv essential skill match", essentialSkillsMatch);
            //
            //    var preferredSkillsMatch = findMatchingWords(stemmedJobDescription.preferredSkills, stemmedCv.skill)
            //    + findMatchingWords(stemmedJobDescription.preferredSkills, stemmedCv.experience);
            //    console.log("cv preferred skill match", preferredSkillsMatch);
            //    var result = {
            //        id: stemmedCv.id,
            //        score: essentialSkillsMatch + preferredSkillsMatch
            //    };
            //    rankedCvs.push(result);
            //});
            //console.log("ranked CVS", rankedCvs);
            return rankedCvs;
        };

        //returns number of matched words
        function findMatchingWords(source1, source2) {
            var wordsOfSource1 = source1.join(" ").split(" ");
            var wordsOfSource2 = source2.join(" ").split(" ");
          console.log("1", wordsOfSource1, "2", wordsOfSource2);
            //results will contain all of the matched words between word source 1 and word source 2
            var results = [];

            for (var i = 0; i < wordsOfSource1.length; i++) {
                //for each word, check the entire wordsOfSource2?
                var hasKeyWord = function (keyWord) {
                    return wordsOfSource1[i].toLowerCase().indexOf(keyWord.toLowerCase()) >= 0;
                };
                var matchedWords = wordsOfSource2.filter(hasKeyWord);
              console.log("match?", matchedWords);
                results = results.concat(matchedWords);
            }
            return results.length;
        }

        function stemCv(cv) {
            var stemmedCv = new CV();
            //need to stem keys only if needed
            stemmedCv.education = cv.education;
            stemmedCv.education.keywords = stem.stemKeyWords(stemmedCv.education.keywords);
            stemmedCv.language = stem.stem(cv.language);
            stemmedCv.interest = stem.stem(cv.interest);
            stemmedCv.skill = stem.stem(cv.skill);
            stemmedCv.experience = stem.stemKeyWords(cv.experience);
            stemmedCv.id = cv.id;
            console.log("stemmed cv", stemmedCv);
            return stemmedCv;
        }

        function stemJobDesc(jobDesc) {
            var stemmedJobDescription = new JobDescription();
            stemmedJobDescription.essentialSkills = stem.stemKeyWords(jobDesc.essentialSkills);
            stemmedJobDescription.preferredSkills = stem.stemKeyWords(jobDesc.preferredSkills);
            stemmedJobDescription.location = jobDesc.location;
            stemmedJobDescription.education = jobDesc.education;
            stemmedJobDescription.education.keywords = stem.stemKeyWords(stemmedJobDescription.education.keywords);
            stemmedJobDescription.workExperienceTime = jobDesc.workExperienceTime;
            console.log("stemmed job desc", stemmedJobDescription);
            return stemmedJobDescription;
        }

        return {
            evaluateCV: evaluateAllCv
        }
    });<commit_msg>Evaluator updates<commit_after>'use strict';

angular.module('myApp.factories')
    .factory('cvEvaluator', function (stem, storageAccess) {
        var evaluateAllCv = function () {
            // WEIGHTAGES
            var EDU_WEIGHT = 1, ESS_SKILLS_WEIGHT = 1, PRE_SKILLS_WEIGHT = 1, LANG_WEIGHT = 1;

            var allCv = storageAccess.getAllCV();
            var jobDesc = storageAccess.getJobDescription();

            var stemmedJobDescription = stemJobDesc(jobDesc);
            var stemmedAllCv = allCv.map(function(cv) {return stemCv(cv);});

            var rankedCvs = [];
            //to change to suit new structure of cv
            //essential and preferredSkills is now an array of objects, where the key is the name of the skill, and value is the priority
            //TODO: adapt this to new format
            stemmedAllCv.forEach(function (stemmedCv) {
                var score = 0;

                // match education
                var educationScore = findMatchingWords(stemmedCv.education, stemmedJobDescription.education);

                // match skills
                var essentialSkillsScore = 0;
               /* stemmedJobDescription.essentialSkills.forEach(function (skill) {
                    essentialSkillsScore += findMatchingWords(skill, stemmedCv.skill)
                        + findMatchingWords(skill, stemmedCv.experience);
                });*/
                var essentialSkillsScore = findMatchingWords(stemmedJobDescription.essentialSkills, stemmedCv.skill)
                    + findMatchingWords(stemmedJobDescription.essentialSkills, stemmedCv.experience);
                console.log("cv essential skill match", essentialSkillsScore);

                var preferredSkillsScore = findMatchingWords(stemmedJobDescription.preferredSkills, stemmedCv.skill)
                    + findMatchingWords(stemmedJobDescription.preferredSkills, stemmedCv.experience);
                console.log("cv preferred skill match", preferredSkillsScore);

                // match language
                var languageScore = findMatchingWords(stemmedJobDescription.language, stemmedCv.language);
                console.log("cv language match", languageScore);

                var result = {
                    id: stemmedCv.id,
                    score: educationScore * EDU_WEIGHT
                        + essentialSkillsScore * ESS_SKILLS_WEIGHT
                        + preferredSkillsScore * PRE_SKILLS_WEIGHT
                        + languageScore * LANG_WEIGHT
                };
                rankedCvs.push(result);
            });

            console.log("ranked CVS", rankedCvs);
            return rankedCvs;
        };

        //returns number of matched words
        function findMatchingWords(source1, source2) {
            var wordsOfSource1 = source1.join(" ").split(" ");
            var wordsOfSource2 = source2.join(" ").split(" ");
            console.log("1", wordsOfSource1, "2", wordsOfSource2);
            //results will contain all of the matched words between word source 1 and word source 2
            var results = [];

            for (var i = 0; i < wordsOfSource1.length; i++) {
                //for each word, check the entire wordsOfSource2?
                var hasKeyWord = function (keyWord) {
                    return wordsOfSource1[i].toLowerCase().indexOf(keyWord.toLowerCase()) >= 0;
                };
                var matchedWords = wordsOfSource2.filter(hasKeyWord);
                console.log("match?", matchedWords);
                results = results.concat(matchedWords);
            }
            return results.length;
        }

        function stemCv(cv) {
            var stemmedCv = new CV();
            //need to stem keys only if needed
            stemmedCv.education = cv.education;
            stemmedCv.education.keywords = stem.stemKeyWords(stemmedCv.education.keywords);
            stemmedCv.language = stem.stem(cv.language);
            stemmedCv.interest = stem.stem(cv.interest);
            stemmedCv.skill = stem.stem(cv.skill);
            stemmedCv.experience = stem.stemKeyWords(cv.experience);
            stemmedCv.id = cv.id;
            console.log("stemmed cv", stemmedCv);
            return stemmedCv;
        }

        function stemJobDesc(jobDesc) {
            var stemmedJobDescription = new JobDescription();
            stemmedJobDescription.essentialSkills = stem.stemKeyWords(jobDesc.essentialSkills);
            stemmedJobDescription.preferredSkills = stem.stemKeyWords(jobDesc.preferredSkills);
            stemmedJobDescription.location = jobDesc.location;
            stemmedJobDescription.education = jobDesc.education;
            stemmedJobDescription.education.keywords = stem.stemKeyWords(stemmedJobDescription.education.keywords);
            stemmedJobDescription.workExperienceTime = jobDesc.workExperienceTime;
            console.log("stemmed job desc", stemmedJobDescription);
            return stemmedJobDescription;
        }

        return {
            evaluateCV: evaluateAllCv
        }
    });<|endoftext|>


<commit_before>/*jshint node:true, es3:false*/
(function() {
  'use strict';
  module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt); // Load grunt tasks automatically
    // Project configuration.
    grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      jshint: {
        all: ['Gruntfile.js', 'src/**/*.js', 'spec/**/*.js']
      },
      watch: {
        options: {
          spawn: false
        },
        //watches all scripts an rerun hinting and the tests immediately
        scripts: {
          files: ['<%= jshint.all %>'],
          tasks: ['jshint', 'karma:server:run']
        }
      },
      'bower-verify': {
        test: {
          tasks: ['karma:once']
        }
      },
      karma: {
        options: {
          configFile: 'karma.conf.js'
        },
        //for a single run of test
        once: {
          singleRun: true,
        },
        //for use while developing and in combination with watch task
        server: {
          background: true,
        },
      }
    });

    //For development
    grunt.registerTask('develop', ['jshint', 'karma:server', 'watch:scripts']);

    //For testing
    grunt.registerTask('test', ['jshint', 'karma:once']);
    grunt.registerTask('test:full', ['jshint', 'bower-verify']);
  };
})();
<commit_msg>fixed bowerVerify name<commit_after>/*jshint node:true, es3:false*/
(function() {
  'use strict';
  module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt); // Load grunt tasks automatically
    // Project configuration.
    grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      jshint: {
        all: ['Gruntfile.js', 'src/**/*.js', 'spec/**/*.js']
      },
      watch: {
        options: {
          spawn: false
        },
        //watches all scripts an rerun hinting and the tests immediately
        scripts: {
          files: ['<%= jshint.all %>'],
          tasks: ['jshint', 'karma:server:run']
        }
      },
      bowerVerify: {
        test: {
          tasks: ['karma:once']
        }
      },
      karma: {
        options: {
          configFile: 'karma.conf.js'
        },
        //for a single run of test
        once: {
          singleRun: true,
        },
        //for use while developing and in combination with watch task
        server: {
          background: true,
        },
      }
    });

    //For development
    grunt.registerTask('develop', ['jshint', 'karma:server', 'watch:scripts']);

    //For testing
    grunt.registerTask('test', ['jshint', 'karma:once']);
    grunt.registerTask('test:full', ['jshint', 'bower-verify']);
  };
})();
<|endoftext|>


<commit_before>var ApiGen = ApiGen || {};
ApiGen.elements = [
    ["c", "ErrorCode"],
    ["c", "PKCS7Encoder"],
    ["c", "Prpcrypt"],
    ["c", "SHA1"],
    ["c", "Weixin_BaseCore"],
    ["c", "WeiXin_SDK"],
    ["c", "Weixin_Template"],
    ["f", "wx_admin_log()"],
    ["f", "wx_is_xml()"],
    ["f", "wx_notice_msg()"],
    ["f", "wx_parse_xml()"],
    ["f", "wx_random_big_pic()"],
    ["f", "wx_random_small_pic()"],
    ["f", "wx_request_array()"],
    ["f", "wx_request_decode()"],
    ["f", "wx_request_is_encode()"],
    ["f", "wx_request_xml()"],
    ["f", "wx_send_encode()"],
    ["c", "WXBizMsgCrypt"],
    ["c", "WxRobot_Admin"],
    ["c", "WxRobot_Admin_Menu_Extends"],
    ["c", "WxRobot_Admin_Menu_Instro"],
    ["c", "WxRobot_Admin_Menu_Menu"],
    ["c", "WxRobot_Admin_Menu_Records"],
    ["c", "WxRobot_Admin_Menu_Reply"],
    ["c", "WxRobot_Admin_Menu_Setting"],
    ["c", "WxRobot_Admin_Menu_Statistics"],
    ["c", "WxRobot_Cmd"],
    ["c", "WxRobot_Cmd_Event"],
    ["c", "WxRobot_Cmd_Event_User"],
    ["c", "WxRobot_Cmd_Text"],
    ["c", "WxRobot_Extends"],
    ["c", "WxRobot_Install"],
    ["c", "WxRobot_Robot"],
    ["c", "WxRobot_SDK"],
    ["c", "WxRobot_Table_Extends"],
    ["c", "WxRobot_Table_Menu"],
    ["c", "WxRobot_Table_Records"],
    ["c", "WxRobot_Table_Reply"],
    ["c", "WxRobot_Uninstall"],
    ["c", "WxRobot_Wp"],
    ["c", "XMLParse"]
];

var _hmt = _hmt || [];
(function() {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?c66706e0fc1b6293a62f8eba588390ec";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
})();

var google = document.createElement("script");
google.src = "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(google, s);
(adsbygoogle = window.adsbygoogle || []).push({
  google_ad_client: "ca-pub-7736695762519033",
  enable_page_level_ads: true
});<commit_msg>Update api-docs/elementlist.js<commit_after>var ApiGen = ApiGen || {};
ApiGen.elements = [
    ["c", "ErrorCode"],
    ["c", "PKCS7Encoder"],
    ["c", "Prpcrypt"],
    ["c", "SHA1"],
    ["c", "Weixin_BaseCore"],
    ["c", "WeiXin_SDK"],
    ["c", "Weixin_Template"],
    ["f", "wx_admin_log()"],
    ["f", "wx_is_xml()"],
    ["f", "wx_notice_msg()"],
    ["f", "wx_parse_xml()"],
    ["f", "wx_random_big_pic()"],
    ["f", "wx_random_small_pic()"],
    ["f", "wx_request_array()"],
    ["f", "wx_request_decode()"],
    ["f", "wx_request_is_encode()"],
    ["f", "wx_request_xml()"],
    ["f", "wx_send_encode()"],
    ["c", "WXBizMsgCrypt"],
    ["c", "WxRobot_Admin"],
    ["c", "WxRobot_Admin_Menu_Extends"],
    ["c", "WxRobot_Admin_Menu_Instro"],
    ["c", "WxRobot_Admin_Menu_Menu"],
    ["c", "WxRobot_Admin_Menu_Records"],
    ["c", "WxRobot_Admin_Menu_Reply"],
    ["c", "WxRobot_Admin_Menu_Setting"],
    ["c", "WxRobot_Admin_Menu_Statistics"],
    ["c", "WxRobot_Cmd"],
    ["c", "WxRobot_Cmd_Event"],
    ["c", "WxRobot_Cmd_Event_User"],
    ["c", "WxRobot_Cmd_Text"],
    ["c", "WxRobot_Extends"],
    ["c", "WxRobot_Install"],
    ["c", "WxRobot_Robot"],
    ["c", "WxRobot_SDK"],
    ["c", "WxRobot_Table_Extends"],
    ["c", "WxRobot_Table_Menu"],
    ["c", "WxRobot_Table_Records"],
    ["c", "WxRobot_Table_Reply"],
    ["c", "WxRobot_Uninstall"],
    ["c", "WxRobot_Wp"],
    ["c", "XMLParse"]
];

function isLocal() {
    var local_url = "http://127.0.0.1:4000/";
    if (location.href.substr(0, local_url.length) == local_url) {
        return true;
    }
    return false;
}

if (!isLocal()) {
    var targetProtocol = "https:";
    if (window.location.protocol != targetProtocol) {
        window.location.href = targetProtocol +
            window.location.href.substring(window.location.protocol.length);
    }
}

var _hmt = _hmt || [];
(function() {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?c66706e0fc1b6293a62f8eba588390ec";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
})();

var google = document.createElement("script");
google.src = "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(google, s);
(adsbygoogle = window.adsbygoogle || []).push({
  google_ad_client: "ca-pub-7736695762519033",
  enable_page_level_ads: true
});<|endoftext|>


<commit_before>// ==UserScript==
// @name        Canvas CSS Tweaks
// @namespace   https://github.com/jamesjonesmath/canvancement
// @description Various tweaks to Canvas CSS
// @include     https://*.instructure.com/courses/*
// @include     https://*.instructure.com/accounts/*
// @version     1
// ==/UserScript==
(function () {
  'use strict';

  // Only run in parent window, do not run in iframes
  if (window !== parent.window) {
    return;
  }

  // Select the features to enable. Comment out or delete any you do not want
  const features = [
    'fullscreen', // use full width of page
    'sg_rubrics', // don't make rubrics so big in speedgrader
    // 'no_test' , // hide test instance notification in test and beta
  ];

  const rules = [];

  // Allow Canvas to use the full width of the page
  if (features.indexOf('fullscreen') > -1) {
    if (!document.body.classList.contains('full-width') && !document.body.classList.contains('outcomes')) {
      console.log('Step 2a');
      rules.push('body:not(.full-width):not(.outcomes) #wrapper.ic-Layout-wrapper {max-width:none;}');
    }
  }

  // Override the min-width=60rem; that Canvas has on rubrics in speedgrader
  if (features.indexOf('sg_rubrics') > -1) {
    if (/^\/courses\/\d+\/gradebook\/speed_grader$/.test(window.location.pathname)) {
      console.log('step 1a');
      rules.push('#rubric_holder .rubric_container.rubric.assessing .react-rubric {min-width: min-content !important;}');
    }
  }

  // Disable the test instance notification
  if (features.indexOf('no_test') > -1) {
    rules.push('#fixed_bottom {display: none;}');
  }

  if (rules.length) {
    const style = document.createElement('style');
    document.head.appendChild(style);
    const sheet = style.sheet;
    for (let i = 0; i < rules.length; i++) {
      sheet.insertRule(rules[i],i);
    }
  }
}) ();
<commit_msg>Added a rule for table-layout in rubrics<commit_after>// ==UserScript==
// @name        Canvas CSS Tweaks
// @namespace   https://github.com/jamesjonesmath/canvancement
// @description Various tweaks to Canvas CSS
// @include     https://*.instructure.com/courses/*
// @include     https://*.instructure.com/accounts/*
// @version     2
// ==/UserScript==
(function () {
  'use strict';

  // Only run in parent window, do not run in iframes
  if (window !== parent.window) {
    return;
  }

  // Select the features to enable. Comment out or delete any you do not want
  const features = [
    'fullscreen', // use full width of page
    'sg_rubrics', // don't make rubrics so big in speedgrader
    // 'no_test' , // hide test instance notification in test and beta
  ];

  const rules = [];

  // Allow Canvas to use the full width of the page
  if (features.indexOf('fullscreen') > -1) {
    if (!document.body.classList.contains('full-width') && !document.body.classList.contains('outcomes')) {
      console.log('Step 2a');
      rules.push('body:not(.full-width):not(.outcomes) #wrapper.ic-Layout-wrapper {max-width:none;}');
    }
  }

  // Override the min-width=60rem; that Canvas has on rubrics in speedgrader
  if (features.indexOf('sg_rubrics') > -1) {
    if (/^\/courses\/\d+\/gradebook\/speed_grader$/.test(window.location.pathname)) {
      console.log('step 1a');
      rules.push('#rubric_holder .rubric_container.rubric.assessing .react-rubric {min-width: min-content !important;}');
      rules.push('#rubric_holder .rubric_container.rubric.assessing .react-rubric table {table-layout: auto;}');
    }
  }

  // Disable the test instance notification
  if (features.indexOf('no_test') > -1) {
    rules.push('#fixed_bottom {display: none;}');
  }

  if (rules.length) {
    const style = document.createElement('style');
    document.head.appendChild(style);
    const sheet = style.sheet;
    for (let i = 0; i < rules.length; i++) {
      sheet.insertRule(rules[i],i);
    }
  }
}) ();
<|endoftext|>


<commit_before>/*** MQTT Z-Way odule *******************************************
 Version: 1.0.0
 -----------------------------------------------------------------------------
 Author: David Uebelacker <david@uebelacker.ch>
 ******************************************************************************/

function ZWayMqttBridge(id, controller) {
    ZWayMqttBridge.super_.call(this, id, controller);
}

inherits(ZWayMqttBridge, AutomationModule);

_module = ZWayMqttBridge;

ZWayMqttBridge.prototype.init = function (config) {
    ZWayMqttBridge.super_.prototype.init.call(this, config);

    var self = this;

    this.log = function (message) {
        console.log('ZWayMqttBridge: ' + message);
    };

    if (!self.config.host || !self.config.port) {
        this.log('Host or port not configured! will not start!')
    }
    ;

    this.reconnect = function () {
        self.connected = false;
        self.mqttBridge = null;
        self.log('Will try to reconnect to Mqtt Bridge in 10 seconds ...');
        setTimeout(function () {
            self.connect();
        }, 10000);
    };

    this.connect = function () {
        self.log('Connecting to Mqtt Bridge ....');

        this.mqttBridge = new sockets.tcp();
        this.mqttBridge.onrecv = function (data) {
            if (!self.connected) {
                self.log('Connecting to Mqtt Bridge established!');
                self.connected = true;
            }

            if (data) {
                var messageStr = String.fromCharCode.apply(null, new Uint8Array(data));
                if (messageStr != 'HELLO') {
                    var message = JSON.parse(messageStr);
                    if (message.topic && message.payload) {
                        self.handleUpdatRequest(message);
                    }
                }
            }
        };

        this.mqttBridge.onclose = function (data) {
            self.log('Mqtt Bridge connection was closed!');
            self.reconnect();
        };

        if (this.mqttBridge.connect(self.config.host, parseInt(self.config.port))) {
            setTimeout(function () {
                if (self.mqttBridge && !self.connected) {
                    self.log('Mqtt Bridge connection timeout!');
                    self.reconnect();
                }
            }, 5000);
        } else {
            self.log('Could not connect to Mqtt Bridge!');
            self.reconnect();
        }
    };

    this.handleUpdatRequest = function (message) {
        var device = self.findDevice(message.topic);
        if (device) {
            device.performCommand(message.payload);
        }
    };

    this.findDevice = function (topic) {

        var devices = self.controller.devices;
        if (devices) {
            for (var i = 0; i < devices.length; i++) {

                self.log(JSON.stringify(devices[i]));
                /*
                    var device_topic = self.createTopic(devices[i]);
                    if (device_topic + '/' + 'set' == topic) {
                        return devices[i];
                    }
                    */
            }
        }
        return null;
    };

    this.findRoom = function (id) {
        var locations = self.controller.locations;
        if (locations) {
            for (var i = 0; i < locations.length; i++) {
                if (locations[i].id == id) {
                    return locations[i];
                }
            }
        }
        return null;
    };

    this.createTopic = function (device) {
        var room = self.findRoom(device.get('location'));
        var topic = self.config.topic_prefix;
        topic += '/';
        topic += self.normalizeTopicToken(room.title);
        topic += '/';
        topic += self.normalizeTopicToken(device.get('metrics:title'));
        return topic;
    };

    this.normalizeTopicToken = function (token) {
        token = token.toLowerCase();
        token = token.replace(/[^0-9a-z_]/g, '_');
        return token;
    };

    this.deviceUpdate = function (device) {
        if (self.mqttBridge) {
            var message = {
                'topic': self.createTopic(device),
                'payload': device.get('metrics:level')
            };

            var str = JSON.stringify(message);
            self.log('Sending update to bridge:' + str);
            var buf = new ArrayBuffer(str.length); // 2 bytes for each char
            var bufView = new Uint8Array(buf);

            for (var i = 0; i < str.length; i++) {
                bufView[i] = str.charCodeAt(i);
            }

            self.mqttBridge.send(buf);
        }
    };

    this.connect();
    this.controller.devices.on('change:metrics:level', self.deviceUpdate);
};

<commit_msg>devel<commit_after>/*** MQTT Z-Way odule *******************************************
 Version: 1.0.0
 -----------------------------------------------------------------------------
 Author: David Uebelacker <david@uebelacker.ch>
 ******************************************************************************/

function ZWayMqttBridge(id, controller) {
    ZWayMqttBridge.super_.call(this, id, controller);
}

inherits(ZWayMqttBridge, AutomationModule);

_module = ZWayMqttBridge;

ZWayMqttBridge.prototype.init = function (config) {
    ZWayMqttBridge.super_.prototype.init.call(this, config);

    var self = this;

    this.log = function (message) {
        console.log('ZWayMqttBridge: ' + message);
    };

    if (!self.config.host || !self.config.port) {
        this.log('Host or port not configured! will not start!')
    }
    ;

    this.reconnect = function () {
        self.connected = false;
        self.mqttBridge = null;
        self.log('Will try to reconnect to Mqtt Bridge in 10 seconds ...');
        setTimeout(function () {
            self.connect();
        }, 10000);
    };

    this.connect = function () {
        self.log('Connecting to Mqtt Bridge ....');

        this.mqttBridge = new sockets.tcp();
        this.mqttBridge.onrecv = function (data) {
            if (!self.connected) {
                self.log('Connecting to Mqtt Bridge established!');
                self.connected = true;
            }

            if (data) {
                var messageStr = String.fromCharCode.apply(null, new Uint8Array(data));
                if (messageStr != 'HELLO') {
                    var message = JSON.parse(messageStr);
                    if (message.topic && message.payload) {
                        self.handleUpdatRequest(message);
                    }
                }
            }
        };

        this.mqttBridge.onclose = function (data) {
            self.log('Mqtt Bridge connection was closed!');
            self.reconnect();
        };

        if (this.mqttBridge.connect(self.config.host, parseInt(self.config.port))) {
            setTimeout(function () {
                if (self.mqttBridge && !self.connected) {
                    self.log('Mqtt Bridge connection timeout!');
                    self.reconnect();
                }
            }, 5000);
        } else {
            self.log('Could not connect to Mqtt Bridge!');
            self.reconnect();
        }
    };

    this.handleUpdatRequest = function (message) {
        var device = self.findDevice(message.topic);
        if (device) {
            device.performCommand(message.payload);
        }
    };

    this.findDevice = function (topic) {
        return self.controller.devices.findWhere(function (device) {
            var device_topic = self.createTopic(device);
            return device_topic + '/' + 'set' == topic;
        });
    };

    this.findRoom = function (id) {
        var locations = self.controller.locations;
        if (locations) {
            for (var i = 0; i < locations.length; i++) {
                if (locations[i].id == id) {
                    return locations[i];
                }
            }
        }
        return null;
    };

    this.createTopic = function (device) {
        var room = self.findRoom(device.get('location'));
        var topic = self.config.topic_prefix;
        topic += '/';
        topic += self.normalizeTopicToken(room.title);
        topic += '/';
        topic += self.normalizeTopicToken(device.get('metrics:title'));
        return topic;
    };

    this.normalizeTopicToken = function (token) {
        token = token.toLowerCase();
        token = token.replace(/[^0-9a-z_]/g, '_');
        return token;
    };

    this.deviceUpdate = function (device) {
        if (self.mqttBridge) {
            var message = {
                'topic': self.createTopic(device),
                'payload': device.get('metrics:level')
            };

            var str = JSON.stringify(message);
            self.log('Sending update to bridge:' + str);
            var buf = new ArrayBuffer(str.length); // 2 bytes for each char
            var bufView = new Uint8Array(buf);

            for (var i = 0; i < str.length; i++) {
                bufView[i] = str.charCodeAt(i);
            }

            self.mqttBridge.send(buf);
        }
    };

    this.connect();
    this.controller.devices.on('change:metrics:level', self.deviceUpdate);
};

<|endoftext|>


<commit_before>define(["Ti/_/css", "Ti/_/declare", "Ti/_/style", "Ti/_/lang", "Ti/API", "Ti/UI", "Ti/_", "Ti/_/dom"],
	function(css, declare, style, lang, API, UI, _, dom) {

	var isDef = lang.isDef,
		val = lang.val;

	return declare("Ti._.Layouts.Base", null, {

		computedSize: {width: 0, height: 0},

		constructor: function(element) {
			this.element = element;
			css.add(element.domNode, css.clean(this.declaredClass));
		},

		destroy: function() {
			css.remove(this.element.domNode, css.clean(this.declaredClass));
		},

		handleInvalidState: function(child, parent) {
			API.debug("WARNING: Attempting to layout element that has been destroyed.\n\t Removing the element from the parent.\n\t The parent has a widget ID of " + parent.widgetId + ".");
			var children = parent._children;
			children.splice(children.indexOf(child),1);
		},

		getValueType: function(value) {
			if (isDef(value)) {
				if (value === UI.SIZE || value === UI.FILL) {
					return value;
				}
				return ~(value + "").indexOf("%") ? "%" : "#";
			}
		},

		calculateAnimation: function(node, animation) {
			var animationCoefficients = node._animationCoefficients,
				center,
				results,
				pixelUnits = "px";

			(node.center || animation.center) && (center = {});
			if (center) {
				center.x = val(animation.center && animation.center.x, node.center && node.center.x);
				center.y = val(animation.center && animation.center.y, node.center && node.center.y);
			}

			!animationCoefficients && (animationCoefficients = node._animationCoefficients = {
				width: {},
				sandboxWidth: {},
				height: {},
				sandboxHeight: {},
				left: {},
				top: {}
			});

			this._measureNode(node, {
				left: val(animation.left,node.left),
				right: val(animation.right,node.right),
				top: val(animation.top,node.top),
				bottom: val(animation.bottom,node.bottom),
				center: center,
				width: val(animation.width,node.width),
				height: val(animation.height,node.height)
			},animationCoefficients, this);

			results = this._doAnimationLayout(node, animationCoefficients);

			style.set(node.domNode, {
				zIndex: node.zIndex | 0,
				left: Math.round(results.left) + pixelUnits,
				top: Math.round(results.top) + pixelUnits,
				width: Math.round(results.width - node._borderLeftWidth - node._borderRightWidth) + pixelUnits,
				height: Math.round(results.height - node._borderTopWidth - node._borderBottomWidth) + pixelUnits
			});
		},

		computeValue: function(dimension, valueType) {
			var value = parseFloat(dimension);
			switch (valueType) {
				case "%":
					return value / 100;

				case "#":
					return dom.computeSize(dimension);
			}
		}

	});

});<commit_msg>[TIMOB-9410] Fixed an animation bug.<commit_after>define(["Ti/_/css", "Ti/_/declare", "Ti/_/style", "Ti/_/lang", "Ti/API", "Ti/UI", "Ti/_", "Ti/_/dom"],
	function(css, declare, style, lang, API, UI, _, dom) {

	var isDef = lang.isDef,
		val = lang.val;

	return declare("Ti._.Layouts.Base", null, {

		computedSize: {width: 0, height: 0},

		constructor: function(element) {
			this.element = element;
			css.add(element.domNode, css.clean(this.declaredClass));
		},

		destroy: function() {
			css.remove(this.element.domNode, css.clean(this.declaredClass));
		},

		handleInvalidState: function(child, parent) {
			API.debug("WARNING: Attempting to layout element that has been destroyed.\n\t Removing the element from the parent.\n\t The parent has a widget ID of " + parent.widgetId + ".");
			var children = parent._children;
			children.splice(children.indexOf(child),1);
		},

		getValueType: function(value) {
			if (isDef(value)) {
				if (value === UI.SIZE || value === UI.FILL) {
					return value;
				}
				return ~(value + "").indexOf("%") ? "%" : "#";
			}
		},

		calculateAnimation: function(node, animation) {
			var animationCoefficients = node._animationCoefficients,
				center,
				results,
				pixelUnits = "px";

			(node.center || animation.center) && (center = {});
			if (center) {
				center.x = val(animation.center && animation.center.x, node.center && node.center.x);
				center.y = val(animation.center && animation.center.y, node.center && node.center.y);
			}

			!animationCoefficients && (animationCoefficients = node._animationCoefficients = {
				width: {},
				minWidth: {},
				sandboxWidth: {},
				height: {},
				minHeight: {},
				sandboxHeight: {},
				left: {},
				top: {}
			});

			this._measureNode(node, {
				left: val(animation.left,node.left),
				right: val(animation.right,node.right),
				top: val(animation.top,node.top),
				bottom: val(animation.bottom,node.bottom),
				center: center,
				width: val(animation.width,node.width),
				minWidth: node.minWidth,
				minHeight: node.minHeight,
				height: val(animation.height,node.height)
			},animationCoefficients, this);

			results = this._doAnimationLayout(node, animationCoefficients);

			style.set(node.domNode, {
				zIndex: node.zIndex | 0,
				left: Math.round(results.left) + pixelUnits,
				top: Math.round(results.top) + pixelUnits,
				width: Math.round(results.width - node._borderLeftWidth - node._borderRightWidth) + pixelUnits,
				height: Math.round(results.height - node._borderTopWidth - node._borderBottomWidth) + pixelUnits
			});
		},

		computeValue: function(dimension, valueType) {
			var value = parseFloat(dimension);
			switch (valueType) {
				case "%":
					return value / 100;

				case "#":
					return dom.computeSize(dimension);
			}
		}

	});

});<|endoftext|>


<commit_before>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO: no-op all of these when on iOS
var platform = cordova.require('cordova/platform');

var GCM_STORAGE_PREFIX = 'gcm-';
var GCM_REGKEY = GCM_STORAGE_PREFIX+'RegID';

var Event = require('org.chromium.common.events');
var exec = require('cordova/exec');
var channel = require('cordova/channel');
var _registrationId;

exports.MAX_MESSAGE_SIZE = 4096;

exports.send = function(message, callback){
  var win = function(msg) {
    callback(msg);
  }
  var fail = function(msg) {
    console.log('Send failed: '+msg);
    callback(msg);
  }
  var dest = message.destinationId;
  chrome.runtime.lastError=undefined;
  var n = JSON.stringify(message).length;
  if(n>4096) {
     throw(new Error("Payload exceeded allowed size limit. Payload size is: "+n));
  }
  console.log('sending to '+dest);
  exec(win, fail, 'ChromeGcm', 'send',  [dest,message]  );
}

exports.unregister = function(callback) {

  var unregok = function() {
    console.log('Cleared registration ');
    setRegistrationID('');
    callback();
  }
  var unregfail = function() {
    chrome.runtime.lastError='Unregistration Failed';
    callback();
  }
  getRegistrationID(function(regid) {
    chrome.runtime.lastError=undefined;
    if(regid) {
      exec(unregok, unregfail, 'ChromeGcm', 'unregister',[''] );
    } else {
      console.log('Not registered - skipping de-register');
    }
  });
}

// registration should be cached in localstorage.
// If its not there, then registration is required
exports.register = function(senderid, callback) {

  var win = function(registrationId) {
    setRegistrationID(registrationId);
    callback(registrationId);
  }
  var fail = function(msg) {
    console.log('Registration failed: '+msg);
    callback(null);
  }
  chrome.runtime.lastError=undefined;
  if(senderid[0].length == 0) {
    throw(new Error("Invalid value for argument 1. Property '.0': String must be at least 1 characters long."));
  }
  console.log('starting registration check');
  getRegistrationID(function(regid) {
    if(!regid) {
       console.log('Registering');
       exec(win, fail, 'ChromeGcm', 'getRegistrationId',  senderid );
    } else {
      console.log('Using cached  registrationId:' +regid);
      callback(regid);
    }
  });
}

exports.onMessage = new Event('onMessage');
exports.onMessagesDeleted = new Event('onMessagesDeleted');
exports.onSendError = new Event('onSendError');

function setRegistrationID(regid) {
  var regidObject ={};
  regidObject[GCM_REGKEY]=regid;
  chrome.storage.internal.set(regidObject);
  _registrationId = regid;
}

function getRegistrationID(callback) {
   if(!_registrationId) {
      chrome.storage.internal.get(GCM_REGKEY,function(items){
         if(items[GCM_REGKEY]) {
            _registrationId=items[GCM_REGKEY];
            callback(_registrationId);
         } else {
            callback(null);
         }
      });
   } else {
     callback(_registrationId);
   }
}

function fireQueuedMessages() {
   console.log('firing queued messages');
   exec(undefined, undefined, 'ChromeGcm', 'fireQueuedMessages', []);
}

if (platform.id == 'android') {
  require('org.chromium.common.helpers').runAtStartUp(fireQueuedMessages);
}
<commit_msg>Cleaning gcm, fix jshint jscs errors, remove excess console logs<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/* global cordova */
/* global chrome */

// TODO: no-op all of these when on iOS
var platform = cordova.require('cordova/platform');

var GCM_STORAGE_PREFIX = 'gcm-';
var GCM_REGKEY = GCM_STORAGE_PREFIX + 'RegID';

var Event = require('org.chromium.common.events');
var exec = require('cordova/exec');
var _registrationId;

exports.MAX_MESSAGE_SIZE = 4096;

exports.send = function(message, callback){
  var win = function(msg) {
    callback(msg);
  };
  var fail = function(msg) {
    console.error('[chrome.gcm] Send failed:', msg);
    callback(msg);
  };
  var dest = message.destinationId;
  chrome.runtime.lastError = undefined;
  var n = JSON.stringify(message).length;
  if (n>4096) {
    throw(new Error("Payload exceeded allowed size limit. Payload size is: " + n));
  }
  exec(win, fail, 'ChromeGcm', 'send',  [dest,message]  );
};

exports.unregister = function(callback) {
  var unregok = function() {
    setRegistrationID('');
    callback();
  };
  var unregfail = function() {
    chrome.runtime.lastError = 'Unregistration Failed';
    callback();
  };
  getRegistrationID(function(regid) {
    chrome.runtime.lastError = undefined;
    if (regid) {
      exec(unregok, unregfail, 'ChromeGcm', 'unregister',[''] );
    }
  });
};

// registration should be cached in localstorage.
// If its not there, then registration is required
exports.register = function(senderid, callback) {

  var win = function(registrationId) {
    setRegistrationID(registrationId);
    callback(registrationId);
  };
  var fail = function(msg) {
    console.error('[chrome.gcm] Registration failed:', msg);
    callback(null);
  };
  chrome.runtime.lastError=undefined;
  if (senderid[0].length === 0) {
    throw(new Error("Invalid value for argument 1. Property '.0': String must be at least 1 characters long."));
  }
  getRegistrationID(function(regid) {
    if (!regid) {
      exec(win, fail, 'ChromeGcm', 'getRegistrationId',  senderid );
    } else {
      callback(regid);
    }
  });
};

exports.onMessage = new Event('onMessage');
exports.onMessagesDeleted = new Event('onMessagesDeleted');
exports.onSendError = new Event('onSendError');

function setRegistrationID(regid) {
  var regidObject ={};
  regidObject[GCM_REGKEY]=regid;
  chrome.storage.internal.set(regidObject);
  _registrationId = regid;
}

function getRegistrationID(callback) {
  if (!_registrationId) {
    chrome.storage.internal.get(GCM_REGKEY,function(items){
      if (items[GCM_REGKEY]) {
        _registrationId=items[GCM_REGKEY];
        callback(_registrationId);
      } else {
        callback(null);
      }
    });
  } else {
    callback(_registrationId);
  }
}

function fireQueuedMessages() {
  exec(undefined, undefined, 'ChromeGcm', 'fireQueuedMessages', []);
}

if (platform.id == 'android') {
  require('org.chromium.common.helpers').runAtStartUp(fireQueuedMessages);
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name              Pixiv自動ブックマークタグ付け
// @description       Pixivのブックマークタグ付けを半自動化してくれる
// @include           http://www.pixiv.net/bookmark_add.php?type=illust&illust_id=*
// @run-at            document-end
// @version           0.2.0
// ==/UserScript==

// デフォルトルール
var defaultRuleStr = 'private R-18';

// 設定テキストを解析し、連想配列で返す
var parseRules = function(ruleStr) {
	var patternRule    = [];
	var patternAllRule = [];
	var privateRule    = [];
	var errors         = [];

	// 正規表現を表す文字列のリストから、正規表現のリストを作成
	var createRegExpFromStrAry = function(regexpStrAry, lineNumber) {
		var regexps = [];
		regexpStrAry.forEach(function(regexpStr) {
			try { regexps.push(new RegExp(regexpStr)); }
			catch (e) { errors.push({ lineNumber: lineNumber, message: ('RegularExpression Error:' + e.name + ':' + e.massage + ', Str:' + regexpStr) }); }
		});
		return regexps;
	};

	// strに完全一致する正規表現を生成
	var createRegExpPerfectMatch = function(str) {
		return new RegExp('^' + str.replace(/[.*+?^${}()|\[\]\\]/g, '\\$&') + '$');
	};

	ruleStr.split('\n').forEach(function(line, i) {
		var parsed = line.split(/\s+/);
		var matchData;
		var rule;
		if ( parsed.length >= 3 && (matchData = parsed[0].match(/^match(|_all)$/i)) ) {  // 一致
			rule = { tag: parsed[1], regexps: parsed.slice(2).map(createRegExpPerfectMatch) };
		} else if ( parsed.length >= 3 && (matchData = parsed[0].match(/^pattern(|all)$/i)) ) { // 正規表現
			var regexps = createRegExpFromStrAry(parsed.slice(2), i + 1);
			rule = { tag: parsed[1], regexps: regexps };
		} else if ( parsed.length >= 2 && parsed[0].match(/^private$/i) ) {                     // 非公開タグ
			privateRule.push.apply(privateRule, parsed.slice(1));
			return;
		} else if ( line.match(/^\s*$|^\s*#/) ) {                                               // 空行 or コメント行
			return;
		} else {
			errors.push({ lineNumber: (i+1), message: ('CommandError:Invalid Command or Too Few Arguments, Str:' + line) });
			return;
		}

		Array.prototype.push.call(matchData[1].length === 0 ? patternRule : patternAllRule, rule);
	});
	return { privateRule: privateRule, patternRule: patternRule, patternAllRule: patternAllRule, errors: errors };
};

// matchDataの配列を渡すと文中の~数字をそれで置き換える
var replaceWithMatch = function(input, matchData) {
	return input.split(/(~\d)/).map(function(str) {
		var match = str.match(/^~(\d)/);
		if(match) { return matchData[parseInt(match[1])] || ''; }
		return str;
	}).join('');
};

// 設定画面の生成・消去
var toggleSettingsView = function() {
	// すでに存在していたなら消去
	var settingsView = document.querySelector('#autotag-settings-view');
	if (settingsView) { settingsView.remove(); return; }

	// 保存済みデータの取得
	var ruleStr = window.localStorage.pixivAutoTag_taggingRule || defaultRuleStr;

	// フォームの作成
	settingsView = document.createElement('form');
	settingsView.id = 'autotag-settings-view';
	settingsView.style.backgroundColor = '#FFFFFF';
	settingsView.style.marginTop    = '5px';
	settingsView.style.padding      = '10px 9px';
	settingsView.style.borderRadius = '5px';

	var templateStr  = '
タグ付けルール
<textarea id="autotag-settings-tagging-rule" cols="80" rows="10" style="height:auto;">{{:rule}}</textarea>
';
	settingsView.innerHTML = templateStr.replace('{{:rule}}', ruleStr);

	var buttonsParagraph = document.createElement('p');

	var saveButton = document.createElement('input');
	saveButton.type = 'submit';
	saveButton.className = '_button';
	saveButton.value = '保存';
	settingsView.onsubmit = function() {
		var ruleStr = document.querySelector('#autotag-settings-tagging-rule').value;
		var rule = parseRules(ruleStr);
		if (rule.errors.length === 0) {
			window.localStorage.pixivAutoTag_taggingRule = ruleStr;
			alert('保存しました');
		} else {
			alert(rule.errors.map(function(err) { return '[Error] line: ' + err.lineNumber + ', message: ' + err.message; }).join('\n'));
		}
		return false;
	};
	buttonsParagraph.appendChild(saveButton);

	var cancelButton = document.createElement('input');
	cancelButton.className = '_button';
	cancelButton.type = 'reset';
	cancelButton.value = 'キャンセル';
	// cancelButton.onclick = function() { document.querySelector('#autotag-settings-view').remove(); };
	buttonsParagraph.appendChild(cancelButton);

	settingsView.appendChild(buttonsParagraph);

	var settingsButton = document.querySelector('#autotag-settings-button');
	settingsButton.parentElement.insertBefore(settingsView, settingsButton.nextSibling);
};

// タグの自動追加関数
var autoTag = function() {
	var ruleText = window.localStorage.pixivAutoTag_taggingRule || defaultRuleStr;
	var rule = parseRules(ruleText);

	// 作品タグとタグクラウドの取得
	var tagCloud = Array.prototype.slice.call(document.querySelectorAll('#wrapper > div.layout-body > div > section.list-container.tag-container.tag-cloud-container > ul.list-items.tag-cloud > li')).map(function(item) { return item.textContent; });
	var tagsExist = Array.prototype.concat.apply([], Array.prototype.slice.call(document.querySelectorAll('#wrapper > div.layout-body > div > section.list-container.tag-container.work-tags-container > div > ul > li')).map(function(item) { return item.textContent.replace(/^\*/, '').split('/'); }));

	// 非公開タグが含まれていた場合、自動で非公開に設定
	if (tagsExist.some(function(tag){ return rule.privateRule.indexOf(tag) !== -1; })) {
		document.querySelector('#wrapper > div.layout-body > section > form > div.submit-container > ul > li:nth-child(2) > label').click();
	}

	// ブックマークタグリストの生成
	var input = document.querySelector('#input_tag');
	if (input.value.length === 0) {
		// 作品タグとタグクラウドの共通タグを抽出
		var tagsFound = tagsExist.filter(function(existTag) { return tagCloud.some(function(cloudTag){ return existTag === cloudTag; }); });

		// 付与タグリストの生成
		var tagsAdded = [];
		tagsExist.forEach(function(tag) { // それぞれの作品タグが
			rule.patternRule.forEach(function(patternRule) { // それぞれのルール文に対し
				var matchData = [];
				var foundMatchFlag = patternRule.regexps.some(function(pattern) { // いずれかのパターンに一致するか
					return (matchData = tag.match(pattern));
				});
				if (foundMatchFlag) { tagsAdded.push(replaceWithMatch(patternRule.tag, matchData)); }
			});
		});

		rule.patternAllRule.forEach(function(patternRule) { // それぞれのルール文の
			var matchData = [];
			var foundMatchFlag = patternRule.regexps.every(function(pattern) { // すべてのパターンが
				return tagsExist.some(function(tag) { return (matchData = tag.match(pattern)); }); // いずれかの作品タグに一致するか？
			});
			if (foundMatchFlag) { tagsAdded.push(replaceWithMatch(patternRule.tag, matchData)); }
		});

		// タグを消去する
		tagsFound = tagsFound.filter(function(foundTag) { return tagsAdded.indexOf('-'+foundTag) === -1; });
		tagsAdded = tagsAdded.filter(function(tag) { return !tag.match(/^-/); });

		// 重複の削除
		var uniqueAry = tagsFound.concat(tagsAdded).filter(function(elem, i, ary) { return ary.indexOf(elem) === i; }).join(' ');

		// ブックマークタグを設定する
		input.value = uniqueAry;

		// タグのハイライトを表示させる
		var keyupEvent = document.createEvent('HTMLEvents');
		keyupEvent.initEvent('keyup', true, true);
		input.dispatchEvent(keyupEvent);
	}
};

window.setTimeout(autoTag, 750);

(function() {
	// 設定ボタンの生成
	var settingsButton = document.createElement('button');
	settingsButton.className = '_button';
	settingsButton.style.marginLeft = '1em';
	settingsButton.id = 'autotag-settings-button';
	settingsButton.textContent = 'タグ自動化設定';
	settingsButton.onclick = toggleSettingsView;

	var target = document.querySelector('#wrapper > div.layout-body > div > section.list-container.tag-container.work-tags-container > div > h1');
	target.parentElement.insertBefore(settingsButton, target.nextSibling);
})();
<commit_msg>bugfix: pattern_allで動かないバグを修正<commit_after>// ==UserScript==
// @name              Pixiv自動ブックマークタグ付け
// @description       Pixivのブックマークタグ付けを半自動化してくれる
// @include           http://www.pixiv.net/bookmark_add.php?type=illust&illust_id=*
// @run-at            document-end
// @version           0.2.0
// ==/UserScript==

// デフォルトルール
var defaultRuleStr = 'private R-18';

// 設定テキストを解析し、連想配列で返す
var parseRules = function(ruleStr) {
	var patternRule    = [];
	var patternAllRule = [];
	var privateRule    = [];
	var errors         = [];

	// 正規表現を表す文字列のリストから、正規表現のリストを作成
	var createRegExpFromStrAry = function(regexpStrAry, lineNumber) {
		var regexps = [];
		regexpStrAry.forEach(function(regexpStr) {
			try { regexps.push(new RegExp(regexpStr)); }
			catch (e) { errors.push({ lineNumber: lineNumber, message: ('RegularExpression Error:' + e.name + ':' + e.massage + ', Str:' + regexpStr) }); }
		});
		return regexps;
	};

	// strに完全一致する正規表現を生成
	var createRegExpPerfectMatch = function(str) {
		return new RegExp('^' + str.replace(/[.*+?^${}()|\[\]\\]/g, '\\$&') + '$');
	};

	ruleStr.split('\n').forEach(function(line, i) {
		var parsed = line.split(/\s+/);
		var matchData;
		var rule;
		if ( parsed.length >= 3 && (matchData = parsed[0].match(/^match(|_all)$/i)) ) {  // 一致
			rule = { tag: parsed[1], regexps: parsed.slice(2).map(createRegExpPerfectMatch) };
		} else if ( parsed.length >= 3 && (matchData = parsed[0].match(/^pattern(|_all)$/i)) ) { // 正規表現
			var regexps = createRegExpFromStrAry(parsed.slice(2), i + 1);
			rule = { tag: parsed[1], regexps: regexps };
		} else if ( parsed.length >= 2 && parsed[0].match(/^private$/i) ) {                     // 非公開タグ
			privateRule.push.apply(privateRule, parsed.slice(1));
			return;
		} else if ( line.match(/^\s*$|^\s*#/) ) {                                               // 空行 or コメント行
			return;
		} else {
			errors.push({ lineNumber: (i+1), message: ('CommandError:Invalid Command or Too Few Arguments, Str:' + line) });
			return;
		}

		Array.prototype.push.call(matchData[1].length === 0 ? patternRule : patternAllRule, rule);
	});
	return { privateRule: privateRule, patternRule: patternRule, patternAllRule: patternAllRule, errors: errors };
};

// matchDataの配列を渡すと文中の~数字をそれで置き換える
var replaceWithMatch = function(input, matchData) {
	return input.split(/(~\d)/).map(function(str) {
		var match = str.match(/^~(\d)/);
		if(match) { return matchData[parseInt(match[1])] || ''; }
		return str;
	}).join('');
};

// 設定画面の生成・消去
var toggleSettingsView = function() {
	// すでに存在していたなら消去
	var settingsView = document.querySelector('#autotag-settings-view');
	if (settingsView) { settingsView.remove(); return; }

	// 保存済みデータの取得
	var ruleStr = window.localStorage.pixivAutoTag_taggingRule || defaultRuleStr;

	// フォームの作成
	settingsView = document.createElement('form');
	settingsView.id = 'autotag-settings-view';
	settingsView.style.backgroundColor = '#FFFFFF';
	settingsView.style.marginTop    = '5px';
	settingsView.style.padding      = '10px 9px';
	settingsView.style.borderRadius = '5px';

	var templateStr  = '
タグ付けルール
<textarea id="autotag-settings-tagging-rule" cols="80" rows="10" style="height:auto;">{{:rule}}</textarea>
';
	settingsView.innerHTML = templateStr.replace('{{:rule}}', ruleStr);

	var buttonsParagraph = document.createElement('p');

	var saveButton = document.createElement('input');
	saveButton.type = 'submit';
	saveButton.className = '_button';
	saveButton.value = '保存';
	settingsView.onsubmit = function() {
		var ruleStr = document.querySelector('#autotag-settings-tagging-rule').value;
		var rule = parseRules(ruleStr);
		if (rule.errors.length === 0) {
			window.localStorage.pixivAutoTag_taggingRule = ruleStr;
			alert('保存しました');
		} else {
			alert(rule.errors.map(function(err) { return '[Error] line: ' + err.lineNumber + ', message: ' + err.message; }).join('\n'));
		}
		return false;
	};
	buttonsParagraph.appendChild(saveButton);

	var cancelButton = document.createElement('input');
	cancelButton.className = '_button';
	cancelButton.type = 'reset';
	cancelButton.value = 'キャンセル';
	// cancelButton.onclick = function() { document.querySelector('#autotag-settings-view').remove(); };
	buttonsParagraph.appendChild(cancelButton);

	settingsView.appendChild(buttonsParagraph);

	var settingsButton = document.querySelector('#autotag-settings-button');
	settingsButton.parentElement.insertBefore(settingsView, settingsButton.nextSibling);
};

// タグの自動追加関数
var autoTag = function() {
	var ruleText = window.localStorage.pixivAutoTag_taggingRule || defaultRuleStr;
	var rule = parseRules(ruleText);

	// 作品タグとタグクラウドの取得
	var tagCloud = Array.prototype.slice.call(document.querySelectorAll('#wrapper > div.layout-body > div > section.list-container.tag-container.tag-cloud-container > ul.list-items.tag-cloud > li')).map(function(item) { return item.textContent; });
	var tagsExist = Array.prototype.concat.apply([], Array.prototype.slice.call(document.querySelectorAll('#wrapper > div.layout-body > div > section.list-container.tag-container.work-tags-container > div > ul > li')).map(function(item) { return item.textContent.replace(/^\*/, '').split('/'); }));

	// 非公開タグが含まれていた場合、自動で非公開に設定
	if (tagsExist.some(function(tag){ return rule.privateRule.indexOf(tag) !== -1; })) {
		document.querySelector('#wrapper > div.layout-body > section > form > div.submit-container > ul > li:nth-child(2) > label').click();
	}

	// ブックマークタグリストの生成
	var input = document.querySelector('#input_tag');
	if (input.value.length === 0) {
		// 作品タグとタグクラウドの共通タグを抽出
		var tagsFound = tagsExist.filter(function(existTag) { return tagCloud.some(function(cloudTag){ return existTag === cloudTag; }); });

		// 付与タグリストの生成
		var tagsAdded = [];
		tagsExist.forEach(function(tag) { // それぞれの作品タグが
			rule.patternRule.forEach(function(patternRule) { // それぞれのルール文に対し
				var matchData = [];
				var foundMatchFlag = patternRule.regexps.some(function(pattern) { // いずれかのパターンに一致するか
					return (matchData = tag.match(pattern));
				});
				if (foundMatchFlag) { tagsAdded.push(replaceWithMatch(patternRule.tag, matchData)); }
			});
		});

		rule.patternAllRule.forEach(function(patternRule) { // それぞれのルール文の
			var matchData = [];
			var foundMatchFlag = patternRule.regexps.every(function(pattern) { // すべてのパターンが
				return tagsExist.some(function(tag) { return (matchData = tag.match(pattern)); }); // いずれかの作品タグに一致するか？
			});
			if (foundMatchFlag) { tagsAdded.push(replaceWithMatch(patternRule.tag, matchData)); }
		});

		// タグを消去する
		tagsFound = tagsFound.filter(function(foundTag) { return tagsAdded.indexOf('-'+foundTag) === -1; });
		tagsAdded = tagsAdded.filter(function(tag) { return !tag.match(/^-/); });

		// 重複の削除
		var uniqueAry = tagsFound.concat(tagsAdded).filter(function(elem, i, ary) { return ary.indexOf(elem) === i; }).join(' ');

		// ブックマークタグを設定する
		input.value = uniqueAry;

		// タグのハイライトを表示させる
		var keyupEvent = document.createEvent('HTMLEvents');
		keyupEvent.initEvent('keyup', true, true);
		input.dispatchEvent(keyupEvent);
	}
};

window.setTimeout(autoTag, 750);

(function() {
	// 設定ボタンの生成
	var settingsButton = document.createElement('button');
	settingsButton.className = '_button';
	settingsButton.style.marginLeft = '1em';
	settingsButton.id = 'autotag-settings-button';
	settingsButton.textContent = 'タグ自動化設定';
	settingsButton.onclick = toggleSettingsView;

	var target = document.querySelector('#wrapper > div.layout-body > div > section.list-container.tag-container.work-tags-container > div > h1');
	target.parentElement.insertBefore(settingsButton, target.nextSibling);
})();
<|endoftext|>


<commit_before>import cockpit from "cockpit";
import QUnit from "qunit-tests";

/* Set this to a regexp to ignore that warning once */
/*
function console_ignore_warning(exp) {
    const console_warn = console.warn;
    console.warn = function() {
        if (!exp.exec(arguments[0]))
            console_warn.apply(console, arguments);
        console.warn = console_warn;
    };
}
*/

QUnit.test("public api", assert => {
    const client = cockpit.http("/test");
    assert.equal(typeof client, "object", "http is an object");
    assert.equal(typeof client.get, "function", "http.get() is a function");
    assert.equal(typeof client.post, "function", "http.post() is a function");
});

const test_server = {
    address: window.location.hostname,
    port: parseInt(window.location.port, 10)
};

QUnit.test("simple request", assert => {
    const done = assert.async();
    assert.expect(1);

    cockpit.http(test_server).get("/pkg/playground/manifest.json")
            .then(data => {
                assert.deepEqual(JSON.parse(data), {
                    requires: {
                        cockpit: "122"
                    },

                    tools: {
                        index: {
                            label: "Development"
                        }
                    },

                    playground: {
                        "react-patterns": {
                            label: "React Patterns"
                        },
                        translate: {
                            label: "Translating"
                        },
                        exception: {
                            label: "Exceptions"
                        },
                        pkgs: {
                            label: "Packages"
                        },
                        preloaded: {
                            label: "Preloaded"
                        },
                        "notifications-receiver": {
                            label: "Notifications Receiver"
                        },
                        metrics: {
                            label: "Monitoring"
                        },
                        plot: {
                            label: "Plots"
                        },
                        service: {
                            label: "Generic Service Monitor"
                        },
                        speed: {
                            label: "Speed Tests"
                        },
                        journal: {
                            label: "Logs Box"
                        },
                        test: {
                            label: "Playground"
                        }
                    },
                    preload: ["preloaded"],
                    "content-security-policy": "img-src 'self' data:"
                }, "returned right data");
            })
            .finally(done);
});

QUnit.test("with params", assert => {
    const done = assert.async();
    assert.expect(1);

    cockpit.http(test_server)
            .get("/mock/qs", { key: "value", name: "Scruffy the Janitor" })
            .then(resp => assert.equal(resp, "key=value&name=Scruffy+the+Janitor", "right query string"))
            .finally(done);
});

QUnit.test("not found", assert => {
    const done = assert.async();
    assert.expect(5);

    cockpit.http(test_server)
            .get("/not/found")
            .response(status => assert.equal(status, 404, "status code"))
            .catch((ex, data) => {
                assert.strictEqual(ex.problem, null, "mapped to cockpit code");
                assert.strictEqual(ex.status, 404, "has status code");
                assert.equal(ex.message, "Not Found", "has reason");
                assert.true(data !== undefined && data.includes('
Not Found
'), "got body");
            })
            .finally(done);
});

QUnit.test("streaming", assert => {
    const done = assert.async();
    assert.expect(3);

    let num_chunks = 0;
    let got = "";
    cockpit.http(test_server)
            .get("/mock/stream")
            .stream(resp => {
                got += resp;
                num_chunks++;
            })
            .finally(() => {
                assert.true(num_chunks > 1, "got at least two chunks");
                assert.true(num_chunks <= 10, "got at most 10 chunks");
                assert.equal(got, "0 1 2 3 4 5 6 7 8 9 ", "stream got right data");
                done();
            });
});

QUnit.test("close", assert => {
    const done = assert.async();
    assert.expect(3);

    let at = 0;
    const http = cockpit.http(test_server);

    http.get("/mock/stream")
            .stream(resp => {
                at += 1;
                assert.equal(resp, "0 ", "first stream part");
                http.close("bad-boy");
            })
            .catch(ex => assert.equal(ex.problem, "bad-boy", "right problem"))
            .finally(() => {
                assert.equal(at, 1, "stream got cancelled");
                done();
            });
});

QUnit.test("close all", assert => {
    const done = assert.async();
    assert.expect(3);

    const http = cockpit.http(test_server);
    const req = http.get("/mock/stream");

    let at = 0;
    req
            .stream(resp => {
                at += 1;
                assert.equal(resp, "0 ", "first stream part");
                http.close("bad-boy");
            })
            .catch(ex => assert.equal(ex.problem, "bad-boy", "right problem"))
            .finally(() => {
                assert.equal(at, 1, "stream got cancelled");
                http.close("closed"); // This should be a no-op now
                done();
            });
});

QUnit.test("headers", assert => {
    const done = assert.async();
    assert.expect(3);

    cockpit.http(test_server)
            .get("/mock/headers", null, { Header1: "booo", Header2: "yay value" })
            .response((status, headers) => {
                assert.equal(status, 201, "status code");
                assert.deepEqual(headers, {
                    Header1: "booo",
                    Header2: "yay value",
                    Header3: "three",
                    Header4: "marmalade",
                    "Referrer-Policy": "no-referrer",
                    "X-DNS-Prefetch-Control": "off",
                    "X-Content-Type-Options": "nosniff",
                    "X-Frame-Options": "sameorigin",
                    "Cross-Origin-Resource-Policy": "same-origin",
                }, "got back headers");
            })
            .then(() => assert.ok(true, "split response succeeded"))
            .finally(done);
});

QUnit.test("escape host header", assert => {
    const done = assert.async();
    assert.expect(3);

    cockpit.http(test_server)
            .get("/mock/host", null, { })
            .response((status, headers) => {
                assert.equal(status, 201, "status code");
                assert.deepEqual(headers.Host, window.location.host, "got back escaped headers");
            })
            .then(() => assert.ok(true, "split response succeeded"))
            .finally(done);
});

QUnit.test("connection headers", assert => {
    const done = assert.async();
    assert.expect(2);

    cockpit.http({ port: test_server.port, headers: { Header1: "booo", Header2: "not this" } })
            .get("/mock/headers", null, { Header2: "yay value", Header0: "extra" })
            .response((status, headers) => {
                assert.equal(status, 201, "status code");
                assert.deepEqual(headers, {
                    Header0: "extra",
                    Header1: "booo",
                    Header2: "yay value",
                    Header3: "three",
                    Header4: "marmalade",
                    "Referrer-Policy": "no-referrer",
                    "X-DNS-Prefetch-Control": "off",
                    "X-Content-Type-Options": "nosniff",
                    "X-Frame-Options": "sameorigin",
                    "Cross-Origin-Resource-Policy": "same-origin",
                }, "got back combined headers");
            })
            .finally(done);
});

QUnit.test("http promise recursive", assert => {
    assert.expect(7);

    const promise = cockpit.http(test_server).get("/");

    const target = { };
    const promise2 = promise.promise(target);
    assert.strictEqual(promise2, target, "used target");
    assert.equal(typeof promise2.done, "function", "promise2.done()");
    assert.equal(typeof promise2.promise, "function", "promise2.promise()");
    assert.equal(typeof promise2.input, "function", "promise2.input()");

    const promise3 = promise2.promise();
    assert.equal(typeof promise3.done, "function", "promise3.done()");
    assert.equal(typeof promise3.promise, "function", "promise3.promise()");
    assert.equal(typeof promise3.input, "function", "promise3.input()");
});

QUnit.test("http keep alive", async assert => {
    assert.expect(1);

    /*
     * The /mock/connection handler returns an identifier that changes if
     * a different connection is used.
     */
    const first = await cockpit.http({ port: test_server.port, connection: "marmalade" }).get("/mock/connection");
    const second = await cockpit.http({ port: test_server.port, connection: "marmalade" }).get("/mock/connection");
    assert.equal(first, second, "same connection");
});

QUnit.test("http connection different", async assert => {
    assert.expect(1);

    /*
     * The /mock/connection handler returns an identifier that changes if
     * a different connection is used.
     */
    const first = await cockpit.http({ port: test_server.port, connection: "one" }).get("/mock/connection");
    const second = await cockpit.http({ port: test_server.port, connection: "two" }).get("/mock/connection");
    assert.notEqual(first, second, "different connection");
});

QUnit.test("http connection without address", async assert => {
    assert.expect(1);

    // Able to reuse connection client info and not specify address again.
    const first = await cockpit.http({ port: test_server.port, connection: "one" }).get("/mock/connection");
    const second = await cockpit.http({ connection: "one" }).get("/mock/connection");
    assert.equal(first, second, "same connection");
});

QUnit.test("no dns address", assert => {
    assert.expect(1);

    assert.rejects(cockpit.http({ port: 8080, address: "the-other-host.example.com" }).get("/"),
                   /* Unfortunately we can see either of these errors when running unit tests */
                   ex => { return ex.problem === "timeout" || ex.problem === "not-found" });
});

QUnit.test("address with params", assert => {
    const done = assert.async();
    assert.expect(1);

    cockpit.http(test_server)
            .get("/mock/qs", { key: "value", name: "Scruffy the Janitor" })
            .then(resp => assert.equal(resp, "key=value&name=Scruffy+the+Janitor", "right query string"))
            .finally(done);
});

QUnit.start();
<commit_msg>base1: Add http-stream2 unit test for invalid channel options<commit_after>import cockpit from "cockpit";
import QUnit from "qunit-tests";

/* Set this to a regexp to ignore that warning once */
/*
function console_ignore_warning(exp) {
    const console_warn = console.warn;
    console.warn = function() {
        if (!exp.exec(arguments[0]))
            console_warn.apply(console, arguments);
        console.warn = console_warn;
    };
}
*/

QUnit.test("public api", assert => {
    const client = cockpit.http("/test");
    assert.equal(typeof client, "object", "http is an object");
    assert.equal(typeof client.get, "function", "http.get() is a function");
    assert.equal(typeof client.post, "function", "http.post() is a function");
});

const test_server = {
    address: window.location.hostname,
    port: parseInt(window.location.port, 10)
};

QUnit.test("simple request", assert => {
    const done = assert.async();
    assert.expect(1);

    cockpit.http(test_server).get("/pkg/playground/manifest.json")
            .then(data => {
                assert.deepEqual(JSON.parse(data), {
                    requires: {
                        cockpit: "122"
                    },

                    tools: {
                        index: {
                            label: "Development"
                        }
                    },

                    playground: {
                        "react-patterns": {
                            label: "React Patterns"
                        },
                        translate: {
                            label: "Translating"
                        },
                        exception: {
                            label: "Exceptions"
                        },
                        pkgs: {
                            label: "Packages"
                        },
                        preloaded: {
                            label: "Preloaded"
                        },
                        "notifications-receiver": {
                            label: "Notifications Receiver"
                        },
                        metrics: {
                            label: "Monitoring"
                        },
                        plot: {
                            label: "Plots"
                        },
                        service: {
                            label: "Generic Service Monitor"
                        },
                        speed: {
                            label: "Speed Tests"
                        },
                        journal: {
                            label: "Logs Box"
                        },
                        test: {
                            label: "Playground"
                        }
                    },
                    preload: ["preloaded"],
                    "content-security-policy": "img-src 'self' data:"
                }, "returned right data");
            })
            .finally(done);
});

QUnit.test("with params", assert => {
    const done = assert.async();
    assert.expect(1);

    cockpit.http(test_server)
            .get("/mock/qs", { key: "value", name: "Scruffy the Janitor" })
            .then(resp => assert.equal(resp, "key=value&name=Scruffy+the+Janitor", "right query string"))
            .finally(done);
});

QUnit.test("not found", assert => {
    const done = assert.async();
    assert.expect(5);

    cockpit.http(test_server)
            .get("/not/found")
            .response(status => assert.equal(status, 404, "status code"))
            .catch((ex, data) => {
                assert.strictEqual(ex.problem, null, "mapped to cockpit code");
                assert.strictEqual(ex.status, 404, "has status code");
                assert.equal(ex.message, "Not Found", "has reason");
                assert.true(data !== undefined && data.includes('
Not Found
'), "got body");
            })
            .finally(done);
});

QUnit.test("streaming", assert => {
    const done = assert.async();
    assert.expect(3);

    let num_chunks = 0;
    let got = "";
    cockpit.http(test_server)
            .get("/mock/stream")
            .stream(resp => {
                got += resp;
                num_chunks++;
            })
            .finally(() => {
                assert.true(num_chunks > 1, "got at least two chunks");
                assert.true(num_chunks <= 10, "got at most 10 chunks");
                assert.equal(got, "0 1 2 3 4 5 6 7 8 9 ", "stream got right data");
                done();
            });
});

QUnit.test("close", assert => {
    const done = assert.async();
    assert.expect(3);

    let at = 0;
    const http = cockpit.http(test_server);

    http.get("/mock/stream")
            .stream(resp => {
                at += 1;
                assert.equal(resp, "0 ", "first stream part");
                http.close("bad-boy");
            })
            .catch(ex => assert.equal(ex.problem, "bad-boy", "right problem"))
            .finally(() => {
                assert.equal(at, 1, "stream got cancelled");
                done();
            });
});

QUnit.test("close all", assert => {
    const done = assert.async();
    assert.expect(3);

    const http = cockpit.http(test_server);
    const req = http.get("/mock/stream");

    let at = 0;
    req
            .stream(resp => {
                at += 1;
                assert.equal(resp, "0 ", "first stream part");
                http.close("bad-boy");
            })
            .catch(ex => assert.equal(ex.problem, "bad-boy", "right problem"))
            .finally(() => {
                assert.equal(at, 1, "stream got cancelled");
                http.close("closed"); // This should be a no-op now
                done();
            });
});

QUnit.test("headers", assert => {
    const done = assert.async();
    assert.expect(3);

    cockpit.http(test_server)
            .get("/mock/headers", null, { Header1: "booo", Header2: "yay value" })
            .response((status, headers) => {
                assert.equal(status, 201, "status code");
                assert.deepEqual(headers, {
                    Header1: "booo",
                    Header2: "yay value",
                    Header3: "three",
                    Header4: "marmalade",
                    "Referrer-Policy": "no-referrer",
                    "X-DNS-Prefetch-Control": "off",
                    "X-Content-Type-Options": "nosniff",
                    "X-Frame-Options": "sameorigin",
                    "Cross-Origin-Resource-Policy": "same-origin",
                }, "got back headers");
            })
            .then(() => assert.ok(true, "split response succeeded"))
            .finally(done);
});

QUnit.test("escape host header", assert => {
    const done = assert.async();
    assert.expect(3);

    cockpit.http(test_server)
            .get("/mock/host", null, { })
            .response((status, headers) => {
                assert.equal(status, 201, "status code");
                assert.deepEqual(headers.Host, window.location.host, "got back escaped headers");
            })
            .then(() => assert.ok(true, "split response succeeded"))
            .finally(done);
});

QUnit.test("connection headers", assert => {
    const done = assert.async();
    assert.expect(2);

    cockpit.http({ port: test_server.port, headers: { Header1: "booo", Header2: "not this" } })
            .get("/mock/headers", null, { Header2: "yay value", Header0: "extra" })
            .response((status, headers) => {
                assert.equal(status, 201, "status code");
                assert.deepEqual(headers, {
                    Header0: "extra",
                    Header1: "booo",
                    Header2: "yay value",
                    Header3: "three",
                    Header4: "marmalade",
                    "Referrer-Policy": "no-referrer",
                    "X-DNS-Prefetch-Control": "off",
                    "X-Content-Type-Options": "nosniff",
                    "X-Frame-Options": "sameorigin",
                    "Cross-Origin-Resource-Policy": "same-origin",
                }, "got back combined headers");
            })
            .finally(done);
});

QUnit.test("http promise recursive", assert => {
    assert.expect(7);

    const promise = cockpit.http(test_server).get("/");

    const target = { };
    const promise2 = promise.promise(target);
    assert.strictEqual(promise2, target, "used target");
    assert.equal(typeof promise2.done, "function", "promise2.done()");
    assert.equal(typeof promise2.promise, "function", "promise2.promise()");
    assert.equal(typeof promise2.input, "function", "promise2.input()");

    const promise3 = promise2.promise();
    assert.equal(typeof promise3.done, "function", "promise3.done()");
    assert.equal(typeof promise3.promise, "function", "promise3.promise()");
    assert.equal(typeof promise3.input, "function", "promise3.input()");
});

QUnit.test("http keep alive", async assert => {
    assert.expect(1);

    /*
     * The /mock/connection handler returns an identifier that changes if
     * a different connection is used.
     */
    const first = await cockpit.http({ port: test_server.port, connection: "marmalade" }).get("/mock/connection");
    const second = await cockpit.http({ port: test_server.port, connection: "marmalade" }).get("/mock/connection");
    assert.equal(first, second, "same connection");
});

QUnit.test("http connection different", async assert => {
    assert.expect(1);

    /*
     * The /mock/connection handler returns an identifier that changes if
     * a different connection is used.
     */
    const first = await cockpit.http({ port: test_server.port, connection: "one" }).get("/mock/connection");
    const second = await cockpit.http({ port: test_server.port, connection: "two" }).get("/mock/connection");
    assert.notEqual(first, second, "different connection");
});

QUnit.test("http connection without address", async assert => {
    assert.expect(1);

    // Able to reuse connection client info and not specify address again.
    const first = await cockpit.http({ port: test_server.port, connection: "one" }).get("/mock/connection");
    const second = await cockpit.http({ connection: "one" }).get("/mock/connection");
    assert.equal(first, second, "same connection");
});

QUnit.test("no dns address", assert => {
    assert.expect(1);

    assert.rejects(cockpit.http({ port: 8080, address: "the-other-host.example.com" }).get("/"),
                   /* Unfortunately we can see either of these errors when running unit tests */
                   ex => { return ex.problem === "timeout" || ex.problem === "not-found" });
});

QUnit.test("address with params", assert => {
    const done = assert.async();
    assert.expect(1);

    cockpit.http(test_server)
            .get("/mock/qs", { key: "value", name: "Scruffy the Janitor" })
            .then(resp => assert.equal(resp, "key=value&name=Scruffy+the+Janitor", "right query string"))
            .finally(done);
});

QUnit.test("wrong options", assert => {
    assert.rejects(
        cockpit.http({}).get("/"),
        // unfortunately cockpit.js does not propagate the detailed error message
        ex => ex.problem == "protocol-error" && ex.status == undefined,
        "rejects request without port or unix option");

    assert.rejects(
        cockpit.http({ port: 1234, unix: "/nonexisting/socket" }).get("/"),
        ex => ex.problem == "protocol-error" && ex.status == undefined,
        "rejects request with both port and unix option");
});

QUnit.start();
<|endoftext|>


<commit_before>import utils from '../src/utils';

describe('clearFormattedCardNumber', () => {
  it('should clear all spaces from card number string', () => {
    expect(utils.clearFormattedCardNumber('1111 2222 3333 4444 555')).toBe('1111222233334444555');
  })
})
<commit_msg>add utils tests<commit_after>import utils from '../src/utils';

describe('utils', () => {
  const card = '1111222233334444555';
  let input;

  beforeEach(() => {
    input = document.createElement('input');
    input.value = card;
    input.focus();
  });

  describe('clearFormattedCardNumber', () => {
    it('should clear all spaces from card number string', () => {
      expect(utils.clearFormattedCardNumber('1111 2222 3333 4444 555')).toBe('1111222233334444555');
    });
  });

  describe('formatCreditCard', () => {
    it('should add space after every four digits in string', () => {
      expect(utils.formatCreditCard('1111222233334444555')).toBe('1111 2222 3333 4444 555');
    });
  });

  describe('setCursorPosition', () => {
    it('should set cursor to given position in passed input', () => {
      const pos = 3;
      expect(input.selectionStart).toBe(0);
      utils.setCursorPosition(input, pos);
      expect(input.selectionStart).toBe(pos);
    });
  });

  describe('getCursorPosition', () => {
    it('should return cursor position in passed input', () => {
      const pos = 4;
      utils.setCursorPosition(input, pos);
      expect(utils.getCursorPosition(input)).toBe(pos);
    });
  });

  describe('formatInputValue', () => {
    it('should add space after every 4 digits in input value and restore cursor position', () => {
      utils.formatInputValue(input);
      expect(input.value).toBe('1111 2222 3333 4444 555');
    })
  })
});
<|endoftext|>