<commit_before>
const chai = require('chai');
const configApp = require('../helpers/config-app');
const getInitDb = require('../helpers/get-init-db');
const { populate, setByDot } = require('../../src/services/index');

const assert = chai.assert;
let provider;

['array', 'obj'].forEach(type => {
  describe(`services populate - include 1:1 - ${type}`, () => {
    let hookAfter;
    let hookAfterArray;

    let app;
    let recommendation;

    beforeEach(() => {
      app = configApp(['posts', 'recommendation']);
      recommendation = clone(getInitDb('recommendation').store);

      app.service('posts').before({
        all: [
          hook => { provider = hook.params.provider; }
        ]
      });

      hookAfter = {
        type: 'after',
        method: 'create',
        params: { provider: 'rest' },
        path: 'recommendations',
        result: recommendation['1']
      };
      hookAfterArray = {
        type: 'after',
        method: 'create',
        params: { provider: 'rest' },
        path: 'recommendations',
        result: [recommendation['1'], recommendation['2'], recommendation['3']]
      };
    });

    describe('root is one item', () => {
      it('saves in nameAs without dot notation', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId', // we have no test for dot notation 'cause no such data
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('post');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('saves in nameAs using dot notation', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post.items',
            parentField: 'postId', // we have no test for dot notation 'cause no such data
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('post.items');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('saves in service as default', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('ignores undefined parentField', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        delete hook.result.postId;

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');

            delete expected.postId;
            delete expected.posts;
            expected._include = [];

            assert.deepEqual(hook1.result, expected);
          });
      });

      it('uses asArray', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            asArray: true
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts', true);
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('Stores null when no joined records and !asArray', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        hook.result.postId = '999';

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');

            expected.postId = '999';
            expected.posts = null;

            assert.deepEqual(hook1.result, expected);
          });
      });

      it('Stores [] when no joined records and asArray', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        hook.result.postId = '999';

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            asArray: true
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');

            expected.postId = '999';
            expected.posts = [];

            assert.deepEqual(hook1.result, expected);
          });
      });

      it('query overridden by childField', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            query: { id: 'aaaaaa' }
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('Provider in joins defaults to method call', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            query: { id: 'aaaaaa' }
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
            assert.equal(provider, 'rest'); // Feathers default if not from WebSocket
          });
      });

      it('Provider in joins can be overridden', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            query: { id: 'aaaaaa' },
            provider: undefined
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
            assert.equal(provider, undefined);
          });
      });

      it('childField overridden by select', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'updatedAt',
            childField: 'id',
            select: (hook, parent) => ({ id: parent.postId })
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('checks permissions', () => {
        let spy = [];
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const checkPermissions = (hook, service, permissions, depth) => {
          spy.push({ service, permissions, depth });
          return true;
        };

        const schema = {
          permissions: 'for root',
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id',
            permissions: 'for posts'
          })
        };

        return populate({ schema, checkPermissions })(hook)
          .then(hook1 => {
            let expected = recommendationPosts('post');
            assert.deepEqual(hook1.result, expected);

            expected = [
              { service: 'recommendations', permissions: 'for root', depth: 0 },
              { service: 'posts', permissions: 'for posts', depth: 1 }
            ];
            assert.deepEqual(spy, expected);
          });
      });

      it('throws on invalid permissions', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const checkPermissions = (hook, service, permissions, depth) => {
          return depth === 0;
        };

        const schema = {
          permissions: 'for root',
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id',
            permissions: 'for posts'
          })
        };

        return populate({ schema, checkPermissions })(hook)
          .then(() => { throw new Error('was not supposed to succeed'); })
          .catch(err => { assert.notEqual(err, undefined); });
      });

      it('stores elapsed time', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(hook1 => {
            const elapsed = hook1.result._elapsed;
            assert.deepEqual(Object.keys(elapsed), ['post', 'total']);
            assert.isAbove(elapsed.total, 1000);
            assert.isAtLeast(elapsed.total, elapsed.post);
          });
      });
    });

    describe('root is item array', () => {
      it('populates each item', () => {
        const hook = clone(hookAfterArray);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(hook1 => {
            assert.equal(hook1.result.length, 3);
          });
      });
    });
  });
});

// Helpers

function makeInclude (type, obj) {
  return type === 'obj' ? obj : [obj];
}

function recommendationPosts (nameAs, asArray, recommendation, posts) {
  recommendation = recommendation || clone(getInitDb('recommendation').store['1']);
  posts = posts || clone(getInitDb('posts').store['1']);

  const expected = clone(recommendation);
  expected._include = [nameAs];

  // expected[nameAs] = asArray ? [clone(posts)] : clone(posts);
  setByDot(expected, nameAs, asArray ? [clone(posts)] : clone(posts));

  return expected;
}

function clone (obj) {
  return JSON.parse(JSON.stringify(obj));
}
<commit_msg>Added tests in populate for non related field joins<commit_after>
const chai = require('chai');
const configApp = require('../helpers/config-app');
const getInitDb = require('../helpers/get-init-db');
const { populate, setByDot } = require('../../src/services/index');

const assert = chai.assert;
let provider;

