<commit_before>const stripe = require('stripe');
const {agentProvider, mockManager, fixtureManager} = require('../../utils/e2e-framework');

let agent;

describe('Members API', function () {
    before(async function () {
        process.env.WEBHOOK_SECRET = 'pissoff';
        // Weird - most of the mocks happen after getting the agent
        // but to mock stripe we want to fake the stripe keys in the settings.
        // And it's initialised at boot - so mocking it before
        // Probably wanna replace this with a settinfs fixture mock or smth??
        mockManager.setupStripe();
        agent = await agentProvider.getMembersAPIAgent();
        await fixtureManager.init('members');
    });

    beforeEach(function () {
        mockManager.mockLabsEnabled('multipleProducts');
        mockManager.mockMail();
        mockManager.mockStripe();
    });

    afterEach(function () {
        mockManager.restore();
    });

    it('Can communicate with the frontend Members API', async function () {
        await agent.get('/api/site/')
            .expectStatus(200);
    });

    describe('/webhooks/stripe/', function () {
        it('Responds with a 401 when the signature is invalid', async function () {
            await agent.post('/webhooks/stripe/')
                .body({
                    fake: 'data'
                })
                .header('stripe-signature', 'dodgy')
                .expectStatus(401);
        });

        it('Responds with a 200 to unknown events with valid signature', async function () {
            const webhookPayload = JSON.stringify({
                type: 'unknown',
                data: {
                    id: 'id_123'
                }
            });
            const webhookSignature = stripe.webhooks.generateTestHeaderString({
                payload: webhookPayload,
                secret: process.env.WEBHOOK_SECRET
            });

            await agent.post('/webhooks/stripe/')
                .body(webhookPayload)
                .header('stripe-signature', webhookSignature)
                .expectStatus(200);
        });
    });
});
<commit_msg>Added test for checkout.session.completed (#14149)<commit_after>const assert = require('assert');
const nock = require('nock');
const stripe = require('stripe');
const {agentProvider, mockManager, fixtureManager} = require('../../utils/e2e-framework');

let membersAgent;
let adminAgent;

describe('Members API', function () {
    before(async function () {
        process.env.WEBHOOK_SECRET = 'pissoff';
        // Weird - most of the mocks happen after getting the agent
        // but to mock stripe we want to fake the stripe keys in the settings.
        // And it's initialised at boot - so mocking it before
        // Probably wanna replace this with a settinfs fixture mock or smth??
        mockManager.setupStripe();
        membersAgent = await agentProvider.getMembersAPIAgent();
        adminAgent = await agentProvider.getAdminAPIAgent();
        await fixtureManager.init('members');
        await adminAgent.loginAsOwner();
    });

    beforeEach(function () {
        mockManager.mockLabsEnabled('multipleProducts');
        mockManager.mockMail();
        mockManager.mockStripe();
    });

    afterEach(function () {
        mockManager.restore();
    });

    it('Can communicate with the frontend Members API', async function () {
        await membersAgent.get('/api/site/')
            .expectStatus(200);
    });

    describe('/webhooks/stripe/', function () {
        it('Responds with a 401 when the signature is invalid', async function () {
            await membersAgent.post('/webhooks/stripe/')
                .body({
                    fake: 'data'
                })
                .header('stripe-signature', 'dodgy')
                .expectStatus(401);
        });

        it('Responds with a 200 to unknown events with valid signature', async function () {
            const webhookPayload = JSON.stringify({
                type: 'unknown',
                data: {
                    id: 'id_123'
                }
            });
            const webhookSignature = stripe.webhooks.generateTestHeaderString({
                payload: webhookPayload,
                secret: process.env.WEBHOOK_SECRET
            });

            await membersAgent.post('/webhooks/stripe/')
                .body(webhookPayload)
                .header('stripe-signature', webhookSignature)
                .expectStatus(200);
        });

        describe('checkout.session.completed', function () {
            it('Will create a member if one does not exist', async function () {
                const webhookPayload = JSON.stringify({
                    type: 'checkout.session.completed',
                    data: {
                        object: {
                            mode: 'subscription',
                            customer: 'cus_123',
                            subscription: 'sub_123',
                            metadata: {}
                        }
                    }
                });

                const webhookSignature = stripe.webhooks.generateTestHeaderString({
                    payload: webhookPayload,
                    secret: process.env.WEBHOOK_SECRET
                });

                const subscription = {
                    id: 'sub_123',
                    customer: 'cus_123',
                    status: 'active',
                    items: {
                        type: 'list',
                        data: [{
                            id: 'item_123',
                            price: {
                                id: 'price_123',
                                product: 'product_123',
                                active: true,
                                nickname: 'Monthly',
                                currency: 'USD',
                                recurring: {
                                    interval: 'month'
                                },
                                unit_amount: 500,
                                type: 'recurring'
                            }
                        }]
                    },
                    start_date: Date.now() / 1000,
                    current_period_end: Date.now() / 1000 + (60 * 60 * 24 * 31),
                    cancel_at_period_end: false
                };

                const customer = {
                    id: 'cus_123',
                    name: 'Test Member',
                    email: 'checkout-webhook-test@email.com',
                    subscriptions: {
                        type: 'list',
                        data: [subscription]
                    }
                };

                nock('https://api.stripe.com')
                    .persist()
                    .get(/v1\/.*/)
                    .reply((uri, body) => {
                        const [match, resource, id] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null];

                        if (!match) {
                            return [500];
                        }

                        if (resource === 'customers') {
                            return [200, customer];
                        }

                        if (resource === 'subscriptions') {
                            return [200, subscription];
                        }
                    });

                { // ensure member didn't already exist
                    const {body} = await adminAgent.get('/members/?search=checkout-webhook-test@email.com');
                    assert.equal(body.members.length, 0, 'A member already existed');
                }

                await membersAgent.post('/webhooks/stripe/')
                    .body(webhookPayload)
                    .header('stripe-signature', webhookSignature);

                const {body} = await adminAgent.get('/members/?search=checkout-webhook-test@email.com');
                assert.equal(body.members.length, 1, 'The member was not created');
                const member = body.members[0];

                assert.equal(member.status, 'paid', 'The member should be "paid"');
                assert.equal(member.subscriptions.length, 1, 'The member should have a single subscription');

                mockManager.assert.sentEmail({
                    subject: '🙌 Thank you for signing up to Ghost!',
                    to: 'checkout-webhook-test@email.com'
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>import { Chromeless }  from 'chromeless';
import { expect } from 'chai';
import { download } from '../utils';
const WEBSITE_URL = "https://staging.opencollective.com";
// const WEBSITE_URL = "http://localhost:3030";

describe("logged out", () => {
  let chromeless;

  before((done) => {
    chromeless = new Chromeless({
      remote: true,
      viewport: { width: 768, height: 1024 }
    });
    done();
  })

  after(async () => await chromeless.end());

  it("load collective page", async function() {

    this.timeout(20000);

    const screenshot = await chromeless
      .goto(`${WEBSITE_URL}/webpack`)
      .wait('section#sponsors', 2000)
      .wait('section#backers', 2000)
      .wait('section#budget', 2000)
      .screenshot();

    download("collective_page", screenshot);
    const balance = await chromeless.evaluate(() => document.querySelector('.balance').innerText);
    console.log(">>> balance", balance);
    expect(balance).to.match(/\$[0-9]/);
  });

  it("filter transactions", async function() {

    this.timeout(20000);

    const screenshot = await chromeless
      .goto(`${WEBSITE_URL}/webpack`)
      .wait('#transactions .filterBtn', 4000)
      .scrollToElement('#transactions')
      .click('#transactions .filterBtn:nth-of-type(3)')
      .wait('.transaction.debit', 4000)
      .screenshot();

    download("filter_transactions", screenshot);
    const numberOfDebitTransactions = await chromeless.evaluate(() => document.querySelectorAll('.transaction.debit').length);
    expect(numberOfDebitTransactions).to.equal(5);
  });

  it("clicks on submit new expense", async function() {
    this.timeout(20000);
    const screenshot = await chromeless
      .goto(`${WEBSITE_URL}/webpack`)
      .wait('.SubmitExpenseBtn')
      .scrollToElement('.SubmitExpenseBtn')
      .wait(500)
      .click('.SubmitExpenseBtn')
      .wait(1500)
      .screenshot();

    download("new_expense", screenshot);
    const url = await chromeless.evaluate(() => window.location.href)
    expect(url).to.contain(`${WEBSITE_URL}/webpack/expenses/new`);
  });
});
<commit_msg>increase time to scroll<commit_after>import { Chromeless }  from 'chromeless';
import { expect } from 'chai';
import { download } from '../utils';
const WEBSITE_URL = "https://staging.opencollective.com";
// const WEBSITE_URL = "http://localhost:3030";

describe("logged out", () => {
  let chromeless;

  before((done) => {
    chromeless = new Chromeless({
      remote: true,
      viewport: { width: 768, height: 1024 }
    });
    done();
  })

  after(async () => await chromeless.end());

  it("load collective page", async function() {

    this.timeout(20000);

    const screenshot = await chromeless
      .goto(`${WEBSITE_URL}/webpack`)
      .wait('section#sponsors', 2000)
      .wait('section#backers', 2000)
      .wait('section#budget', 2000)
      .screenshot();

    download("collective_page", screenshot);
    const balance = await chromeless.evaluate(() => document.querySelector('.balance').innerText);
    console.log(">>> balance", balance);
    expect(balance).to.match(/\$[0-9]/);
  });

  it("filter transactions", async function() {

    this.timeout(20000);

    const screenshot = await chromeless
      .goto(`${WEBSITE_URL}/webpack`)
      .wait('#transactions .filterBtn', 4000)
      .scrollToElement('#transactions')
      .click('#transactions .filterBtn:nth-of-type(3)')
      .wait('.transaction.debit', 4000)
      .screenshot();

    download("filter_transactions", screenshot);
    const numberOfDebitTransactions = await chromeless.evaluate(() => document.querySelectorAll('.transaction.debit').length);
    expect(numberOfDebitTransactions).to.equal(5);
  });

  it("clicks on submit new expense", async function() {
    this.timeout(20000);
    const screenshot = await chromeless
      .goto(`${WEBSITE_URL}/webpack`)
      .wait('.SubmitExpenseBtn')
      .scrollToElement('.SubmitExpenseBtn')
      .wait(750)
      .click('.SubmitExpenseBtn')
      .wait(1500)
      .screenshot();

    download("new_expense", screenshot);
    const url = await chromeless.evaluate(() => window.location.href)
    expect(url).to.contain(`${WEBSITE_URL}/webpack/expenses/new`);
  });
});
<|endoftext|>


<commit_before>'use strict';

function NormalLevelFactory(context, audioContext) {
  if(!(this instanceof NormalLevelFactory))
    return new NormalLevelFactory(context, audioContext);
  this.isDuringDevelopment = false;
  this.context = context;
  this.audioContext = audioContext;
  this.startAudioBufferPromise = this.loadAudioBuffer('sounds/lunardrive_drip.wav');
  this.warpAudioBufferPromise = this.loadAudioBuffer('sounds/univ-lyon3_cannet.wav')
}

NormalLevelFactory.prototype.loadAudioBuffer = function(bufferPath) {
  return new Promise((fulfill, reject) => {
    const request = new XMLHttpRequest;
    request.open('GET', bufferPath);
    request.responseType = 'arraybuffer';
    request.onload = () => fulfill(this.audioContext.decodeAudioData(request.response));
    request.onerror = () => reject(Error('status: '+request.status));
    request.send();
  });
}

NormalLevelFactory.prototype.createLevelNumber = function(n, respawnInfo) {
  const levelArgFactory = NormalLevelFactory.levelArgFactories[n];
  if(!levelArgFactory)
    return null;
  const levelArgs = levelArgFactory.call(this);
  levelArgs.respawnInfo = respawnInfo;
  const startCheckpoint =
    this.createTypicalCheckpoint(levelArgs.player.x, levelArgs.player.y);
  levelArgs.gameplayObjects.push(startCheckpoint);
  const playerSoundEmitter = this.createTypicalPlayerSoundEmitter();
  levelArgs.gameplayObjects.push(playerSoundEmitter);
  levelArgs.context = this.context;
  return Level(levelArgs);
}

NormalLevelFactory.prototype.createTypicalPlayer = function(x, y) {
  return Player({
    shape : Circle({
      x : x,
      y : y,
      r : 10,
      style : '#FFF',
      filled : true,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalPlayerTrail = function() {
  return PlayerTrail({
    lineWidth : 2,
    smoothness : 8,
    style : '#444',
  });
}

NormalLevelFactory.prototype.createTypicalGoal = function(x, y) {
  return Goal({
    shape : Circle({
      x : x,
      y : y,
      r : 30,
      style : '#FFF',
      filled : false,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalRectangleObstacle =
function(method, x, y, width, height, style) {
  return Obstacle({
    shape : Rectangle[method]({
      x : x,
      y : y,
      width : width,
      height : height,
      style : (this.isDuringDevelopment && style) || '#444',
    }),
  });
}

NormalLevelFactory.prototype.createTypicalBounds = function(width, height) {
  return Bounds({
    shape : Rectangle.fromCorner({
      x : 0,
      y : 0,
      width : width,
      height : height,
      style : 'transparent',
    }),
  });
}

NormalLevelFactory.prototype.createTypicalCheckpoint = function(x, y) {
  return Checkpoint({
    shape : Circle({
      x : x,
      y : y,
      r : 20,
    }),
    activeStyle : '#FFF',
    achievedStyle : '#444',
  });
}

NormalLevelFactory.prototype.createTypicalKeyGuide = function(x, y) {
  return KeyGuide({
    wasdRadius : 40,
    arrowRadius : 70,
    style : 'white',
    fontFamily : 'mono',
    fontSize : 32,
    shape : Circle({
      x : x,
      y : y,
      r : 50,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalMovementGuide =
function(text, textX, textY, x, y, width, height) {
  return MovementGuide({
    text : text,
    textX : textX,
    textY : textY,
    style : 'white',
    fontFamily : 'mono',
    fontSize : 32,
    shape : Rectangle.fromCorner({
      x : x,
      y : y,
      width : width,
      height : height,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalPlayerSoundEmitter = function() {
  return PlayerSoundEmitter({
    audioContext : this.audioContext,
    startAudioBufferPromise : this.startAudioBufferPromise,
    warpAudioBufferPromise : this.warpAudioBufferPromise,
  });
}

NormalLevelFactory.prototype.rectObstacle = function(cornerX, cornerY, width, height, style) {
  return this.createTypicalRectangleObstacle('fromCorner', cornerX, cornerY,
                                             width, height, style);
}

NormalLevelFactory.prototype.getLevelCount = function() {
  return NormalLevelFactory.levelArgFactories.length;
}

NormalLevelFactory.levelArgFactories = [
  function() {
    return {
      victoryMessages : ['You won, next level:'],
      failureMessages : ["It won't get easier."],
      player : this.createTypicalPlayer(200, 200),
      gameplayObjects : [
        this.createTypicalPlayerTrail(),
        this.createTypicalKeyGuide(200, 200),
        this.createTypicalMovementGuide('↓', 200, 302, 100, 400, 250, 100),
        this.createTypicalMovementGuide('↓', 200, 334, 100, 400, 250, 100),
        this.createTypicalMovementGuide('↓', 232, 334, 100, 400, 250, 100),
        this.createTypicalMovementGuide('↓', 168, 334, 100, 400, 250, 100),
        this.createTypicalBounds(600, 600),
        this.createTypicalCheckpoint(250, 450),
        this.createTypicalGoal(450, 150),
        this.rectObstacle(0, 0, 100, 600, 'blue'),
        this.rectObstacle(500, 0, 100, 600, 'red'),
        this.rectObstacle(0, 0, 600, 100, 'green'),
        this.rectObstacle(0, 500, 600, 100, 'orange'),
        this.rectObstacle(300, 100, 100, 300, 'brown'),
        this.rectObstacle(100, 350, 200, 50, 'navy'),
        this.rectObstacle(400, 200, 100, 50, 'navy'),
        this.rectObstacle(350, 400, 50, 100, 'yellow'),
      ],
    };
  },

  function() {
    return {
      victoryMessages :  ['Some progress.', 'That was okay.'],
      failureMessages : ['Disappointing.', 'Move on, really.', 'Embarrassed yet?'],
      player : this.createTypicalPlayer(60, 540),
      gameplayObjects : [
        this.createTypicalPlayerTrail(),
        this.createTypicalBounds(600, 600),
        this.createTypicalCheckpoint(37.5, 270),
        this.createTypicalCheckpoint(327.5, 60),
        this.createTypicalGoal(525, 60),
        this.rectObstacle(75, 0, 70, 120, 'blue'),
        this.rectObstacle(205, 0, 70, 120, 'green'),
        this.rectObstacle(380, 0, 70, 120, 'yellow'),
        this.rectObstacle(75, 120, 450, 120, 'orange'),
        this.rectObstacle(450, 240, 75, 120, 'red'),
        this.rectObstacle(575, 120, 25, 240, 'magenta'),
        this.rectObstacle(550, 120, 25, 120, 'purple'),
        this.rectObstacle(0, 300, 450, 60, 'gray'),
        this.rectObstacle(0, 360, 200, 120, 'indianred'),
        this.rectObstacle(400, 360, 200, 120, 'pink'),
      ],
    };
  },

  function() {
    return {
      victoryMessages : ['How quick. <- joke', 'Wooow, finally.'],
      failureMessages :  ['Once more?'],
      player : this.createTypicalPlayer(80, 30),
      gameplayObjects : [
        this.createTypicalPlayerTrail(),
        this.createTypicalBounds(600, 600),
        this.createTypicalCheckpoint(250, 510),
        this.createTypicalCheckpoint(210, 330),
        this.createTypicalCheckpoint(290, 150),
        this.createTypicalGoal(560, 60),
        this.rectObstacle(0, 120, 20, 60, 'blue'),
        this.rectObstacle(40, 180, 20, 120, 'yellow'),
        this.rectObstacle(20, 300, 40, 60, 'blue'),
        this.rectObstacle(40, 360, 40, 60, 'blue'),
        this.rectObstacle(20, 420, 40, 60, 'blue'),
        this.rectObstacle(0, 480, 20, 120, 'orange'),
        this.rectObstacle(40, 540, 40, 60, 'yellow'),
        this.rectObstacle(80, 480, 40, 60, 'teal'),
        this.rectObstacle(120, 540, 120, 60, 'purple'),
        this.rectObstacle(280, 540, 120, 60, 'purple'),
        this.rectObstacle(440, 540, 120, 60, 'purple'),
        this.rectObstacle(180, 480, 40, 60, 'chartreuse'),
        this.rectObstacle(280, 480, 40, 60, 'chartreuse'),
        this.rectObstacle(320, 300, 40, 180, 'navy'),
        this.rectObstacle(360, 360, 40, 120, 'navy'),
        this.rectObstacle(400, 420, 40, 120, 'navy'),
        this.rectObstacle(440, 360, 80, 120, 'navy'),
        this.rectObstacle(520, 420, 20, 60, 'indianred'),
        this.rectObstacle(520, 360, 40, 60, 'indianred'),
        this.rectObstacle(540, 300, 40, 60, 'indianred'),
        this.rectObstacle(560, 240, 40, 60, 'indianred'),
        this.rectObstacle(460, 0, 40, 60, 'darkgreen'),
        this.rectObstacle(400, 60, 120, 60, 'darkgreen'),
        this.rectObstacle(420, 120, 120, 60, 'darkgreen'),
        this.rectObstacle(440, 180, 120, 60, 'darkgreen'),
        this.rectObstacle(400, 240, 120, 60, 'darkgreen'),
        this.rectObstacle(340, 120, 60, 60, 'skyblue'),
        this.rectObstacle(300, 180, 60, 60, 'skyblue'),
        this.rectObstacle(520, 480, 40, 60, 'green'),
        this.rectObstacle(60, 60, 40, 60, 'pink'),
        this.rectObstacle(60, 120, 60, 120, 'white'),
        this.rectObstacle(160, 0, 40, 180, 'orange'),
        this.rectObstacle(240, 0, 40, 120, 'orange'),
        this.rectObstacle(340, 0, 40, 60, 'orange'),
        this.rectObstacle(300, 60, 40, 60, 'orange'),
        this.rectObstacle(180, 180, 20, 60, 'brown'),
        this.rectObstacle(220, 240, 20, 60, 'green'),
        this.rectObstacle(200, 120, 40, 120, 'yellow'),
        this.rectObstacle(240, 180, 40, 60, 'coral'),
        this.rectObstacle(80, 240, 80, 240, 'white'),
        this.rectObstacle(160, 300, 20, 120, 'gray'),
        this.rectObstacle(240, 240, 80, 240, 'red'),
      ],
    };
  },
  function() {
    return {
      victoryMessages : ["That's all."],
      failureMessages : ['This is impossible.'],
      player : this.createTypicalPlayer(300, 300),
      gameplayObjects : [
        this.createTypicalGoal(300, 300),
      ],
    };
  },
]<commit_msg>further MovementGuides<commit_after>'use strict';

function NormalLevelFactory(context, audioContext) {
  if(!(this instanceof NormalLevelFactory))
    return new NormalLevelFactory(context, audioContext);
  this.isDuringDevelopment = false;
  this.context = context;
  this.audioContext = audioContext;
  this.startAudioBufferPromise = this.loadAudioBuffer('sounds/lunardrive_drip.wav');
  this.warpAudioBufferPromise = this.loadAudioBuffer('sounds/univ-lyon3_cannet.wav')
}

NormalLevelFactory.prototype.loadAudioBuffer = function(bufferPath) {
  return new Promise((fulfill, reject) => {
    const request = new XMLHttpRequest;
    request.open('GET', bufferPath);
    request.responseType = 'arraybuffer';
    request.onload = () => fulfill(this.audioContext.decodeAudioData(request.response));
    request.onerror = () => reject(Error('status: '+request.status));
    request.send();
  });
}

NormalLevelFactory.prototype.createLevelNumber = function(n, respawnInfo) {
  const levelArgFactory = NormalLevelFactory.levelArgFactories[n];
  if(!levelArgFactory)
    return null;
  const levelArgs = levelArgFactory.call(this);
  levelArgs.respawnInfo = respawnInfo;
  const startCheckpoint =
    this.createTypicalCheckpoint(levelArgs.player.x, levelArgs.player.y);
  levelArgs.gameplayObjects.push(startCheckpoint);
  const playerSoundEmitter = this.createTypicalPlayerSoundEmitter();
  levelArgs.gameplayObjects.push(playerSoundEmitter);
  levelArgs.context = this.context;
  return Level(levelArgs);
}

NormalLevelFactory.prototype.createTypicalPlayer = function(x, y) {
  return Player({
    shape : Circle({
      x : x,
      y : y,
      r : 10,
      style : '#FFF',
      filled : true,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalPlayerTrail = function() {
  return PlayerTrail({
    lineWidth : 2,
    smoothness : 8,
    style : '#444',
  });
}

NormalLevelFactory.prototype.createTypicalGoal = function(x, y) {
  return Goal({
    shape : Circle({
      x : x,
      y : y,
      r : 30,
      style : '#FFF',
      filled : false,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalRectangleObstacle =
function(method, x, y, width, height, style) {
  return Obstacle({
    shape : Rectangle[method]({
      x : x,
      y : y,
      width : width,
      height : height,
      style : (this.isDuringDevelopment && style) || '#444',
    }),
  });
}

NormalLevelFactory.prototype.createTypicalBounds = function(width, height) {
  return Bounds({
    shape : Rectangle.fromCorner({
      x : 0,
      y : 0,
      width : width,
      height : height,
      style : 'transparent',
    }),
  });
}

NormalLevelFactory.prototype.createTypicalCheckpoint = function(x, y) {
  return Checkpoint({
    shape : Circle({
      x : x,
      y : y,
      r : 20,
    }),
    activeStyle : '#FFF',
    achievedStyle : '#444',
  });
}

NormalLevelFactory.prototype.createTypicalKeyGuide = function(x, y) {
  return KeyGuide({
    wasdRadius : 40,
    arrowRadius : 70,
    style : 'white',
    fontFamily : 'mono',
    fontSize : 32,
    shape : Circle({
      x : x,
      y : y,
      r : 50,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalRectangleMovementGuide =
function(text, textX, textY, x, y, width, height) {
  return MovementGuide({
    text : text,
    textX : textX,
    textY : textY,
    style : 'white',
    fontFamily : 'mono',
    fontSize : 32,
    shape : Rectangle.fromCorner({
      x : x,
      y : y,
      width : width,
      height : height,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalCircleMovementGuide =
function(text, textX, textY, x, y, r) {
  return MovementGuide({
    text : text,
    textX : textX,
    textY : textY,
    style : 'white',
    fontFamily : 'mono',
    fontSize : 32,
    shape : Circle({
      x : x,
      y : y,
      r : r,
    }),
  });
}

NormalLevelFactory.prototype.createTypicalPlayerSoundEmitter = function() {
  return PlayerSoundEmitter({
    audioContext : this.audioContext,
    startAudioBufferPromise : this.startAudioBufferPromise,
    warpAudioBufferPromise : this.warpAudioBufferPromise,
  });
}

NormalLevelFactory.prototype.rectObstacle = function(cornerX, cornerY, width, height, style) {
  return this.createTypicalRectangleObstacle('fromCorner', cornerX, cornerY,
                                             width, height, style);
}

NormalLevelFactory.prototype.getLevelCount = function() {
  return NormalLevelFactory.levelArgFactories.length;
}

NormalLevelFactory.levelArgFactories = [
  function() {
    return {
      victoryMessages : ['You won, next level:'],
      failureMessages : ["It won't get easier."],
      player : this.createTypicalPlayer(200, 200),
      gameplayObjects : [
        this.createTypicalPlayerTrail(),
        this.createTypicalKeyGuide(200, 200),
        this.createTypicalRectangleMovementGuide('↓', 200, 302, 100, 400, 250, 100),
        this.createTypicalRectangleMovementGuide('↓', 200, 334, 100, 400, 250, 100),
        this.createTypicalRectangleMovementGuide('↓', 232, 334, 100, 400, 250, 100),
        this.createTypicalRectangleMovementGuide('↓', 168, 334, 100, 400, 250, 100),
        this.createTypicalCircleMovementGuide('→', 200, 450, 250, 450, 20),
        this.createTypicalRectangleMovementGuide('↑', 450, 300, 400, 100, 100, 100),
        this.createTypicalRectangleMovementGuide('↑', 450, 268, 400, 100, 100, 100),
        this.createTypicalBounds(600, 600),
        this.createTypicalCheckpoint(250, 450),
        this.createTypicalGoal(450, 150),
        this.rectObstacle(0, 0, 100, 600, 'blue'),
        this.rectObstacle(500, 0, 100, 600, 'red'),
        this.rectObstacle(0, 0, 600, 100, 'green'),
        this.rectObstacle(0, 500, 600, 100, 'orange'),
        this.rectObstacle(300, 100, 100, 300, 'brown'),
        this.rectObstacle(100, 350, 200, 50, 'navy'),
        this.rectObstacle(400, 200, 100, 50, 'teal'),
        this.rectObstacle(350, 400, 50, 100, 'yellow'),
      ],
    };
  },

  function() {
    return {
      victoryMessages :  ['Some progress.', 'That was okay.'],
      failureMessages : ['Disappointing.', 'Move on, really.', 'Embarrassed yet?'],
      player : this.createTypicalPlayer(60, 540),
      gameplayObjects : [
        this.createTypicalPlayerTrail(),
        this.createTypicalBounds(600, 600),
        this.createTypicalCheckpoint(37.5, 270),
        this.createTypicalCheckpoint(327.5, 60),
        this.createTypicalGoal(525, 60),
        this.rectObstacle(75, 0, 70, 120, 'blue'),
        this.rectObstacle(205, 0, 70, 120, 'green'),
        this.rectObstacle(380, 0, 70, 120, 'yellow'),
        this.rectObstacle(75, 120, 450, 120, 'orange'),
        this.rectObstacle(450, 240, 75, 120, 'red'),
        this.rectObstacle(575, 120, 25, 240, 'magenta'),
        this.rectObstacle(550, 120, 25, 120, 'purple'),
        this.rectObstacle(0, 300, 450, 60, 'gray'),
        this.rectObstacle(0, 360, 200, 120, 'indianred'),
        this.rectObstacle(400, 360, 200, 120, 'pink'),
      ],
    };
  },

  function() {
    return {
      victoryMessages : ['How quick. <- joke', 'Wooow, finally.'],
      failureMessages :  ['Once more?'],
      player : this.createTypicalPlayer(80, 30),
      gameplayObjects : [
        this.createTypicalPlayerTrail(),
        this.createTypicalBounds(600, 600),
        this.createTypicalCheckpoint(250, 510),
        this.createTypicalCheckpoint(210, 330),
        this.createTypicalCheckpoint(290, 150),
        this.createTypicalGoal(560, 60),
        this.rectObstacle(0, 120, 20, 60, 'blue'),
        this.rectObstacle(40, 180, 20, 120, 'yellow'),
        this.rectObstacle(20, 300, 40, 60, 'blue'),
        this.rectObstacle(40, 360, 40, 60, 'blue'),
        this.rectObstacle(20, 420, 40, 60, 'blue'),
        this.rectObstacle(0, 480, 20, 120, 'orange'),
        this.rectObstacle(40, 540, 40, 60, 'yellow'),
        this.rectObstacle(80, 480, 40, 60, 'teal'),
        this.rectObstacle(120, 540, 120, 60, 'purple'),
        this.rectObstacle(280, 540, 120, 60, 'purple'),
        this.rectObstacle(440, 540, 120, 60, 'purple'),
        this.rectObstacle(180, 480, 40, 60, 'chartreuse'),
        this.rectObstacle(280, 480, 40, 60, 'chartreuse'),
        this.rectObstacle(320, 300, 40, 180, 'navy'),
        this.rectObstacle(360, 360, 40, 120, 'navy'),
        this.rectObstacle(400, 420, 40, 120, 'navy'),
        this.rectObstacle(440, 360, 80, 120, 'navy'),
        this.rectObstacle(520, 420, 20, 60, 'indianred'),
        this.rectObstacle(520, 360, 40, 60, 'indianred'),
        this.rectObstacle(540, 300, 40, 60, 'indianred'),
        this.rectObstacle(560, 240, 40, 60, 'indianred'),
        this.rectObstacle(460, 0, 40, 60, 'darkgreen'),
        this.rectObstacle(400, 60, 120, 60, 'darkgreen'),
        this.rectObstacle(420, 120, 120, 60, 'darkgreen'),
        this.rectObstacle(440, 180, 120, 60, 'darkgreen'),
        this.rectObstacle(400, 240, 120, 60, 'darkgreen'),
        this.rectObstacle(340, 120, 60, 60, 'skyblue'),
        this.rectObstacle(300, 180, 60, 60, 'skyblue'),
        this.rectObstacle(520, 480, 40, 60, 'green'),
        this.rectObstacle(60, 60, 40, 60, 'pink'),
        this.rectObstacle(60, 120, 60, 120, 'white'),
        this.rectObstacle(160, 0, 40, 180, 'orange'),
        this.rectObstacle(240, 0, 40, 120, 'orange'),
        this.rectObstacle(340, 0, 40, 60, 'orange'),
        this.rectObstacle(300, 60, 40, 60, 'orange'),
        this.rectObstacle(180, 180, 20, 60, 'brown'),
        this.rectObstacle(220, 240, 20, 60, 'green'),
        this.rectObstacle(200, 120, 40, 120, 'yellow'),
        this.rectObstacle(240, 180, 40, 60, 'coral'),
        this.rectObstacle(80, 240, 80, 240, 'white'),
        this.rectObstacle(160, 300, 20, 120, 'gray'),
        this.rectObstacle(240, 240, 80, 240, 'red'),
      ],
    };
  },
  function() {
    return {
      victoryMessages : ["That's all."],
      failureMessages : ['This is impossible.'],
      player : this.createTypicalPlayer(300, 300),
      gameplayObjects : [
        this.createTypicalGoal(300, 300),
      ],
    };
  },
]<|endoftext|>


<commit_before>import { createRequestObject, sendRequest } from './utils';

export default class Portal {

  /**
   * Set up our portal instance.
   */
  constructor () {
    this._requestInterceptors = [];
    this._responseInterceptors = [];
    this._errorHandlers = [];
  }

  /**
   * Add an interceptor for modifying a request before it's sent
   * out via AJAX/XHR.
   *
   * @param  {Function} fn
   * @return {this}
   */
  onRequest (fn) {
    // enforce that the given value is a function
    if (typeof fn !== 'function') {
      throw new Error('You must provide a valid function as an interceptor!');
    }
    // add the interceptor to the list of interceptors
    this._requestInterceptors.push(fn);

    return this;
  }

  /**
   * Add an interceptor for modifying a response before it's given
   * to the user's promise subscriber.
   *
   * @param  {Function} fn
   * @return {this}
   */
  onResponse (fn) {
    // enforce that the given value is a function
    if (typeof fn !== 'function') {
      throw new Error('You must provide a valid function as an interceptor!');
    }
    // add the interceptor to the list of interceptors
    this._responseInterceptors.push(fn);

    return this;
  }

  /**
   * Add an error handler that will be invoked whenever a Portal
   * request errors out.
   *
   * @param  {Function} fn
   * @return {this}
   */
  onError (fn) {
    // enforce that the given value is a function
    if (typeof fn !== 'function') {
      throw new Error('You must provide a valid function as an error handler!');
    }
    // add the handler to the list of handlers
    this._errorHandlers.push(fn);

    return this;
  }

  /**
   * Creates an XHR object and sends it out, returning a promise
   * that can be used to subscribe to resolution or rejection
   * states.
   *
   * @param  {Object} req
   * @return {Promise}
   */
  send (req = {}) {
    // create our XHR object for the request
    var xhr = createRequestObject();
    // send the request and get the promise for the result
    var promise = sendRequest(xhr, req, this._requestInterceptors, this._responseInterceptors, this._errorHandlers);
    // attach the XHR object's abort() method to the promise
    promise.abort = xhr.abort.bind(xhr);
    // return the promise
    return promise;
  }

  /**
   * Helper methods for GET, POST, PUT and DELETE.
   */

  get (url, req = {}) {
    this.send(Object.assign({}, req, { method: 'GET', url }));
  }

  post (url, body, req = {}) {
    this.send(Object.assign({}, req, { method: 'POST', url, body }));
  }

  put (url, body, req = {}) {
    this.send(Object.assign({}, req, { method: 'PUT', url, body }));
  }

  delete (url, req = {}) {
    this.send(Object.assign({}, req, { method: 'DELETE', url }));
  }

}
<commit_msg>Add return statements to helper methods to return the promises.<commit_after>import { createRequestObject, sendRequest } from './utils';

export default class Portal {

  /**
   * Set up our portal instance.
   */
  constructor () {
    this._requestInterceptors = [];
    this._responseInterceptors = [];
    this._errorHandlers = [];
  }

  /**
   * Add an interceptor for modifying a request before it's sent
   * out via AJAX/XHR.
   *
   * @param  {Function} fn
   * @return {this}
   */
  onRequest (fn) {
    // enforce that the given value is a function
    if (typeof fn !== 'function') {
      throw new Error('You must provide a valid function as an interceptor!');
    }
    // add the interceptor to the list of interceptors
    this._requestInterceptors.push(fn);

    return this;
  }

  /**
   * Add an interceptor for modifying a response before it's given
   * to the user's promise subscriber.
   *
   * @param  {Function} fn
   * @return {this}
   */
  onResponse (fn) {
    // enforce that the given value is a function
    if (typeof fn !== 'function') {
      throw new Error('You must provide a valid function as an interceptor!');
    }
    // add the interceptor to the list of interceptors
    this._responseInterceptors.push(fn);

    return this;
  }

  /**
   * Add an error handler that will be invoked whenever a Portal
   * request errors out.
   *
   * @param  {Function} fn
   * @return {this}
   */
  onError (fn) {
    // enforce that the given value is a function
    if (typeof fn !== 'function') {
      throw new Error('You must provide a valid function as an error handler!');
    }
    // add the handler to the list of handlers
    this._errorHandlers.push(fn);

    return this;
  }

  /**
   * Creates an XHR object and sends it out, returning a promise
   * that can be used to subscribe to resolution or rejection
   * states.
   *
   * @param  {Object} req
   * @return {Promise}
   */
  send (req = {}) {
    // create our XHR object for the request
    var xhr = createRequestObject();
    // send the request and get the promise for the result
    var promise = sendRequest(xhr, req, this._requestInterceptors, this._responseInterceptors, this._errorHandlers);
    // attach the XHR object's abort() method to the promise
    promise.abort = xhr.abort.bind(xhr);
    // return the promise
    return promise;
  }

  /**
   * Helper methods for GET, POST, PUT and DELETE.
   */

  get (url, req = {}) {
    return this.send(Object.assign({}, req, { method: 'GET', url }));
  }

  post (url, body, req = {}) {
    return this.send(Object.assign({}, req, { method: 'POST', url, body }));
  }

  put (url, body, req = {}) {
    return this.send(Object.assign({}, req, { method: 'PUT', url, body }));
  }

  delete (url, req = {}) {
    return this.send(Object.assign({}, req, { method: 'DELETE', url }));
  }

}
<|endoftext|>


<commit_before>var { CloudContext } = require('./utils');
var randUserId = require('../utils/hooks').randUserId;
var util = require('util');

const someActivityId = 'f9969ca8-e659-11e8-801f-e4a47194940e';
// eslint-disable-next-line no-unused-vars
function log(...args) {
  console.log(
    util.inspect(...args, { showHidden: false, depth: null, colors: true }),
  );
}

describe('Permission checking', () => {
  let ctx = new CloudContext();
  ctx.createUsers();
  describe('When alice tries to impersonate bob', () => {
    let at = new Date().toISOString();
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.feed('user').addActivity({
        actor: ctx.bob.currentUser,
        verb: 'post',
        object: 'I love Alice',
        foreign_id: 'fid:123',
        time: at,
      });
    });
  });
  describe('When alice tries to create another user', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.user(randUserId('someone')).create();
    });
  });
  describe('When alice tries to update bob', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice
        .user(ctx.bob.userId)
        .update({ hacked: true });
    });
  });
  describe('When alice tries to delete bob', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice
        .user(ctx.bob.userId)
        .update({ hacked: true });
    });
  });

  describe('When alice tries to read bobs timeline', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.feed('timeline', ctx.bob.userId).get();
    });
  });

  describe('When alice tries to mark her own notification feed', () => {
    ctx.requestShouldNotError(async () => {
      ctx.response = await ctx.alice
        .feed('notification')
        .get({ mark_seen: true, mark_read: true });
    });
  });

  describe('When alice tries to post to bobs timeline', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice
        .feed('timeline', ctx.bob.userId)
        .addActivity({
          actor: ctx.alice.currentUser,
          verb: 'post',
          object: "I'm writing this directly on your timeline",
        });
    });
  });

  describe('When alice tries to post to someone elses timeline by using to targets', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.feed('user').addActivity({
        actor: ctx.alice.currentUser,
        verb: 'post',
        object: "I'm writing this on your timeline by using to targets",
        to: ['timeline:123'],
      });
    });
  });

  describe('When alice tries to post to someone elses timeline by using target feeds when adding a reaction', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.reactions.add('comment', someActivityId, {
        targetFeeds: ['timeline:123'],
      });
    });
  });

  describe('When alice tries to add a reaction burger with bobs user id', () => {
    ctx.requestShouldError(400, async () => {
      var reaction = {
        user_id: ctx.bob.userId,
        kind: 'like',
        activity_id: someActivityId,
      };
      await ctx.alice.client.post({
        url: ctx.alice.reactions.buildURL(),
        body: reaction,
        signature: ctx.alice.reactions.signature,
      });
    });
  });

  describe('When alice tries to make bob follow her', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice
        .feed('timeline', ctx.bob.userId)
        .follow('user', ctx.alice.userId);
    });
  });

  describe('When alice tries to make bob unfollow her', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice
        .feed('timeline', ctx.bob.userId)
        .unfollow('user', ctx.alice.userId);
    });
  });

  describe('When alice tries to list the followers of bob', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice.feed('timeline', ctx.bob.userId).followers();
    });
  });

  describe('When alice tries to make bob unfollow her', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice.feed('user', ctx.bob.userId).following();
    });
  });

  describe('When alice tries to delete an activity from bob his feed', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice
        .feed('user', ctx.bob.userId)
        .removeActivity(someActivityId);
    });
  });

  describe('When alice tries to delete an activity from her own feed', () => {
    ctx.requestShouldNotError(async () => {
      await ctx.alice.feed('user').removeActivity(someActivityId);
    });
  });
});
<commit_msg>Fix permission tests<commit_after>var { CloudContext } = require('./utils');
var randUserId = require('../utils/hooks').randUserId;
var util = require('util');

const someActivityId = 'f9969ca8-e659-11e8-801f-e4a47194940e';
// eslint-disable-next-line no-unused-vars
function log(...args) {
  console.log(
    util.inspect(...args, { showHidden: false, depth: null, colors: true }),
  );
}

describe('Permission checking', () => {
  let ctx = new CloudContext();
  ctx.createUsers();
  describe('When alice tries to impersonate bob', () => {
    let at = new Date().toISOString();
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.feed('user').addActivity({
        actor: ctx.bob.currentUser,
        verb: 'post',
        object: 'I love Alice',
        foreign_id: 'fid:123',
        time: at,
      });
    });
  });
  describe('When alice tries to create another user', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.user(randUserId('someone')).create();
    });
  });
  describe('When alice tries to update bob', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice
        .user(ctx.bob.userId)
        .update({ hacked: true });
    });
  });
  describe('When alice tries to delete bob', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice
        .user(ctx.bob.userId)
        .update({ hacked: true });
    });
  });

  describe('When alice tries to read bobs timeline', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.feed('timeline', ctx.bob.userId).get();
    });
  });

  describe('When alice tries to mark her own notification feed', () => {
    ctx.requestShouldNotError(async () => {
      ctx.response = await ctx.alice
        .feed('notification')
        .get({ mark_seen: true, mark_read: true });
    });
  });

  describe('When alice tries to post to bobs timeline', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice
        .feed('timeline', ctx.bob.userId)
        .addActivity({
          actor: ctx.alice.currentUser,
          verb: 'post',
          object: "I'm writing this directly on your timeline",
        });
    });
  });

  describe('When alice tries to post to someone elses timeline by using to targets', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.feed('user').addActivity({
        actor: ctx.alice.currentUser,
        verb: 'post',
        object: "I'm writing this on your timeline by using to targets",
        to: ['timeline:123'],
      });
    });
  });

  describe('When alice tries to post to someone elses timeline by using target feeds when adding a reaction', () => {
    ctx.requestShouldError(403, async () => {
      ctx.response = await ctx.alice.reactions.add(
        'comment',
        someActivityId,
        {},
        ['timeline:123'],
      );
    });
  });

  describe('When alice tries to add a reaction burger with bobs user id', () => {
    ctx.requestShouldError(400, async () => {
      var reaction = {
        user_id: ctx.bob.userId,
        kind: 'like',
        activity_id: someActivityId,
      };
      await ctx.alice.post({
        url: ctx.alice.reactions.buildURL(),
        body: reaction,
        signature: ctx.alice.reactions.signature,
      });
    });
  });

  describe('When alice tries to make bob follow her', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice
        .feed('timeline', ctx.bob.userId)
        .follow('user', ctx.alice.userId);
    });
  });

  describe('When alice tries to make bob unfollow her', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice
        .feed('timeline', ctx.bob.userId)
        .unfollow('user', ctx.alice.userId);
    });
  });

  describe('When alice tries to list the followers of bob', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice.feed('timeline', ctx.bob.userId).followers();
    });
  });

  describe('When alice tries to make bob unfollow her', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice.feed('user', ctx.bob.userId).following();
    });
  });

  describe('When alice tries to delete an activity from bob his feed', () => {
    ctx.requestShouldError(403, async () => {
      await ctx.alice
        .feed('user', ctx.bob.userId)
        .removeActivity(someActivityId);
    });
  });

  describe('When alice tries to delete an activity from her own feed', () => {
    ctx.requestShouldNotError(async () => {
      await ctx.alice.feed('user').removeActivity(someActivityId);
    });
  });
});
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Particle Swarm Optimization Visualization
//
// Author : Marc Gumowski
//
// Description : Function allowing to visualize a simple implementation of the  particle
//               swarm optimization algorithm (PSO), using a physical simulation of charged
//               particles.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function psoViz(id, expr, options) {

  ////////////////////////////////////////////////////////
  // Initial options /////////////////////////////////////
  ////////////////////////////////////////////////////////

  var cfg = {
    margin: { top: 10, left: 10, right: 10, bottom: 10 },
    width: Math.min(630, window.innerWidth - 10),
    height: Math.min(480, window.innerHeight - 20),
    grid: { xMin: -2, xMax: 2, yMin: -2, yMax: 2,  },
    radius: 3,
    number: 50,
    color: '#ce2525',
  };

  //Put all of the options into a variable called cfg
	if('undefined' !== typeof options){
	  for(var p in options){
		if('undefined' !== typeof options[p]){ cfg[p] = options[p]; }
	  }
	}

	var scaleX = d3.scaleLinear()
	  .domain([cfg.grid.xMin, cfg.grid.xMax])
	  .range([0, cfg.width]);

	var scaleY = d3.scaleLinear()
	  .domain([cfg.grid.yMin, cfg.grid.yMax])
	  .range([0, cfg.height]);

	function randomize(min, max) {
    return Math.random() * (max - min) + min;
  }

  ////////////////////////////////////////////////////////
  // SVG /////////////////////////////////////////////////
  ////////////////////////////////////////////////////////

	d3.select(id).select("svg").remove();

	var svg = d3.select(id).append("svg")
	    .attr('id', 'psoVizSVG')
			.attr("width",  cfg.width)
			.attr("height", cfg.height);

  ////////////////////////////////////////////////////////
  // Contour /////////////////////////////////////////////
  ////////////////////////////////////////////////////////

  // Create a grid of value
  var n = 240, m = 240, values = new Array(n * m);
  for (var j = 0.5, k = 0; j < m; ++j) {
    for (var i = 0.5; i < n; ++i, ++k) {
      values[k] = expr(cfg.grid.xMin + (cfg.grid.xMax - cfg.grid.xMin) * i / n,
      cfg.grid.yMax - (cfg.grid.yMax - cfg.grid.yMin) * j / m);
    }
  }

  // Plot
  var thresholds = d3.range(1, 21)
      .map(function(p) { return Math.pow(2, p); });

  var contours = d3.contours()
      .size([n, m])
      .thresholds(thresholds);

  var color = d3.scaleLog()
      .domain(d3.extent(thresholds))
      .interpolate(function() { return d3.interpolateYlGnBu; });

  svg.append("g").selectAll("path")
    .data(contours(values))
    .enter().append("path")
      .attr("d", d3.geoPath(d3.geoIdentity().scale(cfg.width / n)))
      .attr("fill", function(d) { return color(d.value); });

  ////////////////////////////////////////////////////////
  // Particles ///////////////////////////////////////////
  ////////////////////////////////////////////////////////

  // Initialize data with best known position pbest and velocity
  var data = new Array(1 * cfg.number);
  for (var l = 0; l < cfg.number; ++l) {
    data[l] = {
      "value": cfg.radius,
      "color": cfg.color,
      "pbest": {
        "x": randomize(scaleX.domain()[0], scaleX.domain()[1]),
        "y": randomize(scaleY.domain()[0], scaleY.domain()[1])
      },
      "pbestEval": [],
      "velocity": {
        "x": 0,
        "y": 0
      }
    };
  }

  // Evaluate pbest
  var pbestEval = [];
  data.forEach(function(d) { d.pbestEval = expr(d.pbest.x, d.pbest.y); });

  console.log(data);

  // Update global best: gbest
  var gbest = []; // return x,y, f(x,y) //Particle ID, function that take the max eval of pbestEval and all infos.

  // Create particle and initialize position with appropriate scale
  var particle = svg.selectAll('.particle')
      .data(data)
      .enter().append("g");

  particle.append('circle')
    .attr('class', 'particle')
    .attr('id', function(d,i) { return "particle" + i;})
    .attr('r', function(d) { return d.value; })
    .attr('cx', function(d) { return scaleX(d.pbest.x); })
    .attr('cy', function(d) { return scaleY(d.pbest.y); })
    .on("click", function(d) { console.log(d); })
    .style('fill', function(d) { return d.color; });

  ////////////////////////////////////////////////////////
  // Simulation //////////////////////////////////////////
  ////////////////////////////////////////////////////////

  // While Criteria
  // Do function Loop
  // else STOP

  // Function loop
  // For each particle
   // For each dimension
    // Update position
    // store in array

  var cxNew = cfg.width / 2,
      cyNew = cfg.height / 2;

    particle.selectAll("circle")
      .transition()
      .duration(function(d) { return 2000 * randomize(1, 2)}) // d.vx * d.vy
      .on("start", function repeat() {
        d3.active(this)
          .attr('cx', function(d) { return cxNew *  randomize(0, 2); }) // d.cxNew
          .attr('cy', function(d) { return cyNew *  randomize(0, 2); }) // d.cyNew
          .transition()
            .on("start", repeat);
      });

  ////////////////////////////////////////////////////////
  // Legend and Buttons //////////////////////////////////
  ////////////////////////////////////////////////////////
}

<commit_msg>Prototype of loop<commit_after>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Particle Swarm Optimization Visualization
//
// Author : Marc Gumowski
//
// Description : Function allowing to visualize a simple implementation of the  particle
//               swarm optimization algorithm (PSO), using a physical simulation of charged
//               particles.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function psoViz(id, expr, options) {

  ////////////////////////////////////////////////////////
  // Initial options /////////////////////////////////////
  ////////////////////////////////////////////////////////

  var cfg = {
    margin: { top: 10, left: 10, right: 10, bottom: 10 },
    width: Math.min(630, window.innerWidth - 10),
    height: Math.min(480, window.innerHeight - 20),
    grid: { xMin: -2, xMax: 2, yMin: -2, yMax: 2,  },
    radius: 3,
    number: 50,
    color: '#ce2525',
  };

  //Put all of the options into a variable called cfg
	if('undefined' !== typeof options){
	  for(var p in options){
		if('undefined' !== typeof options[p]){ cfg[p] = options[p]; }
	  }
	}

	var scaleX = d3.scaleLinear()
	  .domain([cfg.grid.xMin, cfg.grid.xMax])
	  .range([0, cfg.width]);

	var scaleY = d3.scaleLinear()
	  .domain([cfg.grid.yMin, cfg.grid.yMax])
	  .range([0, cfg.height]);

	function randomize(min, max) {
    return Math.random() * (max - min) + min;
  }

  ////////////////////////////////////////////////////////
  // SVG /////////////////////////////////////////////////
  ////////////////////////////////////////////////////////

	d3.select(id).select("svg").remove();

	var svg = d3.select(id).append("svg")
	    .attr('id', 'psoVizSVG')
			.attr("width",  cfg.width)
			.attr("height", cfg.height);

  ////////////////////////////////////////////////////////
  // Contour /////////////////////////////////////////////
  ////////////////////////////////////////////////////////

  // Create a grid of value
  var n = 240, m = 240, values = new Array(n * m);
  for (var j = 0.5, k = 0; j < m; ++j) {
    for (var i = 0.5; i < n; ++i, ++k) {
      values[k] = expr(cfg.grid.xMin + (cfg.grid.xMax - cfg.grid.xMin) * i / n,
      cfg.grid.yMax - (cfg.grid.yMax - cfg.grid.yMin) * j / m);
    }
  }

  // Plot
  var thresholds = d3.range(1, 21)
      .map(function(p) { return Math.pow(2, p); });

  var contours = d3.contours()
      .size([n, m])
      .thresholds(thresholds);

  var color = d3.scaleLog()
      .domain(d3.extent(thresholds))
      .interpolate(function() { return d3.interpolateYlGnBu; });

  svg.append("g").selectAll("path")
    .data(contours(values))
    .enter().append("path")
      .attr("d", d3.geoPath(d3.geoIdentity().scale(cfg.width / n)))
      .attr("fill", function(d) { return color(d.value); });

  ////////////////////////////////////////////////////////
  // Particles ///////////////////////////////////////////
  ////////////////////////////////////////////////////////

  // Initialize data with best known position pbest and velocity
  var data = new Array(1 * cfg.number);
  for (var l = 0; l < cfg.number; ++l) {
    data[l] = {
      "value": cfg.radius,
      "color": cfg.color,
      "pbest": {
        "x": randomize(scaleX.domain()[0], scaleX.domain()[1]),
        "y": randomize(scaleY.domain()[0], scaleY.domain()[1])
      },
      "pbestEval": [],
      "velocity": {
        "x": 0,
        "y": 0
      }
    };
  }

  // Evaluate pbest
  var pbestEval = [];
  data.forEach(function(d) { d.pbestEval = expr(d.pbest.x, d.pbest.y); });

  console.log(data);

  // Update global best: gbest
  var gbest = []; // return x,y, f(x,y) //Particle ID, function that selects data array with min pbestEval, give different color to it

  // Create particle and initialize position with appropriate scale
  var particle = svg.selectAll('.particle')
      .data(data)
      .enter().append("g")
      .append('circle')
      .attr('class', 'particle')
      .attr('id', function(d,i) { return "particle" + i;})
      .attr('r', function(d) { return d.value; })
      .attr('cx', function(d) { return scaleX(d.pbest.x); })
      .attr('cy', function(d) { return scaleY(d.pbest.y); })
      .on("click", function(d) { console.log(d); })
      .style('fill', function(d) { return d.color; });

  ////////////////////////////////////////////////////////
  // Simulation //////////////////////////////////////////
  ////////////////////////////////////////////////////////

  // While Criteria
  // Do function Loop
  // else STOP

  // Function loop
  // For each particle
   // For each dimension
    // Update position
    // store in array

  var cxNew = cfg.width / 2,
      cyNew = cfg.height / 2;

  for (var z = 0; z < 20; z++) {

    console.log(z);

    particle = particle
      .transition()
      .duration(500)
      .attr('cx', function(d) { return cxNew *  randomize(0, 2); }) // d.cxNew
      .attr('cy', function(d) { return cyNew *  randomize(0, 2); }) // d.cyNew
      .style('fill', function(d) { return d.color; });

  }

/*    particle.selectAll("circle")
      .transition()
      .duration(function(d) { return 2000 * randomize(1, 2)}) // d.vx * d.vy
      .on("start", function repeat() {
        d3.active(this)
          .attr('cx', function(d) { return cxNew *  randomize(0, 2); }) // d.cxNew
          .attr('cy', function(d) { return cyNew *  randomize(0, 2); }) // d.cyNew
          .transition()
            .on("start", repeat);
      });*/ // Random moves

  ////////////////////////////////////////////////////////
  // Legend and Buttons //////////////////////////////////
  ////////////////////////////////////////////////////////
}

<|endoftext|>


<commit_before>'use strict'

var bluebird = require('bluebird')
var defaults = require('lodash/defaults')
var unique = require('lodash/uniq')
var toArray = require('lodash/toArray')
var get = require('lodash/get')
var isFunction = require('lodash/isFunction')
var designDocRegex = new RegExp('^_design/')
var toUnderscorePrefix = require('./to-underscore-prefix')

/** @lends Pouchy.prototype */
var publicMethods = {
  /**
   * add a document to the db.
   * @see save
   * @example
   * // with _id
   * p.add({ _id: 'my-sauce', bbq: 'sauce' }).then(function(doc) {
   *   console.log(doc._id, doc._rev, doc.bbq); // 'my-sauce', '1-a76...46c', 'sauce'
   * });
   *
   * // no _id
   * p.add({ peanut: 'butter' }).then(function(doc) {
   *   console.log(doc._id, doc._rev, doc.peanut); // '66188...00BF885E', '1-0d74...7ac', 'butter'
   * });
   * @param {object} doc
   * @param {function} [cb]
   * @returns {Promise}
   */
  add: function add () {
    return this.save.apply(this, arguments)
  },

  /**
   * get all documents from db
   * @example
   * p.all().then((docs) => console.log(`total # of docs: ${docs.length}!`))
   * p.all({ includeDesignDocs: true }).then(function(docs) {
   *    console.log('this will include design docs as well');
   * })
   * @param {object} [opts] defaults to `include_docs: true`. In addition to the usual [PouchDB allDocs options](http://pouchdb.com/api.html#batch_fetch), you may also specify `includeDesignDocs: true` to have CouchDB design documents returned.
   * @param {function} [cb]
   * @returns {Promise} resolves to array of documents (excluding any design documents), vs an object with a `docs` array per Pouch allDocs default
   */
  all: function (opts, cb) {
    opts = defaults(opts || {}, { include_docs: true })
    return this.db.allDocs(opts)
    .then(function handleReceivedDocs (docs) {
      return docs.rows.reduce(function simplifyAllDocSet (r, v) {
        var doc = opts.include_docs ? v.doc : v
        // rework doc format to always have id ==> _id
        if (!opts.include_docs) {
          doc._id = doc.id
          doc._rev = doc.value.rev
          delete doc.id
          delete doc.value
          delete doc.key
        }
        /* istanbul ignore next */
        if (!opts.includeDesignDocs) r.push(doc)
        else if (opts.includeDesignDocs && doc._id.match(designDocRegex)) r.push(doc)
        return r
      }, [])
    })
  },

  /**
   * The native bulkGet PouchDB API is not very user friendly.  In fact, it's down right wacky!
   * This method patches PouchDB's `bulkGet` and assumes that _all_ of your requested docs exist.  If they do not, it will error via the usual error control flows.
   * @example
   * // A good example of what you can expect is actually right out of the tests!
   * let dummyDocs = [
   *   { _id: 'a', data: 'a' },
   *   { _id: 'b', data: 'b' }
   * ]
   * Promise.resolve()
   * .then(() => p.save(dummyDocs[0])) // add our first doc to the db
   * .then((doc) => (dummyDocs[0] = doc)) // update our closure doc it knows the _rev
   * .then(() => p.save(dummyDocs[1]))
   * .then((doc) => (dummyDocs[1] = doc))
   * .then(() => {
   *   // prepare bulkGet query (set of { _id, _rev}'s are required)
   *   const toFetch = dummyDocs.map(dummy => ({
   *     _id: dummy._id,
   *     _rev: dummy._rev
   *     // or you can provide .id, .rev
   *   }))
   *   p.bulkGet(toFetch)
   *     .then((docs) => {
   *       t.deepEqual(docs, dummyDocs, 'bulkGet returns sane results')
   *       t.end()
   *     })
   * })
   * @param {object|array} opts array of {_id, _rev}s, or { docs: [ ... } } where
   *                            ... is an array of {_id, _rev}s
   * @param {function} [cb]
   */
  bulkGet: function (opts, cb) {
    /* istanbul ignore else */
    if (!opts) throw new Error('missing bulkGet opts')
    if (Array.isArray(opts)) opts = { docs: opts }
    if (!Array.isArray(opts.docs)) {
      throw new Error('bulkGet requires array of doc filters. please see couchdb bulkGet')
    }
    opts.docs = opts.docs.map(function remapIdRev (doc) {
      // we need to map back to id and rev here
      /* istanbul ignore else */
      if (doc._id) doc.id = doc._id
      /* istanbul ignore else */
      if (doc._rev) doc.rev = doc._rev
      delete doc._rev
      delete doc._id
      return doc
    })
    if (!opts.docs.length) return Promise.resolve([])
    return this.db.bulkGet(opts)
    .then(function mapBulkGetResultsToRoot (r) {
      return r.results.map(function tidyBulkGetDocs (docGroup) {
        var doc = get(docGroup, 'docs[0].ok')
        if (!doc) throw new ReferenceError('doc ' + docGroup.id + 'not found')
        return doc
      })
    })
  },

  /**
   * easy way to create a db index.
   * @see createIndicies
   * @example
   * p.createIndex('myIndex')
   * @param {string} indexName
   * @param {function} [cb]
   * @returns {Promise}
   */
  createIndex: function () {
    return this.createIndicies.apply(this, arguments)
  },

  /**
   * allow single or bulk creation of indicies. also, doesn't flip out if you've
   * already set an index.
   * @example
   * p.createIndicies('test')
   * .then((indexResults) => console.dir(indexResults));
   * // ==>
   * /*
   * [{
   *     id: "_design/idx-28933dfe7bc072c94e2646126133dc0d"
   *     name: "idx-28933dfe7bc072c94e2646126133dc0d"
   *     result: "created"
   * }]
   * @param {array|string} indices 'an-index' or ['some', 'indicies']
   * @param {function} [cb]
   * @returns {Promise} resolves with index meta.  see `pouchy.createIndex`
   */
  createIndicies: function (indicies) {
    indicies = Array.isArray(indicies) ? indicies : [indicies]
    return this.db.createIndex({ index: { fields: unique(indicies) } })
    /* istanbul ignore next */
    .catch(function handleFailCreateIndicies (err) {
      /* istanbul ignore next */
      if (err.status !== 409) throw err
    })
  },

  /**
   * @see deleteAll
   * @param {function} [cb]
   * @returns {Promise}
   */
  clear: function () {
    return this.deleteAll.apply(this, arguments)
  },

  /**
   * delete a document.
   * @example
   * // same as pouch.remove
   * p.delete(doc).then(() => { console.dir(arguments); });
   * // ==>
   * {
   *     id: "test-doc-1"
   *     ok: true
   *     rev: "2-5cf6a4725ed4b9398d609fc8d7af2553"
   * }
   * @param {object} doc
   * @param {object} [opts] pouchdb.remove opts
   * @param {function} [cb]
   * @returns {Promise}
   */
  delete: function (doc, opts) {
    return this.db.remove(doc, opts)
  },

  /**
   * clears the db of documents. under the hood, `_deleted` flags are added to docs
   * @param {function} [cb]
   * @returns {Promise}
   */
  deleteAll: function (cb) {
    var deleteSingleDoc = function deleteSingleDoc (doc) { return this.delete(doc) }.bind(this)
    return this.all()
    .then(function deleteEach (docs) {
      return Promise.all(docs.map(deleteSingleDoc))
    })
  },

  /**
   * @see pouchdb.destroy
   * @param {function} [cb]
   * @returns {Promise}
   */
  deleteDB: function (cb) {
    /* istanbul ignore next */
    return this.db.destroy()
  },

  /**
   * proxies to pouchdb.destroy, but does internal tidy first
   * @param {function} [cb]
   * @returns {Promise}
   */
  destroy: function () {
    var chain = bluebird.resolve()
    /* istanbul ignore next */
    if (this.syncEmitter) {
      if (this._replicationOpts && this._replicationOpts.live) {
        // early bind the `complete` event listener.  careful not to bind it
        // inside the .then, otherwise binding happens at the end of the event
        // loop, which is too late! `.cancel` is a sync call!
        var isCompleteP = new Promise(function waitForLiveSyncComplete (resolve) {
          this.syncEmitter.on('complete', resolve)
        }.bind(this))
        chain = chain.then(isCompleteP)
      }
      this.syncEmitter.cancel() // will trigger complete event per
    }
    chain = chain.then(function bbPouchyDestroy () {
      return this.db.destroy.apply(this.db, arguments)
    }.bind(this))
    return chain
  },

  /**
   * normal pouchdb.find, but returns simple set of results
   * @param {object} opts find query opts
   * @param {function} [cb]
   * @returns {Promise}
   */
  find: function _find (opts, cb) {
    return this.db.find(opts)
    .then(function returnDocsArray (rslt) { return rslt.docs })
  },

  /**
   * normal pouchdb.get, but returns simple set of results
   * @param {string} id
   * @param {object} [opts]
   * @param {function} [cb]
   * @returns {Promise}
   */
  get: function _get (id, cb) {
    return this.db.get.apply(this.db, arguments)
  },

  /**
   * update a document, and get your sensibly updated doc in return.
   * @example
   * p.update({ _id: 'my-doc', _rev: '1-abc123' })
   * .then((doc) => console.log(doc))
   * // ==>
   * {
   *    _id: 'my-doc',
   *    _rev: '2-abc234'
   * }
   * @param {object} doc
   * @param {function} [cb]
   * @returns {Promise}
   */
  update: function (doc, cb) {
    // http://pouchdb.com/api.html#create_document
    // db.put(doc, [docId], [docRev], [options], [callback])
    return this.db.put(doc)
    .then(function (meta) {
      doc._id = meta.id
      doc._rev = meta.rev
      return doc
    })
  },

  /**
   * Adds or updates a document.  If `_id` is set, a `put` is performed (basic add operation). If no `_id` present, a `post` is performed, in which the doc is added, and large-random-string is assigned as `_id`.
   * @example
   * p.save({ beep: 'bop' }).then((doc) => console.log(doc))
   * // ==>
   * {
   *   _id: 'AFEALJW-234LKJASDF-2A;LKFJDA',
   *   _rev: '1-asdblkue242kjsa0f',
   *   beep: 'bop'
   * }
   * @param {object} doc
   * @param {object} [opts] `pouch.put/post` options
   * @param {function} [cb]
   * @returns {Promise} resolves w/ doc, with updated `_id` and `_rev` properties
   */
  save: function (doc, opts, cb) {
    // http://pouchdb.com/api.html#create_document
    // db.post(doc, [docId], [docRev], [options], [callback])
    /* istanbul ignore next */
    var method = doc.hasOwnProperty('_id') && (doc._id || doc._id === 0) ? 'put' : 'post'
    return this.db[method](doc)
      .then(function tidySaveResults (meta) {
        delete meta.status
        doc._id = meta.id
        doc._rev = meta.rev
        return doc
      })
  }
}

function publicMethodFactory (method) {
  return function pouchDualApiSupportMethod () {
    var args = toArray(arguments)
    var cb
    if (typeof args[args.length - 1] === 'function') cb = args.pop()
    var res = bluebird
    .resolve(publicMethods[method].apply(this, args))
    .then(res => toUnderscorePrefix(res))
    return cb ? res.asCallback(cb) : res
  }
}

var dualApiPublicMethods = {}
for (var k in publicMethods) {
  /* istanbul ignore next */
  if (publicMethods.hasOwnProperty(k)) {
    /* istanbul ignore next */
    if (isFunction(publicMethods[k])) {
      dualApiPublicMethods[k] = publicMethodFactory(k)
    }
  }
}

module.exports = dualApiPublicMethods
<commit_msg>fix(remove): patch for pouchdb #6766<commit_after>'use strict'

var bluebird = require('bluebird')
var defaults = require('lodash/defaults')
var unique = require('lodash/uniq')
var toArray = require('lodash/toArray')
var get = require('lodash/get')
var isFunction = require('lodash/isFunction')
var designDocRegex = new RegExp('^_design/')
var toUnderscorePrefix = require('./to-underscore-prefix')

/** @lends Pouchy.prototype */
var publicMethods = {
  /**
   * add a document to the db.
   * @see save
   * @example
   * // with _id
   * p.add({ _id: 'my-sauce', bbq: 'sauce' }).then(function(doc) {
   *   console.log(doc._id, doc._rev, doc.bbq); // 'my-sauce', '1-a76...46c', 'sauce'
   * });
   *
   * // no _id
   * p.add({ peanut: 'butter' }).then(function(doc) {
   *   console.log(doc._id, doc._rev, doc.peanut); // '66188...00BF885E', '1-0d74...7ac', 'butter'
   * });
   * @param {object} doc
   * @param {function} [cb]
   * @returns {Promise}
   */
  add: function add () {
    return this.save.apply(this, arguments)
  },

  /**
   * get all documents from db
   * @example
   * p.all().then((docs) => console.log(`total # of docs: ${docs.length}!`))
   * p.all({ includeDesignDocs: true }).then(function(docs) {
   *    console.log('this will include design docs as well');
   * })
   * @param {object} [opts] defaults to `include_docs: true`. In addition to the usual [PouchDB allDocs options](http://pouchdb.com/api.html#batch_fetch), you may also specify `includeDesignDocs: true` to have CouchDB design documents returned.
   * @param {function} [cb]
   * @returns {Promise} resolves to array of documents (excluding any design documents), vs an object with a `docs` array per Pouch allDocs default
   */
  all: function (opts, cb) {
    opts = defaults(opts || {}, { include_docs: true })
    return this.db.allDocs(opts)
    .then(function handleReceivedDocs (docs) {
      return docs.rows.reduce(function simplifyAllDocSet (r, v) {
        var doc = opts.include_docs ? v.doc : v
        // rework doc format to always have id ==> _id
        if (!opts.include_docs) {
          doc._id = doc.id
          doc._rev = doc.value.rev
          delete doc.id
          delete doc.value
          delete doc.key
        }
        /* istanbul ignore next */
        if (!opts.includeDesignDocs) r.push(doc)
        else if (opts.includeDesignDocs && doc._id.match(designDocRegex)) r.push(doc)
        return r
      }, [])
    })
  },

  /**
   * The native bulkGet PouchDB API is not very user friendly.  In fact, it's down right wacky!
   * This method patches PouchDB's `bulkGet` and assumes that _all_ of your requested docs exist.  If they do not, it will error via the usual error control flows.
   * @example
   * // A good example of what you can expect is actually right out of the tests!
   * let dummyDocs = [
   *   { _id: 'a', data: 'a' },
   *   { _id: 'b', data: 'b' }
   * ]
   * Promise.resolve()
   * .then(() => p.save(dummyDocs[0])) // add our first doc to the db
   * .then((doc) => (dummyDocs[0] = doc)) // update our closure doc it knows the _rev
   * .then(() => p.save(dummyDocs[1]))
   * .then((doc) => (dummyDocs[1] = doc))
   * .then(() => {
   *   // prepare bulkGet query (set of { _id, _rev}'s are required)
   *   const toFetch = dummyDocs.map(dummy => ({
   *     _id: dummy._id,
   *     _rev: dummy._rev
   *     // or you can provide .id, .rev
   *   }))
   *   p.bulkGet(toFetch)
   *     .then((docs) => {
   *       t.deepEqual(docs, dummyDocs, 'bulkGet returns sane results')
   *       t.end()
   *     })
   * })
   * @param {object|array} opts array of {_id, _rev}s, or { docs: [ ... } } where
   *                            ... is an array of {_id, _rev}s
   * @param {function} [cb]
   */
  bulkGet: function (opts, cb) {
    /* istanbul ignore else */
    if (!opts) throw new Error('missing bulkGet opts')
    if (Array.isArray(opts)) opts = { docs: opts }
    if (!Array.isArray(opts.docs)) {
      throw new Error('bulkGet requires array of doc filters. please see couchdb bulkGet')
    }
    opts.docs = opts.docs.map(function remapIdRev (doc) {
      // we need to map back to id and rev here
      /* istanbul ignore else */
      if (doc._id) doc.id = doc._id
      /* istanbul ignore else */
      if (doc._rev) doc.rev = doc._rev
      delete doc._rev
      delete doc._id
      return doc
    })
    if (!opts.docs.length) return Promise.resolve([])
    return this.db.bulkGet(opts)
    .then(function mapBulkGetResultsToRoot (r) {
      return r.results.map(function tidyBulkGetDocs (docGroup) {
        var doc = get(docGroup, 'docs[0].ok')
        if (!doc) throw new ReferenceError('doc ' + docGroup.id + 'not found')
        return doc
      })
    })
  },

  /**
   * easy way to create a db index.
   * @see createIndicies
   * @example
   * p.createIndex('myIndex')
   * @param {string} indexName
   * @param {function} [cb]
   * @returns {Promise}
   */
  createIndex: function () {
    return this.createIndicies.apply(this, arguments)
  },

  /**
   * allow single or bulk creation of indicies. also, doesn't flip out if you've
   * already set an index.
   * @example
   * p.createIndicies('test')
   * .then((indexResults) => console.dir(indexResults));
   * // ==>
   * /*
   * [{
   *     id: "_design/idx-28933dfe7bc072c94e2646126133dc0d"
   *     name: "idx-28933dfe7bc072c94e2646126133dc0d"
   *     result: "created"
   * }]
   * @param {array|string} indices 'an-index' or ['some', 'indicies']
   * @param {function} [cb]
   * @returns {Promise} resolves with index meta.  see `pouchy.createIndex`
   */
  createIndicies: function (indicies) {
    indicies = Array.isArray(indicies) ? indicies : [indicies]
    return this.db.createIndex({ index: { fields: unique(indicies) } })
    /* istanbul ignore next */
    .catch(function handleFailCreateIndicies (err) {
      /* istanbul ignore next */
      if (err.status !== 409) throw err
    })
  },

  /**
   * @see deleteAll
   * @param {function} [cb]
   * @returns {Promise}
   */
  clear: function () {
    return this.deleteAll.apply(this, arguments)
  },

  /**
   * delete a document.
   * @example
   * // same as pouch.remove
   * p.delete(doc).then(() => { console.dir(arguments); });
   * // ==>
   * {
   *     id: "test-doc-1"
   *     ok: true
   *     rev: "2-5cf6a4725ed4b9398d609fc8d7af2553"
   * }
   * @param {object} doc
   * @param {object} [opts] pouchdb.remove opts
   * @param {function} [cb]
   * @returns {Promise}
   */
  delete: function (doc, opts) {
    return this.db.remove(doc, opts || {}) // https://github.com/pouchdb/pouchdb/pull/6766
  },

  /**
   * clears the db of documents. under the hood, `_deleted` flags are added to docs
   * @param {function} [cb]
   * @returns {Promise}
   */
  deleteAll: function (cb) {
    var deleteSingleDoc = function deleteSingleDoc (doc) { return this.delete(doc) }.bind(this)
    return this.all()
    .then(function deleteEach (docs) {
      return Promise.all(docs.map(deleteSingleDoc))
    })
  },

  /**
   * @see pouchdb.destroy
   * @param {function} [cb]
   * @returns {Promise}
   */
  deleteDB: function (cb) {
    /* istanbul ignore next */
    return this.db.destroy()
  },

  /**
   * proxies to pouchdb.destroy, but does internal tidy first
   * @param {function} [cb]
   * @returns {Promise}
   */
  destroy: function () {
    var chain = bluebird.resolve()
    /* istanbul ignore next */
    if (this.syncEmitter) {
      if (this._replicationOpts && this._replicationOpts.live) {
        // early bind the `complete` event listener.  careful not to bind it
        // inside the .then, otherwise binding happens at the end of the event
        // loop, which is too late! `.cancel` is a sync call!
        var isCompleteP = new Promise(function waitForLiveSyncComplete (resolve) {
          this.syncEmitter.on('complete', resolve)
        }.bind(this))
        chain = chain.then(isCompleteP)
      }
      this.syncEmitter.cancel() // will trigger complete event per
    }
    chain = chain.then(function bbPouchyDestroy () {
      return this.db.destroy.apply(this.db, arguments)
    }.bind(this))
    return chain
  },

  /**
   * normal pouchdb.find, but returns simple set of results
   * @param {object} opts find query opts
   * @param {function} [cb]
   * @returns {Promise}
   */
  find: function _find (opts, cb) {
    return this.db.find(opts)
    .then(function returnDocsArray (rslt) { return rslt.docs })
  },

  /**
   * normal pouchdb.get, but returns simple set of results
   * @param {string} id
   * @param {object} [opts]
   * @param {function} [cb]
   * @returns {Promise}
   */
  get: function _get (id, cb) {
    return this.db.get.apply(this.db, arguments)
  },

  /**
   * update a document, and get your sensibly updated doc in return.
   * @example
   * p.update({ _id: 'my-doc', _rev: '1-abc123' })
   * .then((doc) => console.log(doc))
   * // ==>
   * {
   *    _id: 'my-doc',
   *    _rev: '2-abc234'
   * }
   * @param {object} doc
   * @param {function} [cb]
   * @returns {Promise}
   */
  update: function (doc, cb) {
    // http://pouchdb.com/api.html#create_document
    // db.put(doc, [docId], [docRev], [options], [callback])
    return this.db.put(doc)
    .then(function (meta) {
      doc._id = meta.id
      doc._rev = meta.rev
      return doc
    })
  },

  /**
   * Adds or updates a document.  If `_id` is set, a `put` is performed (basic add operation). If no `_id` present, a `post` is performed, in which the doc is added, and large-random-string is assigned as `_id`.
   * @example
   * p.save({ beep: 'bop' }).then((doc) => console.log(doc))
   * // ==>
   * {
   *   _id: 'AFEALJW-234LKJASDF-2A;LKFJDA',
   *   _rev: '1-asdblkue242kjsa0f',
   *   beep: 'bop'
   * }
   * @param {object} doc
   * @param {object} [opts] `pouch.put/post` options
   * @param {function} [cb]
   * @returns {Promise} resolves w/ doc, with updated `_id` and `_rev` properties
   */
  save: function (doc, opts, cb) {
    // http://pouchdb.com/api.html#create_document
    // db.post(doc, [docId], [docRev], [options], [callback])
    /* istanbul ignore next */
    var method = doc.hasOwnProperty('_id') && (doc._id || doc._id === 0) ? 'put' : 'post'
    return this.db[method](doc)
      .then(function tidySaveResults (meta) {
        delete meta.status
        doc._id = meta.id
        doc._rev = meta.rev
        return doc
      })
  }
}

function publicMethodFactory (method) {
  return function pouchDualApiSupportMethod () {
    var args = toArray(arguments)
    var cb
    if (typeof args[args.length - 1] === 'function') cb = args.pop()
    var res = bluebird
    .resolve(publicMethods[method].apply(this, args))
    .then(res => toUnderscorePrefix(res))
    return cb ? res.asCallback(cb) : res
  }
}

var dualApiPublicMethods = {}
for (var k in publicMethods) {
  /* istanbul ignore next */
  if (publicMethods.hasOwnProperty(k)) {
    /* istanbul ignore next */
    if (isFunction(publicMethods[k])) {
      dualApiPublicMethods[k] = publicMethodFactory(k)
    }
  }
}

module.exports = dualApiPublicMethods
<|endoftext|>


<commit_before>// 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.

couchTests.reduce_false = function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;

  var numDocs = 5;
  var docs = makeDocs(1,numDocs + 1);
  db.bulkSave(docs);
  var summate = function(N) {return (N+1)*N/2;};

  var designDoc = {
    _id:"_design/test",
    language: "javascript",
    views: {
      summate: {map:"function (doc) { emit(doc.integer, doc.integer); }",
                reduce:"function (keys, values) { return sum(values); }"},
    }
  };
  T(db.save(designDoc).ok);

  // Test that the reduce works
  var res = db.view('test/summate');
  T(res.rows.length == 1 && res.rows[0].value == summate(5));

  //Test that we get our docs back
  res = db.view('test/summate', {reduce: false});
  T(res.rows.length == 5);
  for(var i=0; i<5; i++) {
    T(res.rows[i].value == i+1);
  }
};
<commit_msg>JS test: update reduce_false.js for 2.0<commit_after>// 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.

couchTests.reduce_false = function(debug) {
  var db_name = get_random_db_name();
  var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
  db.createDb();
  if (debug) debugger;

  var numDocs = 5;
  var docs = makeDocs(1,numDocs + 1);
  db.bulkSave(docs);
  var summate = function(N) {return (N+1)*N/2;};

  var designDoc = {
    _id:"_design/test",
    language: "javascript",
    views: {
      summate: {map:"function (doc) { emit(doc.integer, doc.integer); }",
                reduce:"function (keys, values) { return sum(values); }"},
    }
  };
  T(db.save(designDoc).ok);

  // Test that the reduce works
  var res = db.view('test/summate');

  TEquals(1, res.rows.length, "should have 1 row");
  TEquals(summate(5), res.rows[0].value, 'should summate up 5');

  //Test that we get our docs back
  res = db.view('test/summate', {reduce: false});
  T(res.rows.length == 5);
  for(var i=0; i<5; i++) {
    T(res.rows[i].value == i+1);
  }

  // cleanup
  db.deleteDb();
};
<|endoftext|>


<commit_before>describe('Portal#useDefaultInterceptors()', function () {

  /**
   * @test
   */
  it('returns an instance of Portal with default interceptors', function () {
    var web = new portals.Portal();

    expect(web._requestInterceptors).to.have.lengthOf(2);
    expect(web._responseInterceptors).to.have.lengthOf(0);

    web.useDefaultInterceptors();

    expect(web._requestInterceptors).to.have.lengthOf(3);
    expect(web._responseInterceptors).to.have.lengthOf(1);
  });

});
<commit_msg>Updated the useDefaultInterceptors test<commit_after>describe('Portal#useDefaultInterceptors()', function () {

  /**
   * @test
   */
  it('returns an instance of Portal with default interceptors', function () {
    var web = new portals.Portal();

    expect(web._requestInterceptors).to.have.lengthOf(1);
    expect(web._responseInterceptors).to.have.lengthOf(0);

    web.useDefaultInterceptors();

    expect(web._requestInterceptors).to.have.lengthOf(4);
    expect(web._responseInterceptors).to.have.lengthOf(1);
  });

});
<|endoftext|>


<commit_before>const expect = require('chai').expect;
const { Canvas } = require('../../../../src/renderer');
const Coord = require('../../../../src/coord/index');
const { Arc } = require('../../../../src/component/guide/index');
const Scale = require('@antv/scale');

const div = document.createElement('div');
div.id = 'c1';
document.body.appendChild(div);

describe('Guide: 辅助圆弧线', function() {
  const coord = new Coord.Polar({
    start: { x: 60, y: 460 },
    end: { x: 460, y: 60 },
    startAngle: -9 / 8 * Math.PI,
    endAngle: 1 / 8 * Math.PI
  });

  const canvas = new Canvas({
    containerId: 'c1',
    width: 500,
    height: 500,
    pixelRatio: 2
  });

  const group = canvas.addGroup();

  const xScale = Scale.cat({
    values: [ '一月', '二月', '三月', '四月', '五月' ]
  });

  const yScale = Scale.linear({
    min: 0,
    max: 1200
  });

  it('guide arc', function() {
    const arc = new Arc({
      xScales: {
        month: xScale
      },
      yScales: {
        temp: yScale
      },
      start: {
        month: 0,
        temp: 1200
      },
      end: {
        month: 4,
        temp: 1200
      },
      style: {
        lineWidth: 3,
        stroke: 'blue'
      }
    });
    arc.render(coord, group);
    canvas.draw();
    const children = group.get('children');
    expect(children.length).to.equal(1);
    expect(children[0].name).to.equal('guide-arc');
/*    expect(children[0].attr('r')).to.equal(200);
    expect(children[0].attr('startAngle')).to.equal(2.7488935718910694);
    expect(children[0].attr('endAngle')).to.equal(0.39269908169872403);*/
  });
});
<commit_msg>fix: add unit test of drawing arc<commit_after>const expect = require('chai').expect;
const { Canvas } = require('../../../../src/renderer');
const Coord = require('../../../../src/coord/index');
const { Arc } = require('../../../../src/component/guide/index');
const Scale = require('@antv/scale');

const div = document.createElement('div');
div.id = 'c1';
document.body.appendChild(div);

describe('Guide: 辅助圆弧线', function() {
  const coord = new Coord.Polar({
    start: { x: 60, y: 460 },
    end: { x: 460, y: 60 },
    startAngle: -9 / 8 * Math.PI,
    endAngle: 1 / 8 * Math.PI
  });

  const canvas = new Canvas({
    containerId: 'c1',
    width: 500,
    height: 500,
    pixelRatio: 2
  });

  const group = canvas.addGroup();

  const xScale = Scale.cat({
    values: [ '一月', '二月', '三月', '四月', '五月' ]
  });

  const yScale = Scale.linear({
    min: 0,
    max: 1200
  });

  it('guide arc', function() {
    const arc = new Arc({
      xScales: {
        month: xScale
      },
      yScales: {
        temp: yScale
      },
      start: {
        month: 0,
        temp: 1200
      },
      end: {
        month: 4,
        temp: 1200
      },
      style: {
        lineWidth: 3,
        stroke: 'blue'
      }
    });
    arc.render(coord, group);
    canvas.draw();
    const children = group.get('children');
    expect(children.length).to.equal(1);
    expect(children[0].name).to.equal('guide-arc');
    expect(children[0].attr('path').length).to.equal(2);
    expect(children[0].getBBox().width).to.equal(403.3810740653281);
    expect(children[0].getBBox().height).to.equal(279.80013887133464);
  });
  it('circle as arc', function() {
    const coord = new Coord.Polar({
      start: { x: 80, y: 355 },
      end: { x: 480, y: 20 },
      startAngle: 0,
      endAngle: 2 * Math.PI
    });
    const arc = new Arc({
      xScales: {
        month: xScale
      },
      yScales: {
        temp: yScale
      },
      start: {
        month: 0,
        temp: 1200
      },
      end: {
        month: 4,
        temp: 1200
      },
      style: {
        lineWidth: 3,
        stroke: 'blue'
      }
    });
    arc.render(coord, group);
    canvas.draw();
    const children = group.get('children');
    expect(children.length).to.equal(2);
    expect(children[0].name).to.equal('guide-arc');
    expect(children[1].attr('path').length).to.equal(3);
    expect(children[1].getBBox().width).to.equal(338);
    expect(children[1].getBBox().height).to.equal(338);
  });
});
<|endoftext|>


<commit_before><commit_msg>actually needed document ready for that.<commit_after><|endoftext|>


<commit_before>import React from 'react';
import {mount} from 'enzyme';

import OpenCommitDialog from '../../lib/views/open-commit-dialog';

describe('OpenCommitDialog', function() {
  let atomEnv, commandRegistry;
  let app, wrapper, didAccept, didCancel;

  beforeEach(function() {
    atomEnv = global.buildAtomEnvironment();
    commandRegistry = atomEnv.commands;

    didAccept = sinon.stub();
    didCancel = sinon.stub();

    app = (
      <OpenCommitDialog
        commandRegistry={commandRegistry}
        didAccept={didAccept}
        didCancel={didCancel}
      />
    );
    wrapper = mount(app);
  });

  afterEach(function() {
    atomEnv.destroy();
  });

  const setTextIn = function(selector, text) {
    wrapper.find(selector).getDOMNode().getModel().setText(text);
  };

  describe('entering a commit sha', function() {
    it("updates the commit sha automatically if it hasn't been modified", function() {
      setTextIn('.github-CommitSha atom-text-editor', 'asdf1234');

      assert.equal(wrapper.instance().getCommitSha(), 'asdf1234');
    });

    it('does update the sha if it was modified automatically', function() {
      setTextIn('.github-CommitSha atom-text-editor', 'asdf1234');
      assert.equal(wrapper.instance().getCommitSha(), 'asdf1234');

      setTextIn('.github-CommitSha atom-text-editor', 'zxcv5678');
      assert.equal(wrapper.instance().getCommitSha(), 'zxcv5678');
    });
  });

  describe('open button enablement and error state', function() {
    it('disables the open button with no commit sha', function() {
      setTextIn('.github-CommitSha atom-text-editor', '');
      wrapper.update();

      assert.isTrue(wrapper.find('button.icon-commit').prop('disabled'));
      assert.isFalse(wrapper.find('.error').exists());
    });

    it('disables the open button with an invalid commit sha', function() {
      setTextIn('.github-CommitSha atom-text-editor', 'NOOOPE');
      wrapper.update();

      assert.isTrue(wrapper.find('button.icon-commit').prop('disabled'));
      assert.strictEqual(wrapper.find('.error').text(), 'Not a valid git commit identifier');
    });

    it('enables the open button when commit sha box is populated with a valid sha', function() {
      setTextIn('.github-CommitSha atom-text-editor', 'abcd1234');
      wrapper.update();

      assert.isFalse(wrapper.find('button.icon-commit').prop('disabled'));
      assert.isFalse(wrapper.find('.error').exists());
    });
  });

  it('calls the acceptance callback', function() {
    setTextIn('.github-CommitSha atom-text-editor', 'abcd1234');

    wrapper.find('button.icon-commit').simulate('click');

    assert.isTrue(didAccept.calledWith({sha: 'abcd1234'}));
    wrapper.unmount();
  });

  it('calls the cancellation callback', function() {
    wrapper.find('button.github-CancelButton').simulate('click');
    assert.isTrue(didCancel.called);
    wrapper.unmount();
  });
});
<commit_msg>add test for non existent commit<commit_after>import React from 'react';
import {mount} from 'enzyme';
import {cloneRepository, buildRepository} from '../helpers';

import OpenCommitDialog from '../../lib/views/open-commit-dialog';

describe('OpenCommitDialog', async function() {
  let atomEnv, commandRegistry;
  let app, wrapper, didAccept, didCancel;
  let repository, workdirPath;

  beforeEach(async function() {
    atomEnv = global.buildAtomEnvironment();
    commandRegistry = atomEnv.commands;

    didAccept = sinon.stub();
    didCancel = sinon.stub();
    workdirPath = await cloneRepository('three-files');
    repository = await buildRepository(workdirPath);

    app = (
      <OpenCommitDialog
        commandRegistry={commandRegistry}
        didAccept={didAccept}
        didCancel={didCancel}
        repository={repository}
      />
    );
    wrapper = mount(app);
  });

  afterEach(function() {
    atomEnv.destroy();
  });

  const setTextIn = function(selector, text) {
    wrapper.find(selector).getDOMNode().getModel().setText(text);
  };

  describe('entering a commit sha', function() {
    it("updates the commit sha automatically if it hasn't been modified", function() {
      setTextIn('.github-CommitSha atom-text-editor', 'asdf1234');

      assert.equal(wrapper.instance().getCommitSha(), 'asdf1234');
    });

    it('does update the sha if it was modified automatically', function() {
      setTextIn('.github-CommitSha atom-text-editor', 'asdf1234');
      assert.equal(wrapper.instance().getCommitSha(), 'asdf1234');

      setTextIn('.github-CommitSha atom-text-editor', 'zxcv5678');
      assert.equal(wrapper.instance().getCommitSha(), 'zxcv5678');
    });
  });

  describe('open button enablement and error state', function() {
    it('disables the open button with no commit sha', function() {
      setTextIn('.github-CommitSha atom-text-editor', '');
      wrapper.update();

      assert.isTrue(wrapper.find('button.icon-commit').prop('disabled'));
      assert.isFalse(wrapper.find('.error').exists());
    });

    it('disables the open button with an invalid commit sha', function() {
      setTextIn('.github-CommitSha atom-text-editor', 'NOOOPE');
      wrapper.update();

      assert.isTrue(wrapper.find('button.icon-commit').prop('disabled'));
      assert.strictEqual(wrapper.find('.error').text(), 'Not a valid git commit identifier');
    });

    it('disables open button when commit does not exist in repo', async function() {
      setTextIn('.github-CommitSha atom-text-editor', 'abcd1234');
      wrapper.update();
      wrapper.find('button.icon-commit').simulate('click');

      await assert.async.strictEqual(wrapper.update().find('.error').text(), 'Commit with that sha does not exist in this repository');
      assert.isTrue(wrapper.find('button.icon-commit').prop('disabled'));
    });

    it('enables the open button when commit sha box is populated with a valid sha', function() {
      setTextIn('.github-CommitSha atom-text-editor', 'abcd1234');
      wrapper.update();

      assert.isFalse(wrapper.find('button.icon-commit').prop('disabled'));
      assert.isFalse(wrapper.find('.error').exists());
    });
  });

  it('calls the acceptance callback', async function() {
    const commit = await repository.getLastCommit();
    setTextIn('.github-CommitSha atom-text-editor', commit.sha);

    wrapper.find('button.icon-commit').simulate('click');

    await assert.async.isTrue(didAccept.calledWith({sha: commit.sha}));
    wrapper.unmount();
  });

  it('calls the cancellation callback', function() {
    wrapper.find('button.github-CancelButton').simulate('click');
    assert.isTrue(didCancel.called);
    wrapper.unmount();
  });
});
<|endoftext|>