<commit_before>/**
 * Copyright (c) 2013-2015 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint node: true, expr: true */
/* globals describe: false, before: false, it: false */

'use strict';

var expect = require('chai').expect,
    github = require('../../../webapp/lib/github');

xdescribe('lib/github', function() {

    var content = {
        path: 'temp/dummy.md',
        markdown: '# This is a dummy sample\n\nwith dummy content',
        update: '# This is a dummy sample\n\nwith an update'
    };

    it('it should create content', function(done) {
        github.createContent(content.path, content.markdown, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.deep.property('commit.committer.name', 'membabot');
            expect(response).to.have.deep.property('commit.message', 'System creation');
            expect(response).to.have.deep.property('content.path', content.path);
            expect(response).to.have.deep.property('content.html_url');
            expect(response).to.have.deep.property('content.sha');
            content.sha = response.content.sha;
            done();
        });
    });

    it('it should get commits', function(done) {
        github.getCommits(content.path, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.be.instanceof(Array);
            done();
        });
    });

    it('it should get content', function(done) {
        github.getContent(content.path, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.property('path', content.path);
            expect(response).to.have.property('html_url');
            expect(response).to.have.property('sha', content.sha);
            done();
        });
    });

    it('it should update content', function(done) {
        expect(content.sha).not.to.be.undefined;
        github.updateContent(content.path, content.update, content.sha, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.deep.property('commit.committer.name', 'membabot');
            expect(response).to.have.deep.property('commit.message', 'System update');
            expect(response).to.have.deep.property('content.path', content.path);
            expect(response).to.have.deep.property('content.html_url');
            expect(response).to.have.deep.property('content.sha');
            //content.sha changes which each update
            content.sha = response.content.sha;
            done();
        });
    });

    it('it should get commits', function(done) {
        github.getCommits(content.path, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.be.instanceof(Array);
            done();
        });
    });

    it('it should delete content', function(done) {
        expect(content.sha).not.to.be.undefined;
        github.deleteContent(content.path, content.sha, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.deep.property('commit.committer.name', 'membabot');
            expect(response).to.have.deep.property('commit.message', 'System deletion');
            expect(response).to.have.property('content', null);
            done();
        });
    });

    it('it should fail getting deleted content', function(done) {
        github.getContent(content.path, function(error, response) {
            expect(response).to.be.undefined;
            expect(error).to.be.instanceof(Error);
            done();
        });
    });

    //Note: Updating deleted contents works as restoring

});
<commit_msg>Improved and tested github api layer<commit_after>/**
 * Copyright (c) 2013-2015 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint node: true, expr: true */
/* globals describe: false, before: false, it: false */

'use strict';

var expect = require('chai').expect,
    github = require('../../../webapp/lib/github');

describe('lib/github', function() {

    var content = {
        path: 'temp/dummy.md',
        markdown: '# This is a dummy sample\n\nwith dummy content',
        update: '# This is a dummy sample\n\nwith an update'
    };

    it('it should create content', function(done) {
        github.createContent(content.path, content.markdown, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.deep.property('commit.committer.name', 'membabot');
            expect(response).to.have.deep.property('commit.message', 'System creation');
            expect(response).to.have.deep.property('content.path', content.path);
            expect(response).to.have.deep.property('content.html_url');
            expect(response).to.have.deep.property('content.sha');
            content.sha = response.content.sha;
            done();
        });
    });

    it('it should get commits', function(done) {
        github.getCommits(content.path, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.be.instanceof(Array);
            done();
        });
    });

    it('it should get content', function(done) {
        github.getContent(content.path, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.property('path', content.path);
            expect(response).to.have.property('html_url');
            expect(response).to.have.property('sha', content.sha);
            done();
        });
    });

    it('it should update content', function(done) {
        expect(content.sha).not.to.be.undefined;
        github.updateContent(content.path, content.update, content.sha, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.deep.property('commit.committer.name', 'membabot');
            expect(response).to.have.deep.property('commit.message', 'System update');
            expect(response).to.have.deep.property('content.path', content.path);
            expect(response).to.have.deep.property('content.html_url');
            expect(response).to.have.deep.property('content.sha');
            //content.sha changes which each update
            content.sha = response.content.sha;
            done();
        });
    });

    it('it should get commits', function(done) {
        github.getCommits(content.path, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.be.instanceof(Array);
            done();
        });
    });

    it('it should delete content', function(done) {
        expect(content.sha).not.to.be.undefined;
        github.deleteContent(content.path, content.sha, function(error, response) {
            expect(error).to.be.null;
            expect(response).to.have.deep.property('commit.committer.name', 'membabot');
            expect(response).to.have.deep.property('commit.message', 'System deletion');
            expect(response).to.have.property('content', null);
            done();
        });
    });

    it('it should fail getting deleted content', function(done) {
        github.getContent(content.path, function(error, response) {
            expect(response).to.be.undefined;
            expect(error).to.be.instanceof(Error);
            done();
        });
    });

    //Note: Updating deleted contents works as restoring

});
<|endoftext|>


<commit_before>/* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */
/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */

/* eslint-disable no-console */

import async from 'async';
import fs from 'fs';
import path from 'path';
import minimist from 'minimist';
import prompt from 'prompt';
import exec from './command-line-utilities';

const argv = minimist(process.argv.slice(2));
const rootPath = path.resolve(__dirname, '../');

let currentVersionReleaseNotes = '';

console.log(`# Releasing a ${argv.release} tag`);

const executeTasks = () => {
	async.series([
		// Does a remote named upstream exist? Origin should point to fork.
		(done) => {
			console.log('# Checking to see if an upstream remote exists');
			exec({
				command: 'git ls-remote upstream --exit-code --quiet',
				rootPath
			}, done);
		},
		// Checkout master branch
		(done) => {
			console.log('# Checking out master branch. Please ignore "RELEASENOTES.md - Your branch and \'upstream/master\' have diverged."');
			exec({
				command: 'git checkout master',
				rootPath
			}, done);
		},
		// Remove libraries not in package.json
		(done) => {
			console.log('# Pruning NPM dependencies');
			exec({
				command: 'npm prune',
				rootPath
			}, done);
		},
		// npm install
		(done) => {
			console.log('# Running NPM install');
			exec({
				command: 'npm install',
				rootPath
			}, done);
		},
		// Update inline icons
		(done) => {
			console.log('# Build icons from latest icon module');
			exec({
				command: 'npm run icons',
				rootPath
			}, done);
		},
		// Run tests
		(done) => {
			console.log('# Running test suite');
			exec({
				command: 'npm test',
				rootPath,
				verbose: false
			}, done);
		},
		// Update package.json version
		(done) => {
			console.log('# Bumping version in package.json, committing RELEASENOTES.md, and checking that there are no files in local working copy. Published package is based on current state of local files, not versioned files.');
			exec({
				command: `npm --no-git-tag-version version ${argv.release}`,
				rootPath
			}, done);
		},
		// Builds three disconnected git trees based on package.json version and publishes as tags on upstream remote
		(done) => {
			console.log('# Building and publishing tag to upstream remote');
			exec({
				command: 'npm run publish-to-upstream',
				rootPath,
				verbose: false
			}, done);
		},
		// Push to master the package.json and release notes
		(done) => {
			console.log('# Pushing local master branch to upstream remote');
			exec({
				command: 'git push master upstream',
				rootPath
			}, done);
		},
		(done) => {
			console.log('\n\n# Please add the following to your release notes at https://github.com/salesforce-ux/design-system-react/releases');
			console.log(currentVersionReleaseNotes);
			done();
		}
	], (err) => {
		if (err) throw err;
	});
};

const releaseNotesSchema = {
	properties: {
		releasenotes: {
			default: 'y',
			message: 'Have you written release notes (y/n)? \'n\' will open RELEASENOTES.MD.'
		}
	}
};

prompt.start();

prompt.get(releaseNotesSchema, (err, releaseNotesResult) => {
	if (releaseNotesResult.releasenotes.toUpperCase() === 'N') {
		exec({
			command: 'open RELEASENOTES.MD',
			rootPath
		}, () => {});
		console.log('# Please do not commit changes to RELEASENOTES.MD. Unversioned changes must be present in RELEASENOTES.MD or release will fail. Changes will be versioned for you. Please run script again.');
		process.exit();
	} else {
		fs.readFile(path.resolve(rootPath, 'RELEASENOTES.MD'), 'utf8', (err2, contents) => {
			const regEx = /### Latest Release\n*(##.[^]+?)##/g;
			currentVersionReleaseNotes = regEx.exec(contents)[1];
			executeTasks();
		});
	}
});

<commit_msg>Release process: git command typo<commit_after>/* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */
/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */

/* eslint-disable no-console */

import async from 'async';
import fs from 'fs';
import path from 'path';
import minimist from 'minimist';
import prompt from 'prompt';
import exec from './command-line-utilities';

const argv = minimist(process.argv.slice(2));
const rootPath = path.resolve(__dirname, '../');

let currentVersionReleaseNotes = '';

console.log(`# Releasing a ${argv.release} tag`);

const executeTasks = () => {
	async.series([
		// Does a remote named upstream exist? Origin should point to fork.
		(done) => {
			console.log('# Checking to see if an upstream remote exists');
			exec({
				command: 'git ls-remote upstream --exit-code --quiet',
				rootPath
			}, done);
		},
		// Checkout master branch
		(done) => {
			console.log('# Checking out master branch. Please ignore "RELEASENOTES.md - Your branch and \'upstream/master\' have diverged."');
			exec({
				command: 'git checkout master',
				rootPath
			}, done);
		},
		// Remove libraries not in package.json
		(done) => {
			console.log('# Pruning NPM dependencies');
			exec({
				command: 'npm prune',
				rootPath
			}, done);
		},
		// npm install
		(done) => {
			console.log('# Running NPM install');
			exec({
				command: 'npm install',
				rootPath
			}, done);
		},
		// Update inline icons
		(done) => {
			console.log('# Build icons from latest icon module');
			exec({
				command: 'npm run icons',
				rootPath
			}, done);
		},
		// Run tests
		(done) => {
			console.log('# Running test suite');
			exec({
				command: 'npm test',
				rootPath,
				verbose: false
			}, done);
		},
		// Update package.json version
		(done) => {
			console.log('# Bumping version in package.json, committing RELEASENOTES.md, and checking that there are no files in local working copy. Published package is based on current state of local files, not versioned files.');
			exec({
				command: `npm --no-git-tag-version version ${argv.release}`,
				rootPath
			}, done);
		},
		// Builds three disconnected git trees based on package.json version and publishes as tags on upstream remote
		(done) => {
			console.log('# Building and publishing tag to upstream remote');
			exec({
				command: 'npm run publish-to-upstream',
				rootPath,
				verbose: false
			}, done);
		},
		// Push to master the package.json and release notes
		(done) => {
			console.log('# Pushing local master branch to upstream remote');
			exec({
				command: 'git push upstream master',
				rootPath
			}, done);
		},
		(done) => {
			console.log('\n\n# Please add the following to your release notes at https://github.com/salesforce-ux/design-system-react/releases');
			console.log(currentVersionReleaseNotes);
			done();
		}
	], (err) => {
		if (err) throw err;
	});
};

const releaseNotesSchema = {
	properties: {
		releasenotes: {
			default: 'y',
			message: 'Have you written release notes (y/n)? \'n\' will open RELEASENOTES.MD.'
		}
	}
};

prompt.start();

prompt.get(releaseNotesSchema, (err, releaseNotesResult) => {
	if (releaseNotesResult.releasenotes.toUpperCase() === 'N') {
		exec({
			command: 'open RELEASENOTES.MD',
			rootPath
		}, () => {});
		console.log('# Please do not commit changes to RELEASENOTES.MD. Unversioned changes must be present in RELEASENOTES.MD or release will fail. Changes will be versioned for you. Please run script again.');
		process.exit();
	} else {
		fs.readFile(path.resolve(rootPath, 'RELEASENOTES.MD'), 'utf8', (err2, contents) => {
			const regEx = /### Latest Release\n*(##.[^]+?)##/g;
			currentVersionReleaseNotes = regEx.exec(contents)[1];
			executeTasks();
		});
	}
});

<|endoftext|>


<commit_before>const {resolve} = require('path');
const {execFile} = require('child_process');
const {readFileSync} = require('fs');

const tape = require('tape-catch');
const curry = require('1-liners/curry');
const plus = require('1-liners/plus');
const rimraf = require('rimraf');

const title = curry(plus)('The CLI tool:  ');
const lessIndex = resolve(__dirname, '../../module/bin/less-index.js');
const $lessIndex = curry(execFile)(lessIndex);

const cwd = resolve(__dirname, '../mock-cwd');

tape(title('Prints usage'), (is) => {
  is.plan(10);

  $lessIndex([], (error, _, stderr) => {
    is.equal(error && error.code, 1,
      '`less-index` fails…'
    );

    is.ok(
      /^usage:/i.test(stderr),
      '…and prints usage to stderr'
    );
  });

  $lessIndex(['--invalid', '--options'], (error, _, stderr) => {
    is.equal(error && error.code, 1,
      '`less-index --invalid --options` fails…'
    );

    is.ok(
      /^usage:/i.test(stderr),
      '…and prints usage to stderr'
    );
  });

  $lessIndex(['--invalid', '--options', 'a'], {cwd}, (
    error, _, stderr
  ) => {
    is.equal(error && error.code, 1,
      '`less-index --invalid --options <directory>` fails…'
    );

    is.ok(
      /^usage:/i.test(stderr),
      '…and prints usage to stderr'
    );
  });

  $lessIndex(['-h'], (error, stdout) => {
    is.equal(error, null,
      '`less-index -h` succeeds…'
    );

    is.ok(
      /^usage:/i.test(stdout),
      '…and prints usage'
    );
  });

  $lessIndex(['--help'], (error, stdout) => {
    is.equal(error, null,
      '`less-index --help` succeeds…'
    );

    is.ok(
      /SYNOPSIS/.test(stdout),
      '…and prints manpage-like help'
    );
  });
});

tape(title('Works for a single directory.'), (is) => {
  is.plan(4);
  is.timeoutAfter(500);

  $lessIndex(['a'], {cwd}, (error, stdout) => {
    is.notOk(error,
      'succeeds'
    );

    is.ok(
      /written .*\.less/i.test(stdout),
      'prints a helpful message'
    );

    let file;
    is.doesNotThrow(
      () => file = readFileSync(resolve(cwd, 'a.less'), 'utf-8'),
      'creates the right file'
    );

    is.equal(file,
      ['b', 'c', 'f']
        .map((name) => `@import "./a/${name}";\n`)
        .join('')
      ,
      '…with the right content'
    );

    rimraf(resolve(cwd, 'a.less'),
      () => is.end()
    );
  });
});

tape(title('Works for multiple directories.'), (is) => {
  is.plan(4);
  is.timeoutAfter(500);

  $lessIndex(['a', './b'], {cwd}, (error, stdout) => {
    is.notOk(error,
      'succeeds'
    );

    is.ok(
      /(?:written .*\.less[^]*){2}/i.test(stdout),
      'prints helpful messages'
    );

    let fileA;
    let fileB;
    is.doesNotThrow(
      () => {
        fileA = readFileSync(resolve(cwd, 'a.less'), 'utf-8');
        fileB = readFileSync(resolve(cwd, 'b.less'), 'utf-8');
      },
      'creates the right files'
    );

    is.equal(fileB,
      '@import "./b/c";\n',
      '…with the right content'
    );

    rimraf(resolve(cwd, '{a,b}.less'),
      () => is.end()
    );
  });
});
<commit_msg>Refactor<commit_after>const {resolve} = require('path');
const {execFile} = require('child_process');
const {readFileSync} = require('fs');

const test = require('tape-catch');
const curry = require('1-liners/curry');
const plus = require('1-liners/plus');
const rimraf = require('rimraf');

const title = curry(plus)('The CLI tool:  ');
const lessIndex = resolve(__dirname, '../../module/bin/less-index.js');
const $lessIndex = curry(execFile)(lessIndex);

const cwd = resolve(__dirname, '../mock-cwd');

test(title('Prints usage'), (is) => {
  is.plan(10);

  $lessIndex([], (error, _, stderr) => {
    is.equal(error && error.code, 1,
      '`less-index` fails…'
    );

    is.ok(
      /^usage:/i.test(stderr),
      '…and prints usage to stderr'
    );
  });

  $lessIndex(['--invalid', '--options'], (error, _, stderr) => {
    is.equal(error && error.code, 1,
      '`less-index --invalid --options` fails…'
    );

    is.ok(
      /^usage:/i.test(stderr),
      '…and prints usage to stderr'
    );
  });

  $lessIndex(['--invalid', '--options', 'a'], {cwd}, (
    error, _, stderr
  ) => {
    is.equal(error && error.code, 1,
      '`less-index --invalid --options <directory>` fails…'
    );

    is.ok(
      /^usage:/i.test(stderr),
      '…and prints usage to stderr'
    );
  });

  $lessIndex(['-h'], (error, stdout) => {
    is.equal(error, null,
      '`less-index -h` succeeds…'
    );

    is.ok(
      /^usage:/i.test(stdout),
      '…and prints usage'
    );
  });

  $lessIndex(['--help'], (error, stdout) => {
    is.equal(error, null,
      '`less-index --help` succeeds…'
    );

    is.ok(
      /SYNOPSIS/.test(stdout),
      '…and prints manpage-like help'
    );
  });
});

test(title('Works for a single directory.'), (is) => {
  is.plan(4);
  is.timeoutAfter(500);

  $lessIndex(['a'], {cwd}, (error, stdout) => {
    is.notOk(error,
      'succeeds'
    );

    is.ok(
      /written .*\.less/i.test(stdout),
      'prints a helpful message'
    );

    let file;
    is.doesNotThrow(
      () => file = readFileSync(resolve(cwd, 'a.less'), 'utf-8'),
      'creates the right file'
    );

    is.equal(file,
      ['b', 'c', 'f']
        .map((name) => `@import "./a/${name}";\n`)
        .join('')
      ,
      '…with the right content'
    );

    rimraf(resolve(cwd, 'a.less'),
      () => is.end()
    );
  });
});

test(title('Works for multiple directories.'), (is) => {
  is.plan(4);
  is.timeoutAfter(500);

  $lessIndex(['a', './b'], {cwd}, (error, stdout) => {
    is.notOk(error,
      'succeeds'
    );

    is.ok(
      /(?:written .*\.less[^]*){2}/i.test(stdout),
      'prints helpful messages'
    );

    let fileA;
    let fileB;
    is.doesNotThrow(
      () => {
        fileA = readFileSync(resolve(cwd, 'a.less'), 'utf-8');
        fileB = readFileSync(resolve(cwd, 'b.less'), 'utf-8');
      },
      'creates the right files'
    );

    is.equal(fileB,
      '@import "./b/c";\n',
      '…with the right content'
    );

    rimraf(resolve(cwd, '{a,b}.less'),
      () => is.end()
    );
  });
});
<|endoftext|>


<commit_before>/* Copyright 2012 The Go Authors.   All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
'use strict';

/* Services */

angular.module('tour.services', []).

// Google Analytics
factory('analytics', ['$window',
    function(win) {
        var track = win.trackPageview || (function() {});
        return {
            trackView: track
        };
    }
]).

// Internationalization
factory('i18n', ['translation',
    function(translation) {
        return {
            l: function(key) {
                if (translation[key]) return translation[key];
                return '(no translation for ' + key + ')';
            }
        };
    }
]).

// Running code
factory('run', ['$window',
    function(win) {
        return function(code, output, options) {
            // PlaygroundOutput is defined in playground.js which is prepended
            // to the generated script.js in gotour/tour.go.
            // The next line removes the jshint warning.
            // global PlaygroundOutput
            win.transport.Run(code, PlaygroundOutput(output), options);
        };
    }
]).

// Formatting code
factory('fmt', ['$http',
    function($http) {
        return function(body) {
            var params = $.param({
                'body': body
            });
            var headers = {
                'Content-Type': 'application/x-www-form-urlencoded'
            };
            return $http.post('/fmt', params, {
                headers: headers
            });
        };
    }
]).

factory('storage', ['$window',
    function(win) {
        if (win.localStorage) {
            return {
                get: function(key) {
                    return win.localStorage.getItem(key);
                },
                set: function(key, val) {
                    win.localStorage.setItem(key, val);
                }
            };
        }
        return {
            get: function(key, def) {
                return def;
            },
            set: function() {}
        };
    }
]).

// Editor context service, kept through the whole app.
factory('editor', ['$window', 'storage',
    function(win, storage) {
        var ctx = {
            syntax: storage.get('syntax') === 'true',
            toggleSyntax: function() {
                ctx.syntax = !ctx.syntax;
                storage.set('syntax', ctx.syntax);
                ctx.paint();
            },
            paint: function() {
                var mode = ctx.syntax && 'text/x-go' || 'text/x-go-comment';
                // Wait for codemirror to start.
                var set = function() {
                    if ($('.CodeMirror').length > 0) {
                        var cm = $('.CodeMirror')[0].CodeMirror;
                        if (cm.getOption('mode') == mode) {
                            cm.refresh();
                            return;
                        }
                        cm.setOption('mode', mode);
                    }
                    win.setTimeout(set, 10);
                };
                set();
            },
        };
        return ctx;
    }
]).

// Table of contents management and navigation
factory('toc', ['$http', '$q', '$log', 'tableOfContents',
    function($http, $q, $log, tableOfContents) {
        var modules = tableOfContents;

        var lessons = {};

        var prevLesson = function(id) {
            var mod = lessons[id].module;
            var idx = mod.lessons.indexOf(id);
            if (idx < 0) return '';
            if (idx > 0) return mod.lessons[idx - 1];

            idx = modules.indexOf(mod);
            if (idx <= 0) return '';
            mod = modules[idx - 1];
            return mod.lessons[mod.lessons.length - 1];
        };

        var nextLesson = function(id) {
            var mod = lessons[id].module;
            var idx = mod.lessons.indexOf(id);
            if (idx < 0) return '';
            if (idx + 1 < mod.lessons.length) return mod.lessons[idx + 1];

            idx = modules.indexOf(mod);
            if (idx < 0 || modules.length <= idx + 1) return '';
            mod = modules[idx + 1];
            return mod.lessons[0];
        };

        $http.get('/lesson/').then(
            function(data) {
                lessons = data.data;
                for (var m = 0; m < modules.length; m++) {
                    var module = modules[m];
                    module.lesson = {};
                    for (var l = 0; l < modules[m].lessons.length; l++) {
                        var lessonName = module.lessons[l];
                        var lesson = lessons[lessonName];
                        lesson.module = module;
                        module.lesson[lessonName] = lesson;
                    }
                }
                moduleQ.resolve(modules);
                lessonQ.resolve(lessons);
            }, function(error) {
                $log.error('error loading lessons : ', error);
                moduleQ.reject(error);
                lessonQ.reject(error);
            }
        );

        var moduleQ = $q.defer();
        var lessonQ = $q.defer();

        return {
            modules: moduleQ.promise,
            lessons: lessonQ.promise,
            prevLesson: prevLesson,
            nextLesson: nextLesson
        };
    }
]);
<commit_msg>[x/tour] go-tour: fix storage when localStorage is not available in the browser.<commit_after>/* Copyright 2012 The Go Authors.   All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
'use strict';

/* Services */

angular.module('tour.services', []).

// Google Analytics
factory('analytics', ['$window',
    function(win) {
        var track = win.trackPageview || (function() {});
        return {
            trackView: track
        };
    }
]).

// Internationalization
factory('i18n', ['translation',
    function(translation) {
        return {
            l: function(key) {
                if (translation[key]) return translation[key];
                return '(no translation for ' + key + ')';
            }
        };
    }
]).

// Running code
factory('run', ['$window',
    function(win) {
        return function(code, output, options) {
            // PlaygroundOutput is defined in playground.js which is prepended
            // to the generated script.js in gotour/tour.go.
            // The next line removes the jshint warning.
            // global PlaygroundOutput
            win.transport.Run(code, PlaygroundOutput(output), options);
        };
    }
]).

// Formatting code
factory('fmt', ['$http',
    function($http) {
        return function(body) {
            var params = $.param({
                'body': body
            });
            var headers = {
                'Content-Type': 'application/x-www-form-urlencoded'
            };
            return $http.post('/fmt', params, {
                headers: headers
            });
        };
    }
]).

// Local storage, persistent to page refreshing.
factory('storage', ['$window',
    function(win) {
        if (win.localStorage) {
            return {
                get: function(key) {
                    return win.localStorage.getItem(key);
                },
                set: function(key, val) {
                    win.localStorage.setItem(key, val);
                }
            };
        }
        return {
            get: function() {
                return null;
            },
            set: function() {}
        };
    }
]).

// Editor context service, kept through the whole app.
factory('editor', ['$window', 'storage',
    function(win, storage) {
        var ctx = {
            syntax: storage.get('syntax') === 'true',
            toggleSyntax: function() {
                ctx.syntax = !ctx.syntax;
                storage.set('syntax', ctx.syntax);
                ctx.paint();
            },
            paint: function() {
                var mode = ctx.syntax && 'text/x-go' || 'text/x-go-comment';
                // Wait for codemirror to start.
                var set = function() {
                    if ($('.CodeMirror').length > 0) {
                        var cm = $('.CodeMirror')[0].CodeMirror;
                        if (cm.getOption('mode') == mode) {
                            cm.refresh();
                            return;
                        }
                        cm.setOption('mode', mode);
                    }
                    win.setTimeout(set, 10);
                };
                set();
            },
        };
        return ctx;
    }
]).

// Table of contents management and navigation
factory('toc', ['$http', '$q', '$log', 'tableOfContents',
    function($http, $q, $log, tableOfContents) {
        var modules = tableOfContents;

        var lessons = {};

        var prevLesson = function(id) {
            var mod = lessons[id].module;
            var idx = mod.lessons.indexOf(id);
            if (idx < 0) return '';
            if (idx > 0) return mod.lessons[idx - 1];

            idx = modules.indexOf(mod);
            if (idx <= 0) return '';
            mod = modules[idx - 1];
            return mod.lessons[mod.lessons.length - 1];
        };

        var nextLesson = function(id) {
            var mod = lessons[id].module;
            var idx = mod.lessons.indexOf(id);
            if (idx < 0) return '';
            if (idx + 1 < mod.lessons.length) return mod.lessons[idx + 1];

            idx = modules.indexOf(mod);
            if (idx < 0 || modules.length <= idx + 1) return '';
            mod = modules[idx + 1];
            return mod.lessons[0];
        };

        $http.get('/lesson/').then(
            function(data) {
                lessons = data.data;
                for (var m = 0; m < modules.length; m++) {
                    var module = modules[m];
                    module.lesson = {};
                    for (var l = 0; l < modules[m].lessons.length; l++) {
                        var lessonName = module.lessons[l];
                        var lesson = lessons[lessonName];
                        lesson.module = module;
                        module.lesson[lessonName] = lesson;
                    }
                }
                moduleQ.resolve(modules);
                lessonQ.resolve(lessons);
            }, function(error) {
                $log.error('error loading lessons : ', error);
                moduleQ.reject(error);
                lessonQ.reject(error);
            }
        );

        var moduleQ = $q.defer();
        var lessonQ = $q.defer();

        return {
            modules: moduleQ.promise,
            lessons: lessonQ.promise,
            prevLesson: prevLesson,
            nextLesson: nextLesson
        };
    }
]);
<|endoftext|>


<commit_before>const redis = require('./redis');
const config = require('../config');
const { getVehiclesInRange } = require('./vehicles');

const getNeed = async needId => {
  // Set TTL for need
  redis.expire(`needs:${needId}`, config('needs_ttl'));
  return await redis.hgetallAsync(`needs:${needId}`);
};

const createNeed = async needDetails => {
  // get new unique id for need
  const needId = await redis.incrAsync('next_need_id');
  const key_value_array = [].concat(...Object.entries(needDetails));
  redis.hmsetAsync(`needs:${needId}`, ...key_value_array);

  // See if there are any vehicles around the pickup position, if not a few vehicles will be generated there
  getVehiclesInRange({ lat: parseFloat(needDetails.pickup_latitude), long: parseFloat(needDetails.pickup_longitude) }, 7000);

  // Set TTL for need
  redis.expire(`needs:${needId}`, config('needs_ttl'));
  return needId;
};

const deleteNeed = async needId => {
  return await redis.del(`needs:${needId}`);
};

module.exports = {
  createNeed,
  getNeed,
  deleteNeed,
};
<commit_msg>issue #155 : Refactor setting TTL in need.js<commit_after>const redis = require('./redis');
const config = require('../config');
const { getVehiclesInRange } = require('./vehicles');

const getNeed = async needId => {
  // Set TTL for need
  setNeedTTL(needId);
  return await redis.hgetallAsync(`needs:${needId}`);
};

const createNeed = async needDetails => {
  // get new unique id for need
  const needId = await redis.incrAsync('next_need_id');
  const key_value_array = [].concat(...Object.entries(needDetails));
  redis.hmsetAsync(`needs:${needId}`, ...key_value_array);

  // See if there are any vehicles around the pickup position, if not a few vehicles will be generated there
  getVehiclesInRange({ lat: parseFloat(needDetails.pickup_latitude), long: parseFloat(needDetails.pickup_longitude) }, 7000);

  // Set TTL for need
  setNeedTTL(needId);
  return needId;
};

const deleteNeed = async needId => {
  return await redis.del(`needs:${needId}`);
};

const setNeedTTL = async needId => redis.expire(`needs:${needId}`, config('needs_ttl'));

module.exports = {
  createNeed,
  getNeed,
  deleteNeed,
};
<|endoftext|>


<commit_before>var expect = require('chai').expect;
var ClientsManager = require('../../src/ClientsManager');

var ArgumentError = require('../../src/exceptions').ArgumentError;
var domains = require('../../src/constants').DOMAINS_BY_REGION;

describe('ClientsManager', function () {

  describe('#constructor', function () {

    it('should error when no options are provided', function () {
      expect(ClientsManager).to.throw(ArgumentError, 'Must provide client options');
    });

    it('should error when the first argument is not an object', function () {
      expect(ClientsManager.bind(null, 1)).to.throw(ArgumentError, 'Must provide client options');
    });
  });
});
<commit_msg>Add more tests for the ClientsManager class<commit_after><|endoftext|>


<commit_before>/**
 * Copyright (C) 2014 yanni4night.com
 * p.js
 *
 * changelog
 * 2014-11-30[16:05:07]:revised
 * 2014-12-01[10:57:13]:better invoke
 * 2014-12-02[10:17:14]:add P.reject
 *
 * @author yanni4night@gmail.com
 * @version 0.1.2
 * @since 0.1.0
 */

(function(global, factory) {
    'use strict';
    if ('undefined' !== typeof define && define.amd) {
        define(factory);
    } else if ('undefined' !== typeof module && module.exports) {
        module.exports = factory();
    } else {
        global.P = factory();
    }
})(this, function() {
    'use strict';
    var noop = function(args) {
        return args;
    };

    var STRFUNC = typeof noop;
    var STATE_PENDING = 'pending';
    var STATE_FULFILLED = 'fulfilled';
    var STATE_REJECTED = 'rejected';

    var isFunction = function(obj) {
        return STRFUNC === typeof obj;
    };

    /**
     * Promise constructor.
     *
     * @param {Function} func
     * @class
     * @since 0.1.0
     */
    var P = function(func) {
        this.state = STATE_PENDING;
        var fns = [];
        var value;

        if (!isFunction(func)) {
            throw new TypeError('Promise resolver ' + func + ' is not a function');
        }

        /**
         * Trigger events
         * @since 0.1.0
         */
        var trigger = function() {
            var fn;

            if (STATE_PENDING === this.state) {
                return;
            }

            while ((fn = fns.shift())) {
                //resolve&reject always exists
                if (STATE_FULFILLED === this.state) {
                    fn.resolve(fn.onFulfilled.call(null, value));
                } else if (STATE_REJECTED === this.state) {
                    fn.reject(fn.onRejected.call(null, value));
                }
            }

        }.bind(this);

        /**
         * Change state to fulfilled.
         *
         * @param  {Mixin} data
         * @since 0.1.0
         */
        var resolve = function(data) {
            value = data;
            if (STATE_PENDING === this.state) {
                this.state = STATE_FULFILLED;
            }
            trigger();
        }.bind(this);

        /**
         * Change state to rejected.
         *
         * @param  {Mixin} reason
         * @since 0.1.0
         */
        var reject = function(reason) {
            value = reason;
            if (STATE_PENDING === this.state) {
                this.state = STATE_REJECTED;
            }
            trigger();
        }.bind(this);
        /**
         *
         * @param  {Function} onFulfilled
         * @param  {Function} onRejected
         * @return {Promise}
         */
        this.then = function(onFulfilled, onRejected) {
            var self = this;
            return new P(function(resolve) {
                fns.push({
                    onFulfilled: isFunction(onFulfilled) ? onFulfilled : noop,
                    onRejected: isFunction(onRejected) ? onRejected : noop,
                    resolve: isFunction(resolve) ? resolve : noop,
                    reject: isFunction(resolve) ? resolve : noop
                });
                if (STATE_PENDING !== self.state) {
                    trigger();
                }
            });
        };
        /**
         * @param  {Function} onRejected
         * @return {Promise}
         */
        this.catch = function(onRejected) {
            var self = this;
            return new P(function(resolve) {
                fns.push({
                    onFulfilled: noop,
                    onRejected: isFunction(onRejected) ? onRejected : noop,
                    resolve: isFunction(resolve) ? resolve : noop,
                    reject: isFunction(resolve) ? resolve : noop
                });
                if (STATE_PENDING !== self.state) {
                    trigger();
                }
            });
        };

        setTimeout(function() {
            func(resolve, reject);
        });
    };
    /**
     * Resolve an object to a Promise object.
     *
     * @param  {Mixin} obj
     * @return {Promise}
     * @since 0.1.0
     */
    P.resolve = function(value) {
        if (value instanceof P) {
            //Return a new promise follow the value if it's thenable
            return new P(function(resolve, reject) {
                value.then(resolve, reject);
            });
        } else {
            return new P(function(resolve) {
                resolve(value);
            });
        }
    };

    /**
     * @param  {Mixin} reason
     * @return {Promise}
     * @since 0.2.0
     */
    P.reject = function(reason) {
        //Treat as a reason even reason is thenable
        return new P(function(resolve, reject) {
            reject(reason);
        });
    };

    /**
     * @param  {Array} sequence
     * @return {Promise}
     * @since 0.1.0
     */
    P.race = function(sequence) {
        var qs = Array.prototype.map.call(sequence, P.resolve, P);
        return new P(function(resolve, reject) {
            if (!qs.length) {
                resolve();
            } else {
                qs.forEach(function(q) {
                    q.then(resolve, reject);
                });
            }
        });
    };
    /**
     * @param  {Array} sequence
     * @return {Promise}
     * @since 0.1.0
     */
    P.all = function(sequence) {
        var qs = Array.prototype.map.call(sequence, P.resolve, P);
        return new P(function(resolve, reject) {
            var resolveCnt = 0,
                ret = [];
            var singleResolve = function(idx, data) {
                ret[idx] = data;
                if (qs.length === ++resolveCnt) {
                    resolve(ret);
                }
                return data;
            };

            if (!qs.length) {
                resolve(ret);
            } else {
                qs.forEach(function(q, idx) {
                    q.then((function(idx) {
                        return singleResolve.bind(null, idx);
                    })(idx), reject);
                });
            }
        });
    };

    return P;
});<commit_msg>use setImmediate if possible<commit_after>/**
 * Copyright (C) 2014 yanni4night.com
 * p.js
 *
 * changelog
 * 2014-11-30[16:05:07]:revised
 * 2014-12-01[10:57:13]:better invoke
 * 2014-12-02[10:17:14]:add P.reject
 *
 * @author yanni4night@gmail.com
 * @version 0.1.2
 * @since 0.1.0
 */

(function(global, factory) {
    'use strict';
    if ('undefined' !== typeof define && define.amd) {
        define(factory);
    } else if ('undefined' !== typeof module && module.exports) {
        module.exports = factory();
    } else {
        global.P = factory();
    }
})(this, function() {
    'use strict';
    var noop = function(args) {
        return args;
    };

    var STRFUNC = typeof noop;
    var STATE_PENDING = 'pending';
    var STATE_FULFILLED = 'fulfilled';
    var STATE_REJECTED = 'rejected';

    var isFunction = function(obj) {
        return STRFUNC === typeof obj;
    };

    var asap = 'undefined' === typeof setImmediate ? setTimeout : setImmediate;

    /**
     * Promise constructor.
     *
     * @param {Function} func
     * @class
     * @since 0.1.0
     */
    var P = function(func) {
        this.state = STATE_PENDING;
        var fns = [];
        var value;

        if (!isFunction(func)) {
            throw new TypeError('Promise resolver ' + func + ' is not a function');
        }

        /**
         * Trigger events
         * @since 0.1.0
         */
        var trigger = function() {
            var fn;

            if (STATE_PENDING === this.state) {
                return;
            }

            while ((fn = fns.shift())) {
                //resolve&reject always exists
                if (STATE_FULFILLED === this.state) {
                    fn.resolve(fn.onFulfilled.call(null, value));
                } else if (STATE_REJECTED === this.state) {
                    fn.reject(fn.onRejected.call(null, value));
                }
            }

        }.bind(this);

        /**
         * Change state to fulfilled.
         *
         * @param  {Mixin} data
         * @since 0.1.0
         */
        var resolve = function(data) {
            value = data;
            if (STATE_PENDING === this.state) {
                this.state = STATE_FULFILLED;
            }
            trigger();
        }.bind(this);

        /**
         * Change state to rejected.
         *
         * @param  {Mixin} reason
         * @since 0.1.0
         */
        var reject = function(reason) {
            value = reason;
            if (STATE_PENDING === this.state) {
                this.state = STATE_REJECTED;
            }
            trigger();
        }.bind(this);
        /**
         *
         * @param  {Function} onFulfilled
         * @param  {Function} onRejected
         * @return {Promise}
         */
        this.then = function(onFulfilled, onRejected) {
            var self = this;
            return new P(function(resolve) {
                fns.push({
                    onFulfilled: isFunction(onFulfilled) ? onFulfilled : noop,
                    onRejected: isFunction(onRejected) ? onRejected : noop,
                    resolve: isFunction(resolve) ? resolve : noop,
                    reject: isFunction(resolve) ? resolve : noop
                });
                if (STATE_PENDING !== self.state) {
                    trigger();
                }
            });
        };
        /**
         * @param  {Function} onRejected
         * @return {Promise}
         */
        this.catch = function(onRejected) {
            var self = this;
            return new P(function(resolve) {
                fns.push({
                    onFulfilled: noop,
                    onRejected: isFunction(onRejected) ? onRejected : noop,
                    resolve: isFunction(resolve) ? resolve : noop,
                    reject: isFunction(resolve) ? resolve : noop
                });
                if (STATE_PENDING !== self.state) {
                    trigger();
                }
            });
        };

        asap(function() {
            func(resolve, reject);
        });
    };
    /**
     * Resolve an object to a Promise object.
     *
     * @param  {Mixin} obj
     * @return {Promise}
     * @since 0.1.0
     */
    P.resolve = function(value) {
        if (value instanceof P) {
            //Return a new promise follow the value if it's thenable
            return new P(function(resolve, reject) {
                value.then(resolve, reject);
            });
        } else {
            return new P(function(resolve) {
                resolve(value);
            });
        }
    };

    /**
     * @param  {Mixin} reason
     * @return {Promise}
     * @since 0.2.0
     */
    P.reject = function(reason) {
        //Treat as a reason even reason is thenable
        return new P(function(resolve, reject) {
            reject(reason);
        });
    };

    /**
     * @param  {Array} sequence
     * @return {Promise}
     * @since 0.1.0
     */
    P.race = function(sequence) {
        var qs = Array.prototype.map.call(sequence, P.resolve, P);
        return new P(function(resolve, reject) {
            if (!qs.length) {
                resolve();
            } else {
                qs.forEach(function(q) {
                    q.then(resolve, reject);
                });
            }
        });
    };
    /**
     * @param  {Array} sequence
     * @return {Promise}
     * @since 0.1.0
     */
    P.all = function(sequence) {
        var qs = Array.prototype.map.call(sequence, P.resolve, P);
        return new P(function(resolve, reject) {
            var resolveCnt = 0,
                ret = [];
            var singleResolve = function(idx, data) {
                ret[idx] = data;
                if (qs.length === ++resolveCnt) {
                    resolve(ret);
                }
                return data;
            };

            if (!qs.length) {
                resolve(ret);
            } else {
                qs.forEach(function(q, idx) {
                    q.then((function(idx) {
                        return singleResolve.bind(null, idx);
                    })(idx), reject);
                });
            }
        });
    };

    return P;
});<|endoftext|>


<commit_before>var joi = require('joi');
var should = require('should');
var authenticate = require('../index')({
    models: {
        acode:      {dbPath: 'auth_acode'},
        atoken:     {dbPath: 'auth_atoken'},
        aukey:      {dbPath: 'auth_aukey'},
        decision:   {dbPath: 'auth_decision'},
        md5key:     {dbPath: 'auth_md5key'},
        openkey:    {dbPath: 'auth_openkey'},
        regref:     {dbPath: 'auth_regref'},
        rsa:        {dbPath: 'auth_rsa'},
        salt:       {dbPath: 'auth_salt'},
        secret:     {dbPath: 'auth_secret'},
        userkey:    {dbPath: 'auth_userkey'}
    }
});

describe('B2B Client', function () {
    var registration = new authenticate.registration();

    var regEmail = 'test_{{rand}}@example.com'.replace('{{rand}}', Math.random().toString(16).slice(2));
    var regRef;
    var tokenState;
    var myAtoken;
    var myAukey;
    var myOpenkey;
    var myUserkey;
    var myAukeySecret;
    var myOpenkeySecret;
    var myUserkey;

    it('Should Create a client account', function (done) {
        registration.newUser(regEmail, function (err, result) {
            should(err).be.empty;

            should.exist(result);

            var regRespSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                scope: joi.array().items(joi.string()).required(),
                expires: joi.number().required(),
                created: joi.number().required(),
                status: joi.string().valid('pending', 'fulfilled', 'paused', 'error', 'expired', 'cancelled'),
                state: {
                    _id: joi.string(),
                    _rev: joi.string(),
                    email: joi.string().email().required(),
                    token: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                    salt: joi.string().required(),
                    relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                    expires: joi.number().required(),
                    scope: joi.array().items(joi.string()).required()
                }
            });

            regRespSchema.validate(result, function (err, result) {
                should(err).be.empty;
                should.exist(result);
                regRef = result;
                done();
            });
        });
    });

    it('Should get the created registration state', function (done) {

        registration.get(regRef.key, function (err, regState) {
            should(err).be.empty;

            should.exist(regState);

            var regRespSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                email: joi.string().email().required(),
                token: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                salt: joi.string().required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                expires: joi.number().required(),
                scope: joi.array().items(joi.string()).required()
            });

            regRespSchema.validate(regState, function (err, regState) {
                should(err).be.empty;
                should.exist(regState);

                tokenState = regState;

                done();
            });
        });
    });

    it('Should validate the fetched token', function (done) {
        authenticate.validation({
            accessToken: tokenState.token,
            uniqueKey: tokenState.relkey,
            scope: tokenState.scope
        }, function (err, atoken) {
            should(err).be.empty;

            should.exist(atoken);

            var atokenSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                salt: joi.string().required(),
                uniqueKey: joi.string().required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                expires: joi.number().required(),
                created: joi.number().required(),
                scope: joi.array().items(joi.string()).required()
            });

            atokenSchema.validate(atoken, function (err, atoken) {
                should(err).be.empty;
                should.exist(atoken);

                done();
            });
        });
    });

    it('Should have valid atoken', function (done) {
        authenticate.models.atoken.get(tokenState.token, function (err, atoken) {
            should(err).be.empty;

            should.exist(atoken);

            var atokenSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                salt: joi.string().required(),
                uniqueKey: joi.string().required(),
                expires: joi.number().required(),
                created: joi.number().required(),
                scope: joi.array().items(joi.string()).required()
            });

            atokenSchema.validate(atoken, function (err, atoken) {
                should(err).be.empty;
                should.exist(atoken);

                myAtoken = atoken;

                done();
            });
        });
    });

    it('Should have valid aukey', function (done) {
        authenticate.models.aukey.get(myAtoken.relkey, function (err, aukey) {
            should(err).be.empty;

            should.exist(aukey);

            var aukeySchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                scope: joi.array().items(joi.string()).required(),
                created: joi.number().required()
            });

            aukeySchema.validate(aukey, function (err, aukey) {
                should(err).be.empty;
                should.exist(aukey);

                myAukey = aukey;

                done();
            });
        });
    });

    it('Should have valid aukey secrets', function (done) {
        authenticate.models.secret.get(myAukey.key, function (err, aukeySecret) {
            should(err).be.empty;

            should.exist(aukeySecret);

            var aukeySecretSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                verifier: joi.string().required(),
                srpsalt: joi.string().required(),
                created: joi.number().required()
            });

            aukeySecretSchema.validate(aukeySecret, function (err, aukeySecret) {
                should(err).be.empty;
                should.exist(aukeySecret);

                myAukeySecret = aukeySecret;

                done();
            });
        });
    });

    it('Should have valid openkey', function (done) {
        authenticate.models.openkey.get(myAukey.relkey, function (err, openkey) {
            should(err).be.empty;

            should.exist(openkey);

            var openkeySchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                ukey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                relkey: joi.string().required(),
                scope: joi.array().items(joi.string()).required(),
                created: joi.number().required()
            });

            openkeySchema.validate(openkey, function (err, openkey) {
                should(err).be.empty;
                should.exist(openkey);

                myOpenkey = openkey;

                done();
            });
        });
    });

    it('Should have valid openkey secrets', function (done) {
        authenticate.models.secret.get(myOpenkey.key, function (err, openkeySecret) {
            should(err).be.empty;

            should.exist(openkeySecret);

            var openkeySecretSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                verifier: joi.string().required(),
                srpsalt: joi.string().required(),
                created: joi.number().required()
            });

            openkeySecretSchema.validate(openkeySecret, function (err, openkeySecret) {
                should(err).be.empty;
                should.exist(openkeySecret);

                myOpenkeySecret = openkeySecret;

                done();
            });
        });
    });

    it('Should have valid userkey', function (done) {
        authenticate.models.userkey.get(myOpenkey.ukey, function (err, userkey) {
            should(err).be.empty;

            should.exist(userkey);

            var userkeySchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                email: joi.string().email().required(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                alias: joi.array().items(joi.string().email()),
                created: joi.number().required()
            });

            userkeySchema.validate(userkey, function (err, userkey) {
                should(err).be.empty;
                should.exist(userkey);

                myUserkey = userkey;

                done();
            });
        });
    });

    it('Should have valid userkey secrets', function (done) {
        authenticate.models.secret.get(myUserkey.key, function (err, userkeySecret) {
            should(err).be.empty;

            should.exist(userkeySecret);

            var userkeySecretSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                verifier: joi.string().required(),
                srpsalt: joi.string().required(),
                created: joi.number().required()
            });

            userkeySecretSchema.validate(userkeySecret, function (err, userkeySecret) {
                should(err).be.empty;
                should.exist(userkeySecret);

                myUserkeySecret = userkeySecret;

                done();
            });
        });
    });
});<commit_msg>further tests<commit_after>var joi = require('joi');
var should = require('should');
var authenticate = require('../index')({
    models: {
        acode:      {dbPath: 'auth_acode'},
        atoken:     {dbPath: 'auth_atoken'},
        aukey:      {dbPath: 'auth_aukey'},
        decision:   {dbPath: 'auth_decision'},
        md5key:     {dbPath: 'auth_md5key'},
        openkey:    {dbPath: 'auth_openkey'},
        regref:     {dbPath: 'auth_regref'},
        rsa:        {dbPath: 'auth_rsa'},
        salt:       {dbPath: 'auth_salt'},
        secret:     {dbPath: 'auth_secret'},
        userkey:    {dbPath: 'auth_userkey'}
    }
});

describe('B2B Client', function () {
    var registration = new authenticate.registration();

    var regEmail = 'test_{{rand}}@example.com'.replace('{{rand}}', Math.random().toString(16).slice(2));
    var regRef;
    var tokenState;
    var myAtoken;
    var myAukey;
    var myOpenkey;
    var myUserkey;
    var myAukeySecret;
    var myOpenkeySecret;
    var myUserkey;

    it('Should Create a client account', function (done) {
        registration.newUser(regEmail, function (err, result) {
            should(err).be.empty;

            should.exist(result);

            var regRespSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                scope: joi.array().items(joi.string()).required(),
                expires: joi.number().required(),
                created: joi.number().required(),
                status: joi.string().valid('pending', 'fulfilled', 'paused', 'error', 'expired', 'cancelled'),
                state: {
                    _id: joi.string(),
                    _rev: joi.string(),
                    email: joi.string().email().required(),
                    token: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                    salt: joi.string().required(),
                    relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                    expires: joi.number().required(),
                    scope: joi.array().items(joi.string()).required()
                }
            });

            regRespSchema.validate(result, function (err, result) {
                should(err).be.empty;
                should.exist(result);
                regRef = result;
                done();
            });
        });
    });

    it('Should get the created registration state', function (done) {

        registration.get(regRef.key, function (err, regState) {
            should(err).be.empty;

            should.exist(regState);

            var regRespSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                email: joi.string().email().required(),
                token: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                salt: joi.string().required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                expires: joi.number().required(),
                scope: joi.array().items(joi.string()).required()
            });

            regRespSchema.validate(regState, function (err, regState) {
                should(err).be.empty;
                should.exist(regState);

                tokenState = regState;

                done();
            });
        });
    });

    it('Should validate the fetched token', function (done) {
        authenticate.validation({
            accessToken: tokenState.token,
            uniqueKey: tokenState.relkey,
            scope: tokenState.scope
        }, function (err, atoken) {
            should(err).be.empty;

            should.exist(atoken);

            var atokenSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                salt: joi.string().required(),
                uniqueKey: joi.string().required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                expires: joi.number().required(),
                created: joi.number().required(),
                scope: joi.array().items(joi.string()).required()
            });

            atokenSchema.validate(atoken, function (err, atoken) {
                should(err).be.empty;
                should.exist(atoken);

                done();
            });
        });
    });

    it('Should have valid atoken', function (done) {
        authenticate.models.atoken.get(tokenState.token, function (err, atoken) {
            should(err).be.empty;

            should.exist(atoken);

            var atokenSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                salt: joi.string().required(),
                uniqueKey: joi.string().required(),
                expires: joi.number().required(),
                created: joi.number().required(),
                scope: joi.array().items(joi.string()).required()
            });

            atokenSchema.validate(atoken, function (err, atoken) {
                should(err).be.empty;
                should.exist(atoken);

                myAtoken = atoken;

                done();
            });
        });
    });

    it('Should have valid aukey', function (done) {
        authenticate.models.aukey.get(myAtoken.relkey, function (err, aukey) {
            should(err).be.empty;

            should.exist(aukey);

            var aukeySchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                relkey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                scope: joi.array().items(joi.string()).required(),
                created: joi.number().required()
            });

            aukeySchema.validate(aukey, function (err, aukey) {
                should(err).be.empty;
                should.exist(aukey);

                myAukey = aukey;

                done();
            });
        });
    });

    it('Should have valid aukey secrets', function (done) {
        authenticate.models.secret.get(myAukey.key, function (err, aukeySecret) {
            should(err).be.empty;

            should.exist(aukeySecret);

            var aukeySecretSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                verifier: joi.string().required(),
                srpsalt: joi.string().required(),
                created: joi.number().required()
            });

            aukeySecretSchema.validate(aukeySecret, function (err, aukeySecret) {
                should(err).be.empty;
                should.exist(aukeySecret);

                myAukeySecret = aukeySecret;

                done();
            });
        });
    });

    it('Should have valid aukey rsa', function (done) {
        authenticate.models.rsa.get(myAukey.key, function (err, rsa) {
            should(err).be.empty;

            should.exist(rsa);

            var rsaSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                rsaPrivKey: joi.string().allow(''),
                rsaBits: joi.any().required(),
                created: joi.number().required()
            });

            rsaSchema.validate(rsa, function (err, rsa) {
                should(err).be.empty;
                should.exist(rsa);

                done();
            });
        });
    });

    it('Should have valid openkey', function (done) {
        authenticate.models.openkey.get(myAukey.relkey, function (err, openkey) {
            should(err).be.empty;

            should.exist(openkey);

            var openkeySchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                ukey: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                relkey: joi.string().required(),
                scope: joi.array().items(joi.string()).required(),
                created: joi.number().required()
            });

            openkeySchema.validate(openkey, function (err, openkey) {
                should(err).be.empty;
                should.exist(openkey);

                myOpenkey = openkey;

                done();
            });
        });
    });

    it('Should have valid openkey secrets', function (done) {
        authenticate.models.secret.get(myOpenkey.key, function (err, openkeySecret) {
            should(err).be.empty;

            should.exist(openkeySecret);

            var openkeySecretSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                verifier: joi.string().required(),
                srpsalt: joi.string().required(),
                created: joi.number().required()
            });

            openkeySecretSchema.validate(openkeySecret, function (err, openkeySecret) {
                should(err).be.empty;
                should.exist(openkeySecret);

                myOpenkeySecret = openkeySecret;

                done();
            });
        });
    });

    it('Should have valid openkey rsa', function (done) {
        authenticate.models.rsa.get(myOpenkey.key, function (err, rsa) {
            should(err).be.empty;

            should.exist(rsa);

            var rsaSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                rsaPrivKey: joi.string().allow(''),
                rsaBits: joi.any().required(),
                created: joi.number().required()
            });

            rsaSchema.validate(rsa, function (err, rsa) {
                should(err).be.empty;
                should.exist(rsa);

                done();
            });
        });
    });

    it('Should have valid userkey', function (done) {
        authenticate.models.userkey.get(myOpenkey.ukey, function (err, userkey) {
            should(err).be.empty;

            should.exist(userkey);

            var userkeySchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                email: joi.string().email().required(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                alias: joi.array().items(joi.string().email()),
                created: joi.number().required()
            });

            userkeySchema.validate(userkey, function (err, userkey) {
                should(err).be.empty;
                should.exist(userkey);

                myUserkey = userkey;

                done();
            });
        });
    });

    it('Should have valid userkey secrets', function (done) {
        authenticate.models.secret.get(myUserkey.key, function (err, userkeySecret) {
            should(err).be.empty;

            should.exist(userkeySecret);

            var userkeySecretSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                verifier: joi.string().required(),
                srpsalt: joi.string().required(),
                created: joi.number().required()
            });

            userkeySecretSchema.validate(userkeySecret, function (err, userkeySecret) {
                should(err).be.empty;
                should.exist(userkeySecret);

                myUserkeySecret = userkeySecret;

                done();
            });
        });
    });

    it('Should have valid userkey rsa', function (done) {
        authenticate.models.rsa.get(myUserkey.key, function (err, rsa) {
            should(err).be.empty;

            should.exist(rsa);

            var rsaSchema = joi.object().keys({
                _id: joi.string(),
                _rev: joi.string(),
                key: joi.string().regex(/[a-zA-Z0-9\-]+/).required(),
                rsaPrivKey: joi.string().allow(''),
                rsaBits: joi.any().required(),
                created: joi.number().required()
            });

            rsaSchema.validate(rsa, function (err, rsa) {
                should(err).be.empty;
                should.exist(rsa);

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


<commit_before>import {renderComponent, expect} from '../test_helper';
import App from '../../src/app/components/app';
import FireBaseTools from '../../src/app/utils/firebase';

describe('fillNoClassThisDay', () => {
  let noClassThisDay = new Array();

  FireBaseTools.fillNoClassThisDay(noClassThisDay);
  it('fill', () => {
      expect(noClassThisDay.length).greaterThan(0);
  });
  it('number of days', () => {
    expect(noClassThisDay.length).equals(11);
  });
    it('expect array', () => {
    expect(noClassThisDay).to.be.a('array');
  });
});

describe('populate', () => {
  let startDate = new Date(2017, 1, 9);
  let endDate = new Date(2017, 4, 13);
  let noClassThisDay = new Array();
  FireBaseTools.fillNoClassThisDay(noClassThisDay);
  let val = () => { return {
      'COMP346Y YA': {
      'Term': 2164,
      'Subject': 'COMP',
      'Catalog': 346,
      'Section': 'Y YA',
      'Component': 'TUT',
      'Pat Nbr': 1,
      'Room Nbr': '',
      'Mtg Start': '8:30:00 AM',
      'Mtg End': '9:20:00 AM',
      'Mon': 'N',
      'Tues': 'Y',
      'Wed': 'N',
      'Thurs': 'N',
      'Fri': 'N',
      'Sat': 'N',
      'Sun': 'N',
      'Start Date': '2017-01-09',
      'End Date': '2017-04-13',
      'Last': 'Goswami',
      'First Name': 'Dhrubajyoti',
      'Email': 'dhrubajyoti.goswami@concordia.ca'
      }
    }
  }
  let snap = {val: val};
  let timeTable = FireBaseTools.populate(startDate, endDate, noClassThisDay, snap);

  it('populate timetable', () => {
    expect(timeTable).to.exist;
  });

    it('timetable object', () => {
      expect(timeTable).to.be.an('object');
  });
});

describe('Weekdays', () => {
  let startDate = new Date(2017, 1, 9);
  let endDate = new Date(2017, 4, 13);
  let noClassThisDay = new Array();
  FireBaseTools.fillNoClassThisDay(noClassThisDay);
  let val = () => { return {
      'COMP346Y YA': {
      'Term': 2164,
      'Subject': 'COMP',
      'Catalog': 346,
      'Section': 'Y YA',
      'Component': 'TUT',
      'Pat Nbr': 1,
      'Room Nbr': '',
      'Mtg Start': '8:30:00 AM',
      'Mtg End': '9:20:00 AM',
      'Mon': 'N',
      'Tues': 'Y',
      'Wed': 'N',
      'Thurs': 'N',
      'Fri': 'N',
      'Sat': 'N',
      'Sun': 'N',
      'Start Date': '2017-01-09',
      'End Date': '2017-04-13',
      'Last': 'Goswami',
      'First Name': 'Dhrubajyoti',
      'Email': 'dhrubajyoti.goswami@concordia.ca'
      }
    }
  }
  let snap = {val: val};
  FireBaseTools.checkWeekday(startDate, endDate, snap);

  it('check weekday', () => {
    expect(FireBaseTools.checkWeekday(startDate, endDate, snap)).to.not.exist;
  });
});

describe('setDateEvents', () => {

  let course = {
      'COMP346Y YA': {
      'Term': 2164,
      'Subject': 'COMP',
      'Catalog': 346,
      'Section': 'Y YA',
      'Component': 'TUT',
      'Pat Nbr': 1,
      'Room Nbr': '',
      'Mtg Start': '8:30:00 AM',
      'Mtg End': '9:20:00 AM',
      'Mon': 'N',
      'Tues': 'Y',
      'Wed': 'N',
      'Thurs': 'N',
      'Fri': 'N',
      'Sat': 'N',
      'Sun': 'N',
      'Start Date': '2017-01-09',
      'End Date': '2017-04-13',
      'Last': 'Goswami',
      'First Name': 'Dhrubajyoti',
      'Email': 'dhrubajyoti.goswami@concordia.ca'
      }
    };

    let date = {};
    let returnDate = FireBaseTools.setDateEvents(course, date);

  it('date exists', () => {
    expect(returnDate).to.exist;
  });
  it('date object', () => {
      expect(returnDate).to.be.an('object');
  });
});
<commit_msg>#108 - Rearranged order in which tests are executed.<commit_after>import {renderComponent, expect} from '../test_helper';
import App from '../../src/app/components/app';
import FireBaseTools from '../../src/app/utils/firebase';

describe('fillNoClassThisDay', () => {
  let noClassThisDay = new Array();
  FireBaseTools.fillNoClassThisDay(noClassThisDay);

  it('expect array', () => {
    expect(noClassThisDay).to.be.a('array');
  });
  it('fill', () => {
      expect(noClassThisDay.length).greaterThan(0);
  });
  it('number of days', () => {
    expect(noClassThisDay.length).equals(11);
  });
});

describe('Weekdays', () => {
  let startDate = new Date(2017, 1, 9);
  let endDate = new Date(2017, 4, 13);
  let noClassThisDay = new Array();
  FireBaseTools.fillNoClassThisDay(noClassThisDay);
  let val = () => { return {
      'COMP346Y YA': {
      'Term': 2164,
      'Subject': 'COMP',
      'Catalog': 346,
      'Section': 'Y YA',
      'Component': 'TUT',
      'Pat Nbr': 1,
      'Room Nbr': '',
      'Mtg Start': '8:30:00 AM',
      'Mtg End': '9:20:00 AM',
      'Mon': 'N',
      'Tues': 'Y',
      'Wed': 'N',
      'Thurs': 'N',
      'Fri': 'N',
      'Sat': 'N',
      'Sun': 'N',
      'Start Date': '2017-01-09',
      'End Date': '2017-04-13',
      'Last': 'Goswami',
      'First Name': 'Dhrubajyoti',
      'Email': 'dhrubajyoti.goswami@concordia.ca'
      }
    }
  }
  let snap = {val: val};

  it('check weekday', () => {
    expect(FireBaseTools.checkWeekday(startDate, endDate, snap)).to.not.exist;
  });
});

describe('populate', () => {
  let startDate = new Date(2017, 1, 9);
  let endDate = new Date(2017, 4, 13);
  let noClassThisDay = new Array();
  FireBaseTools.fillNoClassThisDay(noClassThisDay);
  let val = () => { return {
      'COMP346Y YA': {
      'Term': 2164,
      'Subject': 'COMP',
      'Catalog': 346,
      'Section': 'Y YA',
      'Component': 'TUT',
      'Pat Nbr': 1,
      'Room Nbr': '',
      'Mtg Start': '8:30:00 AM',
      'Mtg End': '9:20:00 AM',
      'Mon': 'N',
      'Tues': 'Y',
      'Wed': 'N',
      'Thurs': 'N',
      'Fri': 'N',
      'Sat': 'N',
      'Sun': 'N',
      'Start Date': '2017-01-09',
      'End Date': '2017-04-13',
      'Last': 'Goswami',
      'First Name': 'Dhrubajyoti',
      'Email': 'dhrubajyoti.goswami@concordia.ca'
      }
    }
  }
  let snap = {val: val};
  let timeTable = FireBaseTools.populate(startDate, endDate, noClassThisDay, snap);

  it('populate timetable', () => {
    expect(timeTable).to.exist;
  });
  it('timetable object', () => {
      expect(timeTable).to.be.an('object');
  });
});

describe('setDateEvents', () => {

  let course = {
      'COMP346Y YA': {
      'Term': 2164,
      'Subject': 'COMP',
      'Catalog': 346,
      'Section': 'Y YA',
      'Component': 'TUT',
      'Pat Nbr': 1,
      'Room Nbr': '',
      'Mtg Start': '8:30:00 AM',
      'Mtg End': '9:20:00 AM',
      'Mon': 'N',
      'Tues': 'Y',
      'Wed': 'N',
      'Thurs': 'N',
      'Fri': 'N',
      'Sat': 'N',
      'Sun': 'N',
      'Start Date': '2017-01-09',
      'End Date': '2017-04-13',
      'Last': 'Goswami',
      'First Name': 'Dhrubajyoti',
      'Email': 'dhrubajyoti.goswami@concordia.ca'
      }
    };

    let date = {};
    let returnDate = FireBaseTools.setDateEvents(course, date);

  it('date exists', () => {
    expect(returnDate).to.exist;
  });
  it('date object', () => {
      expect(returnDate).to.be.an('object');
  });
});
<|endoftext|>


<commit_before>import * as firebase from 'firebase-admin'

const { firebase: config } = require('../../config.json')
const serviceAccount = require('../../service-account-key.json')

firebase.initializeApp({
  credential: firebase.credential.cert(serviceAccount),
  databaseURL: config.databaseURL
})

export default (path, data, callback) => {
  firebase
    .database()
    .ref(path)
    .set(data, callback)
}
<commit_msg>forcing exit<commit_after>import * as firebase from 'firebase-admin'

const { firebase: config } = require('../../config.json')
const serviceAccount = require('../../service-account-key.json')

firebase.initializeApp({
  credential: firebase.credential.cert(serviceAccount),
  databaseURL: config.databaseURL
})

export default (path, data, callback) => {
  firebase
    .database()
    .ref(path)
    .set(data, (error) => {
      callback(error)
      process.exit()
    })
}
<|endoftext|>


<commit_before>const mockDb = require('mock-knex');
const expect = require('expect');
const db = require('knex')({ client: 'pg' });

const constructQuery = require('../lib/constructQuery');

const models = [
  {
    mapId: 'student',
    viewId: 'student',
    idProperty: 'id',
    properties: ['name', 'email'],
    associations: [
      { name: 'tutor', mapId: 'tutor', viewId: 'tutor', populate: true }
    ],
    collections: [
      { name: 'friends', mapId: 'friend', viewId: 'friend_view' }
    ]
  },
  {
    mapId: 'tutor',
    viewId: 'tutor',
    idProperty: 'id',
    properties: ['name', 'email'],
    collections: [
      { name: 'students', mapId: 'student', viewId: 'student', populate: true }
    ],
    associations: []
  },
  {
    mapId: 'friend',
    viewId: 'friend_view',
    idProperty: 'id',
    properties: ['age'],
    associations: [
      { name: 'tutor', mapId: 'tutor', viewId: 'tutor' }
    ],
  },
  {
    mapId: 'human',
    viewId: 'human_view',
    idProperty: 'id',
    properties: ['height', 'weight'],
    collections: [
      { name: 'friends', mapId: 'friend', viewId: 'friend', populate: false, ignore: true },
      { name: 'students', mapId: 'student', viewId: 'student', populate: true, ignore: false }
    ],
    associations: [
      { name: 'students', mapId: 'student', viewId: 'student', populate: false, ignore: true },
      { name: 'tutors', mapId: 'tutor', viewId: 'tutor', populate: false, ignore: false }
    ]
  }
];

describe('ConstructQuery', () => {

  let tracker;
  let generatedQuery;
  before(() => {
    mockDb.mock(db);
    tracker = mockDb.getTracker();
    tracker.install();

    tracker.on('query', query => {
      generatedQuery = query;
      query.response([]);
    });
  });

  after(() => {
    tracker.uninstall();
    mockDb.unmock(db);
  });

  describe('#addCollectionSelects', () => {

    it('should select the properties of a collection', () => {
      const selects = constructQuery._addCollectionSelects(
          models[0].collections[0], models[0], models);

      expect(selects).toEqual([
        'friend_view.age as friend_age',
        'friend_view.id as friend_id',
      ]);
    });

    it('should select the associations of the collection when populate=true', () => {
      const selects = constructQuery._addCollectionSelects(
          models[1].collections[0], models[1], models);

      expect(selects).toEqual([
        'student.name as student_name',
        'student.email as student_email',
        'student.id as student_id',
        'student.tutor as student_tutor'
      ]);
    });

    it('should return no selects if a collection is set to ignore true', () => {
      const selects = constructQuery._addCollectionSelects(
          models[3].collections[0], models[3], models);

      expect(selects).toEqual([]);
    });

    it(
      'should select the associations of the selection when ignore false and populate true',
    () => {
      const selects = constructQuery._addCollectionSelects(
          models[3].collections[1], models[3], models);

      expect(selects).toEqual([
        'student.name as student_name',
        'student.email as student_email',
        'student.id as student_id',
        'student.tutor as student_tutor'
      ]);
    });

  });

  describe('#addAssociationSelects', () => {

    it('should only select the id property on the (core) table when populate=false', () => {
      const selects = constructQuery._addAssociationSelects(
          models[2].associations[0], models[2], models);

      expect(selects).toEqual(['friend_view-core.tutor as tutor']);
    });

    it('should select properties on the association when populate=true', () => {
      const selects = constructQuery._addAssociationSelects(
          models[0].associations[0], models[0], models);

      expect(selects).toEqual([
        'tutor.name as tutor_name',
        'tutor.email as tutor_email',
        'tutor.id as tutor_id'
      ]);
    });

    it('should return an empty select array when ignore is true', () => {
      const selects = constructQuery._addAssociationSelects(
        models[3].associations[0], models[3], models);

      expect(selects).toEqual([]);
    });

    it(
      'should only select the ID property on the core table when populate false and ignore false',
    () => {
      const selects = constructQuery._addAssociationSelects(
        models[3].associations[1], models[3], models);

      expect(selects).toEqual([
        'human_view-core.tutor as tutor'
      ]);
    });

  });

  describe('#constructSelects', () => {
    it('should select all the relevant fields', () => {
      const selects = constructQuery._constructSelects(models, models[0], false);
      expect(selects).toEqual([
        // The main model properties
        'student-core.id as id',
        'student-core.name as name',
        'student-core.email as email',

        // the associations properties
        'tutor.name as tutor_name',
        'tutor.email as tutor_email',
        'tutor.id as tutor_id',

        // The collections properties
        'friend_view.age as friend_age',
        'friend_view.id as friend_id'
      ]);
    });

    it('should include the full_count select', () => {
      const selects = constructQuery._constructSelects(models, models[0], true);
      expect(selects).toEqual([
        // The main model properties
        'student-core.id as id',
        'student-core.name as name',
        'student-core.email as email',

        // the associations properties
        'tutor.name as tutor_name',
        'tutor.email as tutor_email',
        'tutor.id as tutor_id',

        // The collections properties
        'friend_view.age as friend_age',
        'friend_view.id as friend_id',
        'full_count AS full_count'
      ]);
    });
  });

  describe('#constructSubQuery', () => {

    it('should construct a subQuery and apply the parameters given', () => {

      const qb = constructQuery._constructSubQuery(
          db,
          db,
          'student',
          4,         // limit
          7,         // skip
          'name',    // sortAttr
          'asc',     // sortDir
          []
      );

      return qb.then(() => {
        expect(generatedQuery.sql).toEqual(
            'select "student".* from "student" order by "student"."name" asc limit ? offset ?');
        expect(generatedQuery.bindings).toEqual([4, 7]);
      });

    });
  });

  describe('#constructQuery', () => {

    it('should generate a standard query for the supplied model', () => {

      const qb = constructQuery(
          models,
          models[0],
          db,
          [{ key: 'id', values: ['ID_1', 'ID_2'] }],
          'name',    // sortAttr
          'asc',     // sortDir
          4,         // limit
          7          // skip
      );

      return qb.then(() => {
        // Subquery
        expect(generatedQuery.sql).toContain(
            'select "student".* from "student" where "student"."id" in (?, ?) order ' +
            'by "student"."name" asc limit ? offset ?');

        // join tutor (assoc)
        expect(generatedQuery.sql).toContain(
            'left join "tutor" on "tutor"."id" = "student-core"."tutor"');

        // join friend (coll)
        expect(generatedQuery.sql).toContain(
            'left join "friend_view" on "student-core"."id" = "friend_view"."student"');

        // Outer query sorting
        expect(generatedQuery.sql).toContain('order by "student-core"."name" asc');
        // Bindings
        expect(generatedQuery.bindings).toEqual(['ID_1', 'ID_2', 4, 7]);
      });

    });
  });

  describe('#constructWhere', () => {
    it('should generate a query with operator in the where clause', () => {

      const qb = constructQuery(
          models,
          models[0],
          db,
          [{ key: 'id', operator: 'like', value: '%test%' }],
          'name',    // sortAttr
          'asc',     // sortDir
          4,         // limit
          7          // skip
      );

      return qb.then(() => {
        // Subquery
        expect(generatedQuery.sql).toContain(
            'select "student".* from "student" where "student"."id" like ? order ' +
            'by "student"."name" asc limit ? offset ?');

        // Bindings
        expect(generatedQuery.bindings).toEqual(['%test%', 4, 7]);
      });
    });
  });

  describe('#constructOuterQuery', () => {
    it('should generate a query with a view lookup', () => {

      const qb = constructQuery(
          models,
          models[0],
          db,
          [{ model: 'student', key: 'id', value: '10' }]
      );

      return qb.then(() => {
        // Subquery
        expect(generatedQuery.sql).toContain(
          // The main model properties
          '"student-core"."id" as "id"'
        );
        expect(generatedQuery.sql).toContain(
          'left join "tutor" on "tutor"."id" = "student-core"."tutor"');
        // join friend (coll)
        expect(generatedQuery.sql).toContain(
          'left join "friend_view" on "student-core"."id" = "friend_view"."student"');
        // Bindings
        expect(generatedQuery.bindings).toEqual(['10']);
      });
    });
  });
});
<commit_msg>add test for whereAfterJoinClause<commit_after>const mockDb = require('mock-knex');
const expect = require('expect');
const db = require('knex')({ client: 'pg' });

const constructQuery = require('../lib/constructQuery');

const models = [
  {
    mapId: 'student',
    viewId: 'student',
    idProperty: 'id',
    properties: ['name', 'email'],
    associations: [
      { name: 'tutor', mapId: 'tutor', viewId: 'tutor', populate: true }
    ],
    collections: [
      { name: 'friends', mapId: 'friend', viewId: 'friend_view' }
    ]
  },
  {
    mapId: 'tutor',
    viewId: 'tutor',
    idProperty: 'id',
    properties: ['name', 'email'],
    collections: [
      { name: 'students', mapId: 'student', viewId: 'student', populate: true }
    ],
    associations: []
  },
  {
    mapId: 'friend',
    viewId: 'friend_view',
    idProperty: 'id',
    properties: ['age'],
    associations: [
      { name: 'tutor', mapId: 'tutor', viewId: 'tutor' }
    ],
  },
  {
    mapId: 'human',
    viewId: 'human_view',
    idProperty: 'id',
    properties: ['height', 'weight'],
    collections: [
      { name: 'friends', mapId: 'friend', viewId: 'friend', populate: false, ignore: true },
      { name: 'students', mapId: 'student', viewId: 'student', populate: true, ignore: false }
    ],
    associations: [
      { name: 'students', mapId: 'student', viewId: 'student', populate: false, ignore: true },
      { name: 'tutors', mapId: 'tutor', viewId: 'tutor', populate: false, ignore: false }
    ]
  },
  {
    mapId: 'college',
    viewId: 'college',
    idProperty: 'id',
    properties: ['location'],
    association: [],
  }
];

describe('ConstructQuery', () => {

  let tracker;
  let generatedQuery;
  before(() => {
    mockDb.mock(db);
    tracker = mockDb.getTracker();
    tracker.install();

    tracker.on('query', query => {
      generatedQuery = query;
      query.response([]);
    });
  });

  after(() => {
    tracker.uninstall();
    mockDb.unmock(db);
  });

  describe('#addCollectionSelects', () => {

    it('should select the properties of a collection', () => {
      const selects = constructQuery._addCollectionSelects(
          models[0].collections[0], models[0], models);

      expect(selects).toEqual([
        'friend_view.age as friend_age',
        'friend_view.id as friend_id',
      ]);
    });

    it('should select the associations of the collection when populate=true', () => {
      const selects = constructQuery._addCollectionSelects(
          models[1].collections[0], models[1], models);

      expect(selects).toEqual([
        'student.name as student_name',
        'student.email as student_email',
        'student.id as student_id',
        'student.tutor as student_tutor'
      ]);
    });

    it('should return no selects if a collection is set to ignore true', () => {
      const selects = constructQuery._addCollectionSelects(
          models[3].collections[0], models[3], models);

      expect(selects).toEqual([]);
    });

    it(
      'should select the associations of the selection when ignore false and populate true',
    () => {
      const selects = constructQuery._addCollectionSelects(
          models[3].collections[1], models[3], models);

      expect(selects).toEqual([
        'student.name as student_name',
        'student.email as student_email',
        'student.id as student_id',
        'student.tutor as student_tutor'
      ]);
    });

  });

  describe('#addAssociationSelects', () => {

    it('should only select the id property on the (core) table when populate=false', () => {
      const selects = constructQuery._addAssociationSelects(
          models[2].associations[0], models[2], models);

      expect(selects).toEqual(['friend_view-core.tutor as tutor']);
    });

    it('should select properties on the association when populate=true', () => {
      const selects = constructQuery._addAssociationSelects(
          models[0].associations[0], models[0], models);

      expect(selects).toEqual([
        'tutor.name as tutor_name',
        'tutor.email as tutor_email',
        'tutor.id as tutor_id'
      ]);
    });

    it('should return an empty select array when ignore is true', () => {
      const selects = constructQuery._addAssociationSelects(
        models[3].associations[0], models[3], models);

      expect(selects).toEqual([]);
    });

    it(
      'should only select the ID property on the core table when populate false and ignore false',
    () => {
      const selects = constructQuery._addAssociationSelects(
        models[3].associations[1], models[3], models);

      expect(selects).toEqual([
        'human_view-core.tutor as tutor'
      ]);
    });

  });

  describe('#constructSelects', () => {
    it('should select all the relevant fields', () => {
      const selects = constructQuery._constructSelects(models, models[0], false);
      expect(selects).toEqual([
        // The main model properties
        'student-core.id as id',
        'student-core.name as name',
        'student-core.email as email',

        // the associations properties
        'tutor.name as tutor_name',
        'tutor.email as tutor_email',
        'tutor.id as tutor_id',

        // The collections properties
        'friend_view.age as friend_age',
        'friend_view.id as friend_id'
      ]);
    });

    it('should include the full_count select', () => {
      const selects = constructQuery._constructSelects(models, models[0], true);
      expect(selects).toEqual([
        // The main model properties
        'student-core.id as id',
        'student-core.name as name',
        'student-core.email as email',

        // the associations properties
        'tutor.name as tutor_name',
        'tutor.email as tutor_email',
        'tutor.id as tutor_id',

        // The collections properties
        'friend_view.age as friend_age',
        'friend_view.id as friend_id',
        'full_count AS full_count'
      ]);
    });
  });

  describe('#constructSubQuery', () => {

    it('should construct a subQuery and apply the parameters given', () => {

      const qb = constructQuery._constructSubQuery(
          db,
          db,
          'student',
          4,         // limit
          7,         // skip
          'name',    // sortAttr
          'asc',     // sortDir
          []
      );

      return qb.then(() => {
        expect(generatedQuery.sql).toEqual(
            'select "student".* from "student" order by "student"."name" asc limit ? offset ?');
        expect(generatedQuery.bindings).toEqual([4, 7]);
      });

    });
  });

  describe('#constructQuery', () => {

    it('should generate a standard query for the supplied model', () => {

      const qb = constructQuery(
          models,
          models[0],
          db,
          [{ key: 'id', values: ['ID_1', 'ID_2'] }],
          'name',    // sortAttr
          'asc',     // sortDir
          4,         // limit
          7          // skip
      );

      return qb.then(() => {
        // Subquery
        expect(generatedQuery.sql).toContain(
            'select "student".* from "student" where "student"."id" in (?, ?) order ' +
            'by "student"."name" asc limit ? offset ?');

        // join tutor (assoc)
        expect(generatedQuery.sql).toContain(
            'left join "tutor" on "tutor"."id" = "student-core"."tutor"');

        // join friend (coll)
        expect(generatedQuery.sql).toContain(
            'left join "friend_view" on "student-core"."id" = "friend_view"."student"');

        // Outer query sorting
        expect(generatedQuery.sql).toContain('order by "student-core"."name" asc');
        // Bindings
        expect(generatedQuery.bindings).toEqual(['ID_1', 'ID_2', 4, 7]);
      });

    });
  });

  describe('#constructWhere', () => {
    it('should generate a query with operator in the where clause', () => {

      const qb = constructQuery(
          models,
          models[0],
          db,
          [{ key: 'id', operator: 'like', value: '%test%' }],
          'name',    // sortAttr
          'asc',     // sortDir
          4,         // limit
          7          // skip
      );

      return qb.then(() => {
        // Subquery
        expect(generatedQuery.sql).toContain(
            'select "student".* from "student" where "student"."id" like ? order ' +
            'by "student"."name" asc limit ? offset ?');

        // Bindings
        expect(generatedQuery.bindings).toEqual(['%test%', 4, 7]);
      });
    });
  });

  describe('#constructWhereAfterJoin', () => {
    it('should generate a query that filters on a non-core table', () => {
      const qb = constructQuery(
        models,
        models[0],
        db,
        [],
        null,
        null,
        null,
        null,
        null,
        {
          primaryJoin: 'tutor',
          secondaryJoin: 'college',
          value: 'test',
        }
      );

      return qb.then(() => {
        expect(generatedQuery.sql).toContain(
          'with "student-core" as (select "student".* from "student" left join ' +
          '"tutor" on "tutor"."id" = "student"."tutor" where "tutor"."college" = ?'
        );
      });
    });
  });

  describe('#constructOuterQuery', () => {
    it('should generate a query with a view lookup', () => {

      const qb = constructQuery(
          models,
          models[0],
          db,
          [{ model: 'student', key: 'id', value: '10' }]
      );

      return qb.then(() => {
        // Subquery
        expect(generatedQuery.sql).toContain(
          // The main model properties
          '"student-core"."id" as "id"'
        );
        expect(generatedQuery.sql).toContain(
          'left join "tutor" on "tutor"."id" = "student-core"."tutor"');
        // join friend (coll)
        expect(generatedQuery.sql).toContain(
          'left join "friend_view" on "student-core"."id" = "friend_view"."student"');
        // Bindings
        expect(generatedQuery.bindings).toEqual(['10']);
      });
    });
  });
});
<|endoftext|>