['array', 'obj'].forEach(type => {
  describe(`services populate - include 1:1 - ${type}`, () => {
    let hookAfter;
    let hookAfterArray;

    let app;
    let recommendation;

    beforeEach(() => {
      app = configApp(['posts', 'recommendation']);
      recommendation = clone(getInitDb('recommendation').store);

      app.service('posts').before({
        all: [
          hook => { provider = hook.params.provider; }
        ]
      });

      hookAfter = {
        type: 'after',
        method: 'create',
        params: { provider: 'rest' },
        path: 'recommendations',
        result: recommendation['1']
      };
      hookAfterArray = {
        type: 'after',
        method: 'create',
        params: { provider: 'rest' },
        path: 'recommendations',
        result: [recommendation['1'], recommendation['2'], recommendation['3']]
      };
    });

    describe('root is one item', () => {
      it('saves in nameAs without dot notation', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId', // we have no test for dot notation 'cause no such data
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('post');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('saves in nameAs using dot notation', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post.items',
            parentField: 'postId', // we have no test for dot notation 'cause no such data
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('post.items');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('saves in service as default', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('ignores undefined parentField', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        delete hook.result.postId;

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');

            delete expected.postId;
            delete expected.posts;
            expected._include = [];

            assert.deepEqual(hook1.result, expected);
          });
      });

      it('uses asArray', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            asArray: true
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts', true);
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('Stores null when no joined records and !asArray', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        hook.result.postId = '999';

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');

            expected.postId = '999';
            expected.posts = null;

            assert.deepEqual(hook1.result, expected);
          });
      });

      it('Stores [] when no joined records and asArray', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        hook.result.postId = '999';

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            asArray: true
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');

            expected.postId = '999';
            expected.posts = [];

            assert.deepEqual(hook1.result, expected);
          });
      });

      it('query overridden by childField', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            query: { id: 'aaaaaa' }
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('Provider in joins defaults to method call', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            query: { id: 'aaaaaa' }
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
            assert.equal(provider, 'rest'); // Feathers default if not from WebSocket
          });
      });

      it('Provider in joins can be overridden', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'postId',
            childField: 'id',
            query: { id: 'aaaaaa' },
            provider: undefined
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
            assert.equal(provider, undefined);
          });
      });

      it('childField overridden by select', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            parentField: 'updatedAt',
            childField: 'id',
            select: (hook, parent) => ({ id: parent.postId })
          })
        };

        return populate({ schema })(hook)
          .then(hook1 => {
            const expected = recommendationPosts('posts');
            assert.deepEqual(hook1.result, expected);
          });
      });

      it('checks permissions', () => {
        let spy = [];
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const checkPermissions = (hook, service, permissions, depth) => {
          spy.push({ service, permissions, depth });
          return true;
        };

        const schema = {
          permissions: 'for root',
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id',
            permissions: 'for posts'
          })
        };

        return populate({ schema, checkPermissions })(hook)
          .then(hook1 => {
            let expected = recommendationPosts('post');
            assert.deepEqual(hook1.result, expected);

            expected = [
              { service: 'recommendations', permissions: 'for root', depth: 0 },
              { service: 'posts', permissions: 'for posts', depth: 1 }
            ];
            assert.deepEqual(spy, expected);
          });
      });

      it('throws on invalid permissions', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const checkPermissions = (hook, service, permissions, depth) => {
          return depth === 0;
        };

        const schema = {
          permissions: 'for root',
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id',
            permissions: 'for posts'
          })
        };

        return populate({ schema, checkPermissions })(hook)
          .then(() => { throw new Error('was not supposed to succeed'); })
          .catch(err => { assert.notEqual(err, undefined); });
      });

      it('stores elapsed time', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(hook1 => {
            const elapsed = hook1.result._elapsed;
            assert.deepEqual(Object.keys(elapsed), ['post', 'total']);
            assert.isAbove(elapsed.total, 1000);
            assert.isAtLeast(elapsed.total, elapsed.post);
          });
      });

      it('allow non related field joins if query', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            query: { id: hookAfter.result.postId }
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(hook1 => {
            const elapsed = hook1.result._elapsed;
            assert.deepEqual(Object.keys(elapsed), ['post', 'total']);
            assert.isAbove(elapsed.total, 1000);
            assert.isAtLeast(elapsed.total, elapsed.post);
          });
      });

      it('allow non related field joins if select', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            select: (hook, parentItem) => ({ id: parentItem.postId })
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(hook1 => {
            const elapsed = hook1.result._elapsed;
            assert.deepEqual(Object.keys(elapsed), ['post', 'total']);
            assert.isAbove(elapsed.total, 1000);
            assert.isAtLeast(elapsed.total, elapsed.post);
          });
      });

      it('throws if no parentField option in related field join', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            childField: 'id'
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(() => {
            assert(false, 'unexpectedly succeeeded');
          })
          .catch(err => {
            assert.isObject(err, 'no error object');
          });
      });

      it('throws if no parentField defined in related field join', () => {
        const hook = clone(hookAfter);
        hook.app = app; // app is a func and wouldn't be cloned
        delete hook.result.postId;

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(() => {
            assert(false, 'unexpectedly succeeeded');
          })
          .catch(err => {
            assert.isObject(err, 'no error object');
          });
      });
    });

    describe('root is item array', () => {
      it('populates each item', () => {
        const hook = clone(hookAfterArray);
        hook.app = app; // app is a func and wouldn't be cloned

        const schema = {
          include: makeInclude(type, {
            service: 'posts',
            nameAs: 'post',
            parentField: 'postId',
            childField: 'id'
          })
        };

        return populate({ schema, profile: true })(hook)
          .then(hook1 => {
            assert.equal(hook1.result.length, 3);
          });
      });
    });
  });
});

// Helpers

function makeInclude (type, obj) {
  return type === 'obj' ? obj : [obj];
}

function recommendationPosts (nameAs, asArray, recommendation, posts) {
  recommendation = recommendation || clone(getInitDb('recommendation').store['1']);
  posts = posts || clone(getInitDb('posts').store['1']);

  const expected = clone(recommendation);
  expected._include = [nameAs];

  // expected[nameAs] = asArray ? [clone(posts)] : clone(posts);
  setByDot(expected, nameAs, asArray ? [clone(posts)] : clone(posts));

  return expected;
}

function clone (obj) {
  return JSON.parse(JSON.stringify(obj));
}
<|endoftext|>


<commit_before>import path from 'path';
import SeleniumHelper from '../helpers/selenium-helper';

const {
    clickText,
    clickXpath,
    findByText,
    findByXpath,
    getDriver,
    loadUri,
    rightClickText,
    scope,
    waitUntilGone
} = new SeleniumHelper();

const uri = path.resolve(__dirname, '../../build/index.html');

let driver;

describe('Menu bar settings', () => {
    beforeAll(() => {
        driver = getDriver();
    });

    afterAll(async () => {
        await driver.quit();
    });

    test('File->New should be enabled', async () => {
        await loadUri(uri);
        await clickXpath(
            '//div[contains(@class, "menu-bar_menu-bar-item") and ' +
            'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
        );
        await findByXpath('//*[li[span[text()="New"]] and not(@data-tip="tooltip")]');
    });

    test('File->Load should be enabled', async () => {
        await loadUri(uri);
        await clickXpath(
            '//div[contains(@class, "menu-bar_menu-bar-item") and ' +
            'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
        );
        await findByXpath('//*[li[span[text()="Load from your computer"]] and not(@data-tip="tooltip")]');
    });

    test('File->Save should be enabled', async () => {
        await loadUri(uri);
        await clickXpath(
            '//div[contains(@class, "menu-bar_menu-bar-item") and ' +
            'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
        );
        await findByXpath('//*[li[span[text()="Save to your computer"]] and not(@data-tip="tooltip")]');
    });

    test('Share button should NOT be enabled', async () => {
        await loadUri(uri);
        await findByXpath('//div[span[div[span[text()="Share"]]] and @data-tip="tooltip"]');
    });

    test('Logo should be clickable', async () => {
        await loadUri(uri);
        await clickXpath('//img[@alt="Scratch"]');
        const currentUrl = await driver.getCurrentUrl();
        await expect(currentUrl).toEqual('https://scratch.mit.edu/');
    });

    test('(GH#4064) Project name should be editable', async () => {
        await loadUri(uri);
        const el = await findByXpath('//input[@value="Scratch Project"]');
        await el.sendKeys(' - Personalized');
        await clickText('Costumes'); // just to blur the input
        await clickXpath('//input[@value="Scratch Project - Personalized"]');
    });

    test('User is not warned before uploading project file over a fresh project', async () => {
        await loadUri(uri);
        await clickXpath('//button[@title="Try It"]');
        await clickText('File');
        const input = await findByXpath('//input[@accept=".sb,.sb2,.sb3"]');
        await input.sendKeys(path.resolve(__dirname, '../fixtures/project1.sb3'));
        await waitUntilGone(findByText('Loading'));
        // No replace alert since no changes were made
        await findByText('project1-sprite');
    });

    test('User is warned before uploading project file over an edited project', async () => {
        await loadUri(uri);
        await clickXpath('//button[@title="Try It"]');

        // Change the project by deleting a sprite
        await rightClickText('Sprite1', scope.spriteTile);
        await clickText('delete', scope.spriteTile);

        await clickText('File');
        const input = await findByXpath('//input[@accept=".sb,.sb2,.sb3"]');
        await input.sendKeys(path.resolve(__dirname, '../fixtures/project1.sb3'));
        await driver.switchTo().alert()
            .accept();
        await waitUntilGone(findByText('Loading'));
        await findByText('project1-sprite');
    });
});
<commit_msg>Update to develop and remove try-it steps from new tests<commit_after>import path from 'path';
import SeleniumHelper from '../helpers/selenium-helper';

const {
    clickText,
    clickXpath,
    findByText,
    findByXpath,
    getDriver,
    loadUri,
    rightClickText,
    scope,
    waitUntilGone
} = new SeleniumHelper();

const uri = path.resolve(__dirname, '../../build/index.html');

let driver;

describe('Menu bar settings', () => {
    beforeAll(() => {
        driver = getDriver();
    });

    afterAll(async () => {
        await driver.quit();
    });

    test('File->New should be enabled', async () => {
        await loadUri(uri);
        await clickXpath(
            '//div[contains(@class, "menu-bar_menu-bar-item") and ' +
            'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
        );
        await findByXpath('//*[li[span[text()="New"]] and not(@data-tip="tooltip")]');
    });

    test('File->Load should be enabled', async () => {
        await loadUri(uri);
        await clickXpath(
            '//div[contains(@class, "menu-bar_menu-bar-item") and ' +
            'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
        );
        await findByXpath('//*[li[span[text()="Load from your computer"]] and not(@data-tip="tooltip")]');
    });

    test('File->Save should be enabled', async () => {
        await loadUri(uri);
        await clickXpath(
            '//div[contains(@class, "menu-bar_menu-bar-item") and ' +
            'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
        );
        await findByXpath('//*[li[span[text()="Save to your computer"]] and not(@data-tip="tooltip")]');
    });

    test('Share button should NOT be enabled', async () => {
        await loadUri(uri);
        await findByXpath('//div[span[div[span[text()="Share"]]] and @data-tip="tooltip"]');
    });

    test('Logo should be clickable', async () => {
        await loadUri(uri);
        await clickXpath('//img[@alt="Scratch"]');
        const currentUrl = await driver.getCurrentUrl();
        await expect(currentUrl).toEqual('https://scratch.mit.edu/');
    });

    test('(GH#4064) Project name should be editable', async () => {
        await loadUri(uri);
        const el = await findByXpath('//input[@value="Scratch Project"]');
        await el.sendKeys(' - Personalized');
        await clickText('Costumes'); // just to blur the input
        await clickXpath('//input[@value="Scratch Project - Personalized"]');
    });

    test('User is not warned before uploading project file over a fresh project', async () => {
        await loadUri(uri);
        await clickText('File');
        const input = await findByXpath('//input[@accept=".sb,.sb2,.sb3"]');
        await input.sendKeys(path.resolve(__dirname, '../fixtures/project1.sb3'));
        await waitUntilGone(findByText('Loading'));
        // No replace alert since no changes were made
        await findByText('project1-sprite');
    });

    test('User is warned before uploading project file over an edited project', async () => {
        await loadUri(uri);

        // Change the project by deleting a sprite
        await rightClickText('Sprite1', scope.spriteTile);
        await clickText('delete', scope.spriteTile);

        await clickText('File');
        const input = await findByXpath('//input[@accept=".sb,.sb2,.sb3"]');
        await input.sendKeys(path.resolve(__dirname, '../fixtures/project1.sb3'));
        await driver.switchTo().alert()
            .accept();
        await waitUntilGone(findByText('Loading'));
        await findByText('project1-sprite');
    });
});
<|endoftext|>


<commit_before>var nm = require("nodemailer");
var t = nm.createTransport();

function sendAlert(outputName, alertContent) {
  t.sendMail({
    from: "bot@data.string.er",
    to: config.userEmail,
    subject: "ALERT for " + outputName,
    text: "On today's run, " + outputName + "generated an alert, with the " +
        "following content:\n" + alertContent // TODO pretty print the object
  },
  function(err, info) {
    if(err) {
      console.log(err);
    }
  });
}

function sendError(outputName, error) {
  t.sendMail({
    from: "bot@data.string.er",
    to: config.userEmail,
    subject: "ERROR for " + outputName,
    text: "On today's run, " + outputName + "generated this error: " + error +
        "\nIf it is one of the build-in datasources, you can contact the " +
        "project maintener on github (http://github.com/basilesimon/datastringer)"
  },
  function(err, info) {
    if(err) {
      console.log(err);
    }
  });
}

module.exports = {
  sendAler: sendAlert,
  sendError: sendError
};
<commit_msg>mailer: simplify & adapt wording<commit_after>var nm = require("nodemailer");
var t = nm.createTransport();

function sendAlert(stringerName, alertContent) {
  t.sendMail({
    from: "bot@data.string.er",
    to: config.userEmail,
    subject: "ALERT for " + stringerName,
    text: "On today's run, " + stringerName + "generated an alert, with the " +
        "following content:\n" + alertContent // TODO pretty print the object
  },
  function(err, info) {
    if(err) {
      console.log(err);
    }
  });
}

module.exports = {
  sendAler: sendAlert,
};
<|endoftext|>


<commit_before>var _ = require('lodash'),
    THREE = require('three'),
    INF = Number.POSITIVE_INFINITY,
    PARTICLE_COUNT = 60;

module.exports = function (scene) {
  var system = generateSystem(),
      geo = system.geometry,
      i = 0,
      projectiles = [];

  return { add: add, move: move, system: system };

  function move (i, x, y, z) {
    geo.vertices[i].set(x, y, z);
    geo.verticesNeedUpdate = true;
  }

  function add (colourHex) {
    if (i > PARTICLE_COUNT) {
      i = 0;
    }
    var position = geo.vertices[i],
        color = geo.colors[i];

    color.setHex(colourHex);
    geo.colorsNeedUpdate = true;
    i++;
    log('Launched torpedo with colour 0x' + colourHex.toString(16));

    return i - 1;
  }
};

function generateSystem () {
  var geo = new THREE.Geometry(),
      material = generateMaterial();

  // Generate a stack of torpedoes for use later
  _.times(PARTICLE_COUNT, function () {
    geo.vertices.push(new THREE.Vector3(INF, INF, INF));
    geo.colors.push(new THREE.Color(0xffffff));
  });
  var system = new THREE.ParticleSystem(geo, material);
  system.sortParticles = true;
  return system;
}

function generateMaterial () {
  return new THREE.ParticleBasicMaterial({
    size: 250,
    map: THREE.ImageUtils.loadTexture('/textures/torpedo.png'),
    transparent: true,
    blending: THREE.AdditiveBlending,
    vertexColors: true,
    depthWrite: false
  });
}
<commit_msg>Correct selection of non existent particle from pool<commit_after>var _ = require('lodash'),
    THREE = require('three'),
    INF = Number.POSITIVE_INFINITY,
    PARTICLE_COUNT = 60;

module.exports = function (scene) {
  var system = generateSystem(),
      geo = system.geometry,
      i = 0,
      projectiles = [];

  return { add: add, move: move, system: system };

  function move (i, x, y, z) {
    geo.vertices[i].set(x, y, z);
    geo.verticesNeedUpdate = true;
  }

  function add (colourHex) {
    if (i >= PARTICLE_COUNT) {
      i = 0;
    }
    var position = geo.vertices[i],
        color = geo.colors[i];

    color.setHex(colourHex);
    geo.colorsNeedUpdate = true;
    i++;
    log('Launched torpedo with colour 0x' + colourHex.toString(16));

    return i - 1;
  }
};

function generateSystem () {
  var geo = new THREE.Geometry(),
      material = generateMaterial();

  // Generate a stack of torpedoes for use later
  _.times(PARTICLE_COUNT, function () {
    geo.vertices.push(new THREE.Vector3(INF, INF, INF));
    geo.colors.push(new THREE.Color(0xffffff));
  });
  var system = new THREE.ParticleSystem(geo, material);
  system.sortParticles = true;
  return system;
}

function generateMaterial () {
  return new THREE.ParticleBasicMaterial({
    size: 250,
    map: THREE.ImageUtils.loadTexture('/textures/torpedo.png'),
    transparent: true,
    blending: THREE.AdditiveBlending,
    vertexColors: true,
    depthWrite: false
  });
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import emberRequire from './ext-require';

const SelectView = emberRequire('ember-views/views/select');
const EmberView = emberRequire('ember-views/views/view');
const RoutingService = emberRequire('ember-routing/services/routing');
const Engine = emberRequire('ember-application/system/engine');

const {
  OutletView,
  TextField,
  TextArea,
  Checkbox,
  ContainerDebugAdapter,
  ComponentLookup,
  LinkComponent
} = Ember;

Engine.reopen({
  buildRegistry() {
    let namespace = this;
    let registry = this._super(...arguments);

    if (!(this instanceof Ember.Application)) {
      registry.optionsForType('component', { singleton: false });
      registry.optionsForType('view', { singleton: false });
      registry.optionsForType('template', { instantiate: false });

      registry.register('application:main', namespace, { instantiate: false });

      registry.register('controller:basic', Ember.Controller, { instantiate: false });

      // registry.register('renderer:-dom', { create() { return new Renderer(new DOMHelper()); } });

      registry.injection('view', 'renderer', 'renderer:-dom');

      if (Ember.ENV._ENABLE_LEGACY_VIEW_SUPPORT) {
        registry.register('view:select', SelectView);
      }
      registry.register('view:-outlet', OutletView);

      //registry.register('-view-registry:main', { create() { return {}; } });

      registry.injection('view', '_viewRegistry', '-view-registry:main');

      registry.register('view:toplevel', EmberView.extend());

      // registry.register('route:basic', Route, { instantiate: false });
      // registry.register('event_dispatcher:main', EventDispatcher);

      // registry.injection('router:main', 'namespace', 'application:main');
      registry.injection('view:-outlet', 'namespace', 'application:main');

      // registry.register('location:auto', AutoLocation);
      // registry.register('location:hash', HashLocation);
      // registry.register('location:history', HistoryLocation);
      // registry.register('location:none', NoneLocation);

      registry.injection('controller', 'target', 'router:main');
      registry.injection('controller', 'namespace', 'application:main');

      // registry.register('-bucket-cache:main', BucketCache);
      registry.injection('router', '_bucketCache', '-bucket-cache:main');
      registry.injection('route', '_bucketCache', '-bucket-cache:main');
      registry.injection('controller', '_bucketCache', '-bucket-cache:main');

      registry.injection('route', 'router', 'router:main');

      registry.register('component:-text-field', TextField);
      registry.register('component:-text-area', TextArea);
      registry.register('component:-checkbox', Checkbox);
      // registry.register('view:-legacy-each', LegacyEachView);
      registry.register('component:link-to', LinkComponent);

      // Register the routing service...
      registry.register('service:-routing', RoutingService);
      // Then inject the app router into it
      registry.injection('service:-routing', 'router', 'router:main');

      // DEBUGGING
      registry.register('resolver-for-debugging:main', registry.resolver, { instantiate: false });
      registry.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main');
      registry.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main');
      // Custom resolver authors may want to register their own ContainerDebugAdapter with this key

      registry.register('container-debug-adapter:main', ContainerDebugAdapter);

      registry.register('component-lookup:main', ComponentLookup);
    }

    return registry;
  }
});
<commit_msg>Remove reference to Ember.Select<commit_after>import Ember from 'ember';
import emberRequire from './ext-require';

const EmberView = emberRequire('ember-views/views/view');
const RoutingService = emberRequire('ember-routing/services/routing');
const Engine = emberRequire('ember-application/system/engine');

const {
  OutletView,
  TextField,
  TextArea,
  Checkbox,
  ContainerDebugAdapter,
  ComponentLookup,
  LinkComponent
} = Ember;

Engine.reopen({
  buildRegistry() {
    let namespace = this;
    let registry = this._super(...arguments);

    if (!(this instanceof Ember.Application)) {
      registry.optionsForType('component', { singleton: false });
      registry.optionsForType('view', { singleton: false });
      registry.optionsForType('template', { instantiate: false });

      registry.register('application:main', namespace, { instantiate: false });

      registry.register('controller:basic', Ember.Controller, { instantiate: false });

      // registry.register('renderer:-dom', { create() { return new Renderer(new DOMHelper()); } });

      registry.injection('view', 'renderer', 'renderer:-dom');

      registry.register('view:-outlet', OutletView);

      //registry.register('-view-registry:main', { create() { return {}; } });

      registry.injection('view', '_viewRegistry', '-view-registry:main');

      registry.register('view:toplevel', EmberView.extend());

      // registry.register('route:basic', Route, { instantiate: false });
      // registry.register('event_dispatcher:main', EventDispatcher);

      // registry.injection('router:main', 'namespace', 'application:main');
      registry.injection('view:-outlet', 'namespace', 'application:main');

      // registry.register('location:auto', AutoLocation);
      // registry.register('location:hash', HashLocation);
      // registry.register('location:history', HistoryLocation);
      // registry.register('location:none', NoneLocation);

      registry.injection('controller', 'target', 'router:main');
      registry.injection('controller', 'namespace', 'application:main');

      // registry.register('-bucket-cache:main', BucketCache);
      registry.injection('router', '_bucketCache', '-bucket-cache:main');
      registry.injection('route', '_bucketCache', '-bucket-cache:main');
      registry.injection('controller', '_bucketCache', '-bucket-cache:main');

      registry.injection('route', 'router', 'router:main');

      registry.register('component:-text-field', TextField);
      registry.register('component:-text-area', TextArea);
      registry.register('component:-checkbox', Checkbox);
      // registry.register('view:-legacy-each', LegacyEachView);
      registry.register('component:link-to', LinkComponent);

      // Register the routing service...
      registry.register('service:-routing', RoutingService);
      // Then inject the app router into it
      registry.injection('service:-routing', 'router', 'router:main');

      // DEBUGGING
      registry.register('resolver-for-debugging:main', registry.resolver, { instantiate: false });
      registry.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main');
      registry.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main');
      // Custom resolver authors may want to register their own ContainerDebugAdapter with this key

      registry.register('container-debug-adapter:main', ContainerDebugAdapter);

      registry.register('component-lookup:main', ComponentLookup);
    }

    return registry;
  }
});
<|endoftext|>


<commit_before>var combine = require('stream-combiner');
var split = require('split');
var through = require('through');

module.exports =
function createParser() {
  var JSONParse = through(parseJSON);
  var s = combine(split('\n'), JSONParse);
  return s;

  function parseJSON(d) {
    try {
      d = JSON.parse(d)
    } catch(err) {
      s.emit('error', err);
      return;
    }
    this.queue(d);
  }
};

<commit_msg>only parsing if has content<commit_after>var combine = require('stream-combiner');
var split = require('split');
var through = require('through');

module.exports =
function createParser() {
  var JSONParse = through(parseJSON);
  var s = combine(split('\n'), JSONParse);
  return s;

  function parseJSON(d) {
    if (d) {
      try {
        d = JSON.parse(d)
      } catch(err) {
        s.emit('error', err);
        return;
      }
      this.queue(d);
    }
  }
};

<|endoftext|>


<commit_before>/*
 * Copyright 2016 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Logger for Closure Compiler output.
 */

'use strict';

const ESC = '\u001B';
const COLOR_END = ESC + '[0m';
const COLOR_RED = ESC + '[91m';
const COLOR_GREEN = ESC + '[92m';
const COLOR_YELLOW = ESC + '[93m';

/**
 * @param {string} line to generate prefix for
 * @param {number} charNo to generate prefix at
 * @return {string} prefix for showing a caret
 */
function caretPrefix(line, charNo) {
  return line.substr(0, charNo).replace(/[^\t]/g, ' ');
}

/**
 * @param {!Object} options
 * @param {!Object} output
 * @param {function(string)} logger
 * @return {boolean} Whether this output should fail a compilation.
 */
module.exports = function(options, output, logger=console.warn) {
  // TODO(samthor): If this file has a sourceMap, then follow it back out of the rabbit hole.
  function fileFor(file) {
    if (!file) { return null; }

    // Filenames are the same across source and externs, so prefer source files.
    for (const files of [options.jsCode, options.externs]) {
      if (!files) { continue; }

      for (const cand of files) {
        if (cand.path == file) {
          return cand;
        }
      }
    }

    return null;
  }

  function writemsg(color, msg) {
    if (!msg.file && msg.lineNo < 0) {
      logger(msg.type);
    } else {
      logger(`${msg.file}:${msg.lineNo} (${msg.type})`)
    }
    logger(msg.description);

    const file = fileFor(msg.file);
    if (file) {
      const lines = file.src.split('\n');  // TODO(samthor): cache this for logger?
      const line = lines[msg.lineNo - 1] || '';
      logger(color + line + COLOR_END);
      logger(COLOR_GREEN + caretPrefix(line, msg.charNo) + '^' + COLOR_END);
    }
    logger('');
  }

  output.warnings.forEach(writemsg.bind(null, COLOR_YELLOW));
  output.errors.forEach(writemsg.bind(null, COLOR_RED));

  return output.errors.length > 0;
};
<commit_msg>Fix Node 4.5 LTS compatibility in logger<commit_after>/*
 * Copyright 2016 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Logger for Closure Compiler output.
 */

'use strict';

const ESC = '\u001B';
const COLOR_END = ESC + '[0m';
const COLOR_RED = ESC + '[91m';
const COLOR_GREEN = ESC + '[92m';
const COLOR_YELLOW = ESC + '[93m';

/**
 * @param {string} line to generate prefix for
 * @param {number} charNo to generate prefix at
 * @return {string} prefix for showing a caret
 */
function caretPrefix(line, charNo) {
  return line.substr(0, charNo).replace(/[^\t]/g, ' ');
}

/**
 * @param {!Object} options
 * @param {!Object} output
 * @param {function(string)} logger
 * @return {boolean} Whether this output should fail a compilation.
 */
module.exports = function(options, output, logger) {
  logger = logger || console.warn;
  // TODO(samthor): If this file has a sourceMap, then follow it back out of the rabbit hole.
  function fileFor(file) {
    if (!file) { return null; }

    // Filenames are the same across source and externs, so prefer source files.
    for (const files of [options.jsCode, options.externs]) {
      if (!files) { continue; }

      for (const cand of files) {
        if (cand.path == file) {
          return cand;
        }
      }
    }

    return null;
  }

  function writemsg(color, msg) {
    if (!msg.file && msg.lineNo < 0) {
      logger(msg.type);
    } else {
      logger(`${msg.file}:${msg.lineNo} (${msg.type})`)
    }
    logger(msg.description);

    const file = fileFor(msg.file);
    if (file) {
      const lines = file.src.split('\n');  // TODO(samthor): cache this for logger?
      const line = lines[msg.lineNo - 1] || '';
      logger(color + line + COLOR_END);
      logger(COLOR_GREEN + caretPrefix(line, msg.charNo) + '^' + COLOR_END);
    }
    logger('');
  }

  output.warnings.forEach(writemsg.bind(null, COLOR_YELLOW));
  output.errors.forEach(writemsg.bind(null, COLOR_RED));

  return output.errors.length > 0;
};
<|endoftext|>


<commit_before>/* global describe, expect, it, jasmine */
var RecordHandler = require( '../../src/record/record-handler' ),
	msg = require( '../test-helper/test-helper' ).msg,
	StorageMock = require( '../mocks/storage-mock' ),
	SocketMock = require( '../mocks/socket-mock' ),
	SocketWrapper = require( '../../src/message/socket-wrapper' ),
	LoggerMock = require( '../mocks/logger-mock' ),
	noopMessageConnector = require( '../../src/default-plugins/noop-message-connector' );

describe( 'record handler handles messages', function(){
	var recordHandler,
		clientA = new SocketWrapper( new SocketMock() ),
		clientB = new SocketWrapper( new SocketMock() ),
		options = {
			cache: new StorageMock(),
			storage: new StorageMock(),
			logger: new LoggerMock(),
			messageConnector: noopMessageConnector
		};

	it( 'creates the record handler', function(){
		recordHandler = new RecordHandler( options );
		expect( recordHandler.handle ).toBeDefined();
	});

	it( 'creates a non existing record', function(){
		recordHandler.handle( clientA, {
			topic: 'RECORD',
			action: 'CR',
			data: [ 'someRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|R|someRecord|0|{}+') );
	});

	it( 'returns an existing record', function(){
		options.cache.set( 'existingRecord', { _v:3, _d: { firstname: 'Wolfram' } }, function(){} );
		recordHandler.handle( clientA, {
			topic: 'RECORD',
			action: 'CR',
			data: [ 'existingRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|R|existingRecord|3|{"firstname":"Wolfram"}+' ));
	});

	it( 'patches a record', function(){
		recordHandler.handle( clientB, {
			raw: msg( 'R|P|existingRecord|4|lastname|SEgon' ),
			topic: 'RECORD',
			action: 'P',
			data: [ 'existingRecord', 4, 'lastname', 'SEgon' ]
		});

		expect( clientB.socket.lastSendMessage ).toBe( null );
		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|P|existingRecord|4|lastname|SEgon+' ));
	});

	it( 'returns the patched record', function(){
		recordHandler.handle( clientB, {
			topic: 'RECORD',
			action: 'CR',
			data: [ 'existingRecord' ]
		});

		expect( clientB.socket.lastSendMessage ).toBe( msg( 'R|R|existingRecord|4|{"firstname":"Wolfram","lastname":"Egon"}+' ));
	});

	it( 'updates a record', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|5|{"name":"Kowalski"}' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'existingRecord', 5, '{"name":"Kowalski"}' ]
		});

		expect( clientB.socket.lastSendMessage ).toBe( msg( 'R|U|existingRecord|5|{"name":"Kowalski"}+' ) );
		options.cache.get( 'existingRecord', function( error, record ){
			expect( record ).toEqual({ _v: 5, _d: { name: 'Kowalski' } });
		});
	});

	it( 'handles unsubscribe messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|US|someRecord' ),
			topic: 'RECORD',
			action: 'US',
			data: [ 'someRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|A|US|someRecord+' ) );

		recordHandler.handle( clientB, {
			raw: msg( 'R|US|someRecord' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'someRecord', 1, '{"bla":"blub"}' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|A|US|someRecord+' ) );
	});

	it( 'rejects updates for existing versions', function(){
		clientA.user = 'someUser';

		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|5|{"name":"Kowalski"}' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'existingRecord', 5, '{"name":"Kowalski"}' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|E|VERSION_EXISTS|5+' ) );
		expect( options.logger.lastLogMessage ).toBe( msg( 'someUser tried to update record existingRecord to version 5 but it already was 5' ) );
	});

	it( 'handles invalid update messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|6' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'existingRecord', 6 ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|E|INVALID_MESSAGE_DATA|existingRecord+' ) );
	});

	it( 'handles invalid patch messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|6|bla' ),
			topic: 'RECORD',
			action: 'P',
			data: [ 'existingRecord', 6, 'bla']
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|E|INVALID_MESSAGE_DATA|R|U|existingRecord|6|bla+' ) );
	});

	it( 'handles deletion messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|D|existingRecord' ),
			topic: 'RECORD',
			action: 'D',
			data: [ 'existingRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|A|D|existingRecord+' ) );
		expect( clientB.socket.lastSendMessage ).toBe( msg( 'R|A|D|existingRecord+' ) );

		options.cache.get( 'existingRecord', function( error, record ){
			expect( record ).toEqual( null );
		});
	});
});<commit_msg>Updated test to match version mismatch message<commit_after>/* global describe, expect, it, jasmine */
var RecordHandler = require( '../../src/record/record-handler' ),
	msg = require( '../test-helper/test-helper' ).msg,
	StorageMock = require( '../mocks/storage-mock' ),
	SocketMock = require( '../mocks/socket-mock' ),
	SocketWrapper = require( '../../src/message/socket-wrapper' ),
	LoggerMock = require( '../mocks/logger-mock' ),
	noopMessageConnector = require( '../../src/default-plugins/noop-message-connector' );

describe( 'record handler handles messages', function(){
	var recordHandler,
		clientA = new SocketWrapper( new SocketMock() ),
		clientB = new SocketWrapper( new SocketMock() ),
		options = {
			cache: new StorageMock(),
			storage: new StorageMock(),
			logger: new LoggerMock(),
			messageConnector: noopMessageConnector
		};

	it( 'creates the record handler', function(){
		recordHandler = new RecordHandler( options );
		expect( recordHandler.handle ).toBeDefined();
	});

	it( 'creates a non existing record', function(){
		recordHandler.handle( clientA, {
			topic: 'RECORD',
			action: 'CR',
			data: [ 'someRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|R|someRecord|0|{}+') );
	});

	it( 'returns an existing record', function(){
		options.cache.set( 'existingRecord', { _v:3, _d: { firstname: 'Wolfram' } }, function(){} );
		recordHandler.handle( clientA, {
			topic: 'RECORD',
			action: 'CR',
			data: [ 'existingRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|R|existingRecord|3|{"firstname":"Wolfram"}+' ));
	});

	it( 'patches a record', function(){
		recordHandler.handle( clientB, {
			raw: msg( 'R|P|existingRecord|4|lastname|SEgon' ),
			topic: 'RECORD',
			action: 'P',
			data: [ 'existingRecord', 4, 'lastname', 'SEgon' ]
		});

		expect( clientB.socket.lastSendMessage ).toBe( null );
		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|P|existingRecord|4|lastname|SEgon+' ));
	});

	it( 'returns the patched record', function(){
		recordHandler.handle( clientB, {
			topic: 'RECORD',
			action: 'CR',
			data: [ 'existingRecord' ]
		});

		expect( clientB.socket.lastSendMessage ).toBe( msg( 'R|R|existingRecord|4|{"firstname":"Wolfram","lastname":"Egon"}+' ));
	});

	it( 'updates a record', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|5|{"name":"Kowalski"}' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'existingRecord', 5, '{"name":"Kowalski"}' ]
		});

		expect( clientB.socket.lastSendMessage ).toBe( msg( 'R|U|existingRecord|5|{"name":"Kowalski"}+' ) );
		options.cache.get( 'existingRecord', function( error, record ){
			expect( record ).toEqual({ _v: 5, _d: { name: 'Kowalski' } });
		});
	});

	it( 'handles unsubscribe messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|US|someRecord' ),
			topic: 'RECORD',
			action: 'US',
			data: [ 'someRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|A|US|someRecord+' ) );

		recordHandler.handle( clientB, {
			raw: msg( 'R|US|someRecord' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'someRecord', 1, '{"bla":"blub"}' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|A|US|someRecord+' ) );
	});

	it( 'rejects updates for existing versions', function(){
		clientA.user = 'someUser';

		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|5|{"name":"Kowalski"}' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'existingRecord', 5, '{"name":"Kowalski"}' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|E|VERSION_EXISTS|existingRecord|5+' ) );
		expect( options.logger.lastLogMessage ).toBe( msg( 'someUser tried to update record existingRecord to version 5 but it already was 5' ) );
	});

	it( 'handles invalid update messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|6' ),
			topic: 'RECORD',
			action: 'U',
			data: [ 'existingRecord', 6 ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|E|INVALID_MESSAGE_DATA|existingRecord+' ) );
	});

	it( 'handles invalid patch messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|U|existingRecord|6|bla' ),
			topic: 'RECORD',
			action: 'P',
			data: [ 'existingRecord', 6, 'bla']
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|E|INVALID_MESSAGE_DATA|R|U|existingRecord|6|bla+' ) );
	});

	it( 'handles deletion messages', function(){
		recordHandler.handle( clientA, {
			raw: msg( 'R|D|existingRecord' ),
			topic: 'RECORD',
			action: 'D',
			data: [ 'existingRecord' ]
		});

		expect( clientA.socket.lastSendMessage ).toBe( msg( 'R|A|D|existingRecord+' ) );
		expect( clientB.socket.lastSendMessage ).toBe( msg( 'R|A|D|existingRecord+' ) );

		options.cache.get( 'existingRecord', function( error, record ){
			expect( record ).toEqual( null );
		});
	});
});<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from '../templates/components/pan-zoom';

export default Ember.Component.extend({
  layout: layout,
  zooming: false,
  // options which match jquery.panzoom options.
  options: {
    eventNamespace: ".panzoom",
    transition: true,
    cursor: "move",
    disablePan: false,
    disableZoom: false,
    increment: 0.3,
    minScale: 0.4,
    maxScale: 5,
    rangeStep: 0.05,
    duration: 200,
    easing: "ease-in-out",
    contain: false,
    startTransform: undefined,
  },

  // computed alias for property
  eventNamespace: Ember.computed.alias("options.eventNamespace"),
  transition: Ember.computed.alias("options.transition"),
  cursor: Ember.computed.alias("options.eventNamespace"),
  disablePan: Ember.computed.alias("options.cursor"),
  disableZoom: Ember.computed.alias("options.disableZoom"),
  increment: Ember.computed.alias("options.increment"),
  minScale: Ember.computed.alias("options.minScale"),
  maxScale: Ember.computed.alias("options.maxScale"),
  rangeStep: Ember.computed.alias("options.rangeStep"),
  duration: Ember.computed.alias("options.duration"),
  easing: Ember.computed.alias("options.easing"),
  contain: Ember.computed.alias("options.contain"),
  startTransform: Ember.computed.alias("options.startTransform"),

  onZoomChanged: Ember.observer("zooming", function() {
    let zoomOut = this.get("zooming")
    this.get("$panzoom").panzoom('zoom', zoomOut, {
      increment: this.get("increment"),
      animate: false,
    });
  }),

  /*
   * @method observer option change, and set panzoom option
   */
  onOptionChanged: Ember.observer("options", function() {
    this.get("$panzoom")("options", this.get("options"));
  }),

  didInsertElement() {
    var _this = this;
    let panzoom = this.$().panzoom({
      eventNamespace  : this.get("eventNamespace"),
      transition      : this.get("transition"),
      cursor          : this.get("cursor"),
      disablePan      : this.get("disablePan"),
      disableZoom     : this.get("disableZoom"),
      increment       : this.get("increment"),
      minScale        : this.get("minScale"),
      maxScale        : this.get("maxScale"),
      rangeStep       : this.get("rangeStep"),
      duration        : this.get("duration"),
      easing          : this.get("easing"),
      contain         : this.get("contain"),
      startTransform  : this.get("startTransform"),
    })
    .on('onStart', function ($event, panzoom) {
      _this.sendAction('onStart', $event, panzoom);
    })
    .on('onChange', function ($event, panzoom) {
      _this.sendAction('onChange', panzoom);
    })
    .on('onPan', function ($event, panzoom) {
      _this.sendAction('onPan', panzoom);
    })
    .on('onEnd', function ($event, panzoom) {
      _this.sendAction('onEnd', panzoom);
    })
    .on('onReset', function ($event, panzoom) {
      _this.sendAction('onReset', panzoom);
    });

    this.set("$panzoom", panzoom);
    return panzoom;
  },
});<commit_msg>fix computed property for cursor and disable pan. Allow mouse wheel for parent<commit_after>import Ember from 'ember';
import layout from '../templates/components/pan-zoom';

export default Ember.Component.extend({
    layout: layout,
    zoomAnimation: false,
    mousewheel: true,
    // options which match jquery.panzoom options.
    options: {
        eventNamespace: ".panzoom",
        transition: true,
        cursor: "move",
        disablePan: false,
        disableZoom: false,
        increment: 0.5,
        minScale: 1,
        maxScale: 5,
        rangeStep: 0.05,
        duration: 200,
        easing: "ease-in-out",
        contain: false,
        startTransform: undefined,
    },

    // computed alias for property
    eventNamespace: Ember.computed.alias("options.eventNamespace"),
    transition: Ember.computed.alias("options.transition"),
    cursor: Ember.computed.alias("options.cursor"),
    disablePan: Ember.computed.alias("options.disablePan"),
    disableZoom: Ember.computed.alias("options.disableZoom"),
    increment: Ember.computed.alias("options.increment"),
    minScale: Ember.computed.alias("options.minScale"),
    maxScale: Ember.computed.alias("options.maxScale"),
    rangeStep: Ember.computed.alias("options.rangeStep"),
    duration: Ember.computed.alias("options.duration"),
    easing: Ember.computed.alias("options.easing"),
    contain: Ember.computed.alias("options.contain"),
    startTransform: Ember.computed.alias("options.startTransform"),
    /*
     * @method observer option change, and set panzoom option
     */
    onOptionChanged: Ember.observer("options", function () {
        this.get("$panzoom")("options", this.get("options"));
    }),

    onMouseWheel(e) {
        e.preventDefault();
        let delta = e.delta || e.originalEvent.wheelDelta;
        let zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0;
        this.get("$panzoom").panzoom('zoom', zoomOut, {
            increment: 0.1,
            animate: this.get("zoomAnimation"),
        });
    },

    didInsertElement() {
        var _this = this;
        let $panzoom = this.$().panzoom({
            eventNamespace: this.get("eventNamespace"),
            transition: this.get("transition"),
            cursor: this.get("cursor"),
            disablePan: this.get("disablePan"),
            disableZoom: this.get("disableZoom"),
            increment: this.get("increment"),
            minScale: this.get("minScale"),
            maxScale: this.get("maxScale"),
            rangeStep: this.get("rangeStep"),
            duration: this.get("duration"),
            easing: this.get("easing"),
            contain: this.get("contain"),
            startTransform: this.get("startTransform"),
        })
        .on('onStart', function ($event, panzoom) {
            _this.sendAction('onStart', $event, panzoom);
        })
        .on('onChange', function ($event, panzoom) {
            _this.sendAction('onChange', panzoom);
        })
        .on('onPan', function ($event, panzoom) {
            _this.sendAction('onPan', panzoom);
        })
        .on('onEnd', function ($event, panzoom) {
            _this.sendAction('onEnd', panzoom);
        })
        .on('onReset', function ($event, panzoom) {
            _this.sendAction('onReset', panzoom);
        });
        if (this.get("mousewheel")) {
            let $parent = $panzoom.parent();
            $parent.on('mousewheel.focal', this.onMouseWheel.bind(this));
            this.set("mousewheelHandled", true);
        }
        this.set("$panzoom", $panzoom);
        return $panzoom;
    },

    willDestroyElement() {
        if (this.get("mousewheelHandled")) {
            let $parent = this.$().parent();
            $parent.off('mousewheel.focal', this.onMouseWheel.bind(this));
        }
    },
});<|endoftext|>


<commit_before>/**
 * Sample LDNode user profile, for use with `solid-profile-test.js`
 */
module.exports = `@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix sp: <http://www.w3.org/ns/pim/space#>.
@prefix loc: </>.
@prefix terms: <http://www.w3.org/ns/solid/terms#>.
@prefix inbox: </inbox/>.

<>
  a foaf:PersonalProfileDocument;
  foaf:primaryTopic <#me>.

<#me>
    a    foaf:Person;
    sp:preferencesFile
       </settings/test-prefs.ttl>;

    sp:storage
       loc:;
    terms:inbox
       inbox:.
`
<commit_msg>Use solid:inbox<commit_after>/**
 * Sample LDNode user profile, for use with `solid-profile-test.js`
 */
module.exports = `@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix sp: <http://www.w3.org/ns/pim/space#>.
@prefix loc: </>.
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix inbox: </inbox/>.

<>
  a foaf:PersonalProfileDocument;
  foaf:primaryTopic <#me>.

<#me>
    a    foaf:Person;
    sp:preferencesFile
       </settings/test-prefs.ttl>;

    sp:storage
       loc:;
    ldp:inbox
       inbox:.
`
<|endoftext|>


<commit_before>class OccurrenceCollection {
    constructor(goals) {
        this.goals = goals;
    }
}

module.exports = OccurrenceCollection;
<commit_msg>Adds constructor for occurrence collection<commit_after>class OccurrenceCollection {
    // Monoid a => a -> a -> a -> a -> OccurrenceCollection
    constructor(goals, shotsOnTargetNoGoal, shotsOffTarget, shots) {
        this.goals = goals;
        this.shotsOnTargetNoGoal = shotsOnTargetNoGoal;
        this.shotsOffTarget = shotsOffTarget;
        this.shots = shots;
    }

    // Monoid a => OccurrenceCollection ~> a
    get shotsOnTarget() {

    }
}

module.exports = OccurrenceCollection;
<|endoftext|>


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

var getPageData = function(title, callback){
    //this is the link format
    var link = "/starcraft2/api.php?format=json&action=query&titles="+ title + "&prop=revisions&rvprop=content";

    //here we have the variable we're going to run the callback on
    var holder;

    //these are the options for the http request
    var options = {
	host: 'wiki.teamliquid.net',
	port: 80,
	path: link
    };

    //do a get request
    http.get(options, function(resp){
	var output = '';

	//put together the output
	resp.on('data', function(chunk){
	    output += chunk;
	});

	//when we're at the end, put the object together and store it
	resp.on('end', function(){
	    holder = JSON.parse(output);
	    //console.log("In end function");
	    //console.log(resp.statusCode);
	    //console.log(holder);

	    callback(holder);
	});
    });
};

var parsePage = function(page){
    //first we split it into an array called lines
    var lines = page.split(/\r\n|\r|\n/g);
    var count = 1;
    var inBracket = false;
    var result;

    for(i in lines){
	if(/{{(.*)bracket$/i.test(lines[i])){
	    inBracket = true;
	}
	if(inBracket){
	    if(/\|R(\d+)(D|W)\d+race=([ztpr])/i.test(lines[i])){
		result = /\|R(\d+)(D|W)\d+race=([ztpr])/i.exec(lines[i]);
		console.log("Found Round " + result[1] + " " + result[2] + " race: " + result[3]);
	    }
	}
	if(/{{:(.*)}}/.test(lines[i])){
	    result = /{{:(.*)}}/.exec(lines[i]);
	    console.log("found link: ");
	    console.log(result[1]);
	}
    }
};

var parseGroupStage = function(lines) {
	var inGroupTable = false,
		result;

	for(i in lines){
		if(/\{\{(Template:)?GroupTableStart/i.test(lines[i])) {
			inGroupTable = true;
		}
		if(inGroupTable){
			if(/\{\{(Template\:)*GroupTableSlot[\s]?\|(.*)race=([ztpr])/i.test(lines[i])) {
				result = /\{\{(Template\:)*GroupTableSlot[\s]*\|.*race=([ztpr])/i.exec(lines[i]);
				console.log("Found Group Stage " + groupStageCount + " race:", result[2]);
			}
		}
	}
};

module.exports.getPageData = getPageData;
module.exports.parsePage = parsePage;<commit_msg>Added support for headings to separate group stages<commit_after>var http = require('http');

var getPageData = function(title, callback){
    //this is the link format
    var link = "/starcraft2/api.php?format=json&action=query&titles="+ title + "&prop=revisions&rvprop=content";

    //here we have the variable we're going to run the callback on
    var holder;

    //these are the options for the http request
    var options = {
	host: 'wiki.teamliquid.net',
	port: 80,
	path: link
    };

    //do a get request
    http.get(options, function(resp){
	var output = '';

	//put together the output
	resp.on('data', function(chunk){
	    output += chunk;
	});

	//when we're at the end, put the object together and store it
	resp.on('end', function(){
	    holder = JSON.parse(output);
	    //console.log("In end function");
	    //console.log(resp.statusCode);
	    //console.log(holder);

	    callback(holder);
	});
    });
};

var parsePage = function(page){
    //first we split it into an array called lines
    var lines = page.split(/\r\n|\r|\n/g);
    var count = 1;
    var inBracket = false;
    var result;

    for(i in lines){
	if(/{{(.*)bracket$/i.test(lines[i])){
	    inBracket = true;
	}
	if(inBracket){
	    if(/\|R(\d+)(D|W)\d+race=([ztpr])/i.test(lines[i])){
		result = /\|R(\d+)(D|W)\d+race=([ztpr])/i.exec(lines[i]);
		console.log("Found Round " + result[1] + " " + result[2] + " race: " + result[3]);
	    }
	}
	if(/{{:(.*)}}/.test(lines[i])){
	    result = /{{:(.*)}}/.exec(lines[i]);
	    console.log("found link: ");
	    console.log(result[1]);
	}
    }
};

var parseGroupStage = function(lines) {
	var inGroupStage = false,
		groupStageCount = 1,
		groupStageHeadingLevel = 0,
		inGroupTable = false,
		result;

	for(i in lines){
		// If we are in a group stage section, look for a heading that could close this section
		if (inGroupStage && /^(=+).*=+$/.test(lines[i])) {
			result = /^(=+).*=+$/.exec(lines[i]);
			// Close the current group stage if section ends
			// (new heading with at same level, or level closer to 1)
			if (result[1].match(/=/g).length <= groupStageHeadingLevel) {
				groupStageCount++;
				inGroupStage = false;
				groupStageHeadingLevel = 0;
			}
		}
		// Look for a Group Stage heading (not mandatory)
		if(/^(=+)[\s]*Group Stage.*=+$/i.test(lines[i])) {
			result = /^(=+)[\s]*Group Stage.*=+$/i.exec(lines[i]);
			inGroupStage = true;
			groupStageHeadingLevel = result[1].match(/=/g).length;
		}
		// Look for a GroupTableStart line
		if(/\{\{(Template:)?GroupTableStart/i.test(lines[i])) {
			inGroupTable = true;
		}
		if(inGroupTable){
			if(/\{\{(Template\:)*GroupTableSlot[\s]?\|(.*)race=([ztpr])/i.test(lines[i])) {
				result = /\{\{(Template\:)*GroupTableSlot[\s]*\|.*race=([ztpr])/i.exec(lines[i]);
				console.log("Found Group Stage " + groupStageCount + " race:", result[2]);
			}
		}
	}
};

module.exports.getPageData = getPageData;
module.exports.parsePage = parsePage;<|endoftext|>


<commit_before>var assert = require('chai').assert;
var ss = require('../../');

function rnd(x) {
    return Math.round(x * 1000) / 1000;
}

describe('sample variance', function() {
    it('can get the sample variance of a six-sided die', function() {
        assert.equal(rnd(ss.sample_variance([1, 2, 3, 4, 5, 6])), 3.5);
    });

    it('the sample variance of two numbers that are the same is 0', function() {
        assert.equal(rnd(ss.sample_variance([1, 1])), 0);
    });

    it('the sample variance of one number is null', function() {
        assert.equal(ss.sample_variance([1]), null);
    });

    it('the sample variance of no numbers is null', function() {
        assert.equal(ss.sample_variance([]), null);
    });
});

describe('sample covariance', function() {
    it('can get perfect negative covariance', function() {
        var x = [1, 2, 3, 4, 5, 6];
        var y = [6, 5, 4, 3, 2, 1];
        assert.equal(rnd(ss.sample_covariance(x, y)), -3.5);
    });

    it('covariance of something with itself is its variance', function() {
        var x = [1, 2, 3, 4, 5, 6];
        assert.equal(rnd(ss.sample_covariance(x, x)), 3.5);
    });

    it('covariance is zero for something with no correlation', function() {
        var x = [1, 2, 3, 4, 5, 6];
        var y = [1, 1, 2, 2, 1, 1];
        assert.equal(rnd(ss.sample_covariance(x, y)), 0);
    });
});
<commit_msg>Add confirmed sample variance test<commit_after>var assert = require('chai').assert;
var ss = require('../../');

function rnd(x) {
    return Math.round(x * 1000) / 1000;
}

describe('sample variance', function() {
    it('can get the sample variance of a six-sided die', function() {
        assert.equal(rnd(ss.sample_variance([1, 2, 3, 4, 5, 6])), 3.5);
    });

    // confirmed in R
    //
    // > var(1:10)
    // [1] 9.166667
    it('can get the sample variance of numbers 1-10', function() {
        assert.equal(rnd(ss.sample_variance([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])), 9.167);
    });

    it('the sample variance of two numbers that are the same is 0', function() {
        assert.equal(rnd(ss.sample_variance([1, 1])), 0);
    });

    it('the sample variance of one number is null', function() {
        assert.equal(ss.sample_variance([1]), null);
    });

    it('the sample variance of no numbers is null', function() {
        assert.equal(ss.sample_variance([]), null);
    });
});

describe('sample covariance', function() {
    it('can get perfect negative covariance', function() {
        var x = [1, 2, 3, 4, 5, 6];
        var y = [6, 5, 4, 3, 2, 1];
        assert.equal(rnd(ss.sample_covariance(x, y)), -3.5);
    });

    it('covariance of something with itself is its variance', function() {
        var x = [1, 2, 3, 4, 5, 6];
        assert.equal(rnd(ss.sample_covariance(x, x)), 3.5);
    });

    it('covariance is zero for something with no correlation', function() {
        var x = [1, 2, 3, 4, 5, 6];
        var y = [1, 1, 2, 2, 1, 1];
        assert.equal(rnd(ss.sample_covariance(x, y)), 0);
    });
});
<|endoftext|>


<commit_before>QUnit.module("Canvas Addon");

QUnit.asyncTest("Canvas pixels", function (assert) {
	var context,
		canvas = document.getElementById('qunit-canvas'),
		imageObj = new Image();
	try {
		context = canvas.getContext('2d');
	} catch(e) {
		// probably no canvas support, just exit
		return;
	}

	QUnit.expect(17);

	// how to use pixelEqual() in conjunction with HTML drawing
	context.fillStyle = 'rgba(0, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 255, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 255, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 255, 255);
	context.clearRect(0, 0, 5, 5);

	// how to use pixelEqual() in conjunction with drawImage()
	imageObj.onload = function() {
		context.drawImage( imageObj, 0, 0 );
		assert.pixelEqual( canvas, 3, 3, 0, 255, 0, 255, "green pixel" );
		QUnit.start();
	};
	imageObj.src = "./0-255-0.gif";
});
<commit_msg>Remove bad comment, leftover from rebasing<commit_after>QUnit.module("Canvas Addon");

QUnit.asyncTest("Canvas pixels", function (assert) {
	var context,
		canvas = document.getElementById('qunit-canvas'),
		imageObj = new Image();
	try {
		context = canvas.getContext('2d');
	} catch(e) {
		// probably no canvas support, just exit
		return;
	}

	QUnit.expect(17);

	context.fillStyle = 'rgba(0, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 255, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 255, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 255, 255);
	context.clearRect(0, 0, 5, 5);

	// how to use pixelEqual() in conjunction with drawImage()
	imageObj.onload = function() {
		context.drawImage( imageObj, 0, 0 );
		assert.pixelEqual( canvas, 3, 3, 0, 255, 0, 255, "green pixel" );
		QUnit.start();
	};
	imageObj.src = "./0-255-0.gif";
});
<|endoftext|>