<commit_before>function runTest()
{
    FBTest.sysout("issue4382.START");

    FBTest.openNewTab(basePath + "net/4382/issue4382.html", function(win)
    {
        FBTest.openFirebug();

        var tests = [];
        /*tests.push(function(callback)
        {
            FBTest.progress("Testing JSON array");
            testJSONArray(win, callback);
        });*/

        tests.push(function(callback)
        {
            FBTest.progress("Testing JSON object");
            testJSONObject(win, callback);
        });

        FBTest.enableNetPanel(function(win)
        {
            FBTestFirebug.runTestSuite(tests, function()
            {
                FBTest.testDone("issue4382; DONE");
            });
        });
    });
}

function testJSONArray(win, callback)
{
    var panel = FBTest.selectPanel("net");
    panel.clear();

    var options =
    {
        tagName: "tr",
        classes: "netRow category-xhr hasHeaders loaded"
    };

    FBTest.waitForDisplayedElement("net", options, function(row)
    {
        var panelNode = FBTest.selectPanel("net").panelNode;

        FBTest.click(row);
        if (FBTest.ok(panelNode.getElementsByClassName("netInfoJSONTab").length > 0,
            "There must be a JSON tab"))
        {
            FBTest.expandElements(panelNode, "netInfoJSONTab");

            var jsonBody = FW.FBL.getElementByClass(panelNode, "netInfoJSONText");
            if (FBTest.ok(jsonBody, "JSON contents must exist"))
            {
                var sortLink = panelNode.getElementsByClassName("doSort").item(0);
                var expectedItems = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];

                verifyJSONContents("array", jsonBody, expectedItems);
                FBTest.click(sortLink);
                verifyJSONContents("array", jsonBody, expectedItems);

                // Reset click state
                FBTest.click(sortLink);
            }
        }

        callback();
    });

    FBTest.click(win.document.getElementById("requestArray"));
}

function testJSONObject(win, callback)
{
    var panel = FBTest.selectPanel("net");
    panel.clear();

    var options =
    {
        tagName: "tr",
        classes: "netRow category-xhr hasHeaders loaded"
    };

    FBTest.waitForDisplayedElement("net", options, function(row)
    {
        var panelNode = FBTest.selectPanel("net").panelNode;

        FBTest.click(row);
        if (FBTest.ok(panelNode.getElementsByClassName("netInfoJSONTab").length > 0,
            "There must be a JSON tab"))
        {
            FBTest.expandElements(panelNode, "netInfoJSONTab");

            var jsonBody = FW.FBL.getElementByClass(panelNode, "netInfoJSONText");
            if (FBTest.ok(jsonBody, "JSON contents must exist"))
            {
                var sortLink = panelNode.getElementsByClassName("doSort").item(0);

                verifyJSONContents("object", jsonBody, ["a", "c", "b"]);

                FBTest.click(sortLink);

                verifyJSONContents("object", jsonBody, ["a", "b", "c"]);

                // Reset click state
                //FBTest.click(sortLink);
            }
        }

        callback();
    });

    FBTest.click(win.document.getElementById("requestObject"));
}

// ********************************************************************************************* //
// Helpers

function verifyJSONContents(type, jsonBody, expectedItems)
{
    var jsonContents = jsonBody.getElementsByClassName("domTable").item(0);
    if (FBTest.ok(jsonContents, "JSON "+type+" contents must exist"))
    {
        var items = jsonContents.getElementsByClassName("memberRow");
        var itemsCorrect = true;
        for (var i=0; i<items.length; i++)
        {
            var label = items[i].getElementsByClassName("memberLabelCell").item(0).textContent;
            var value = parseInt(label);
            var item = (isNaN(value) ? label : value);
            if (item != expectedItems[i])
            {
                FBTrace.sysout("xxxxx "+i, {expectedItems: expectedItems, label: label, item: item});
                itemsCorrect = false;
                break;
            }
        }
        if (itemsCorrect)
            FBTest.ok(true, "All "+type+" items are correct");
        else
            FBTest.compare(i, label, "The "+type+" item at index "+i+" differs");
    }
}
<commit_msg>Follow up for issue 6193<commit_after>function runTest()
{
    FBTest.sysout("issue4382.START");

    FBTest.openNewTab(basePath + "net/4382/issue4382.html", function(win)
    {
        FBTest.openFirebug();

        var tests = [];
        tests.push(function(callback)
        {
            FBTest.progress("Testing JSON array");
            testJSONArray(win, callback);
        });

        tests.push(function(callback)
        {
            FBTest.progress("Testing JSON object");
            testJSONObject(win, callback);
        });

        FBTest.enableNetPanel(function(win)
        {
            FBTestFirebug.runTestSuite(tests, function()
            {
                FBTest.testDone("issue4382; DONE");
            });
        });
    });
}

function testJSONArray(win, callback)
{
    var panel = FBTest.selectPanel("net");
    panel.clear();

    var options =
    {
        tagName: "tr",
        classes: "netRow category-xhr hasHeaders loaded"
    };

    FBTest.waitForDisplayedElement("net", options, function(row)
    {
        var panelNode = FBTest.selectPanel("net").panelNode;

        FBTest.click(row);
        if (FBTest.ok(panelNode.getElementsByClassName("netInfoJSONTab").length > 0,
            "There must be a JSON tab"))
        {
            FBTest.expandElements(panelNode, "netInfoJSONTab");

            var jsonBody = FW.FBL.getElementByClass(panelNode, "netInfoJSONText");
            if (FBTest.ok(jsonBody, "JSON contents must exist"))
            {
                var sortLink = panelNode.getElementsByClassName("doSort").item(0);
                var expectedItems = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];

                verifyJSONContents("array", jsonBody, expectedItems);
                FBTest.click(sortLink);
                verifyJSONContents("array", jsonBody, expectedItems);

                // Reset click state
                FBTest.click(sortLink);
            }
        }

        callback();
    });

    FBTest.click(win.document.getElementById("requestArray"));
}

function testJSONObject(win, callback)
{
    var panel = FBTest.selectPanel("net");
    panel.clear();

    var options =
    {
        tagName: "tr",
        classes: "netRow category-xhr hasHeaders loaded"
    };

    FBTest.waitForDisplayedElement("net", options, function(row)
    {
        var panelNode = FBTest.selectPanel("net").panelNode;

        FBTest.click(row);
        if (FBTest.ok(panelNode.getElementsByClassName("netInfoJSONTab").length > 0,
            "There must be a JSON tab"))
        {
            FBTest.expandElements(panelNode, "netInfoJSONTab");

            var jsonBody = FW.FBL.getElementByClass(panelNode, "netInfoJSONText");
            if (FBTest.ok(jsonBody, "JSON contents must exist"))
            {
                var sortLink = panelNode.getElementsByClassName("doSort").item(0);

                verifyJSONContents("object", jsonBody, ["a", "c", "b"]);

                FBTest.click(sortLink);

                verifyJSONContents("object", jsonBody, ["a", "b", "c"]);

                // Reset click state
                FBTest.click(sortLink);
            }
        }

        callback();
    });

    FBTest.click(win.document.getElementById("requestObject"));
}

// ********************************************************************************************* //
// Helpers

function verifyJSONContents(type, jsonBody, expectedItems)
{
    var jsonContents = jsonBody.getElementsByClassName("domTable").item(0);
    if (FBTest.ok(jsonContents, "JSON "+type+" contents must exist"))
    {
        var items = jsonContents.getElementsByClassName("memberRow");
        var itemsCorrect = true;
        for (var i=0; i<items.length; i++)
        {
            var label = items[i].getElementsByClassName("memberLabelCell").item(0).textContent;
            var value = parseInt(label);
            var item = (isNaN(value) ? label : value);
            if (item != expectedItems[i])
            {
                FBTrace.sysout("xxxxx "+i, {expectedItems: expectedItems, label: label, item: item});
                itemsCorrect = false;
                break;
            }
        }
        if (itemsCorrect)
            FBTest.ok(true, "All "+type+" items are correct");
        else
            FBTest.compare(i, label, "The "+type+" item at index "+i+" differs");
    }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2020 Google Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

const { JSDOM } = require("jsdom");
const cspHashGen = require("csp-hash-generator");
const syncPackage = require("browser-sync/package.json");
const fs = require("fs");
const CSP = require("../_data/csp");

/**
 * Substitute the magic `HASHES` string in the CSP with the actual values of the
 * loaded JS files.
 * The ACTUAL CSP is configured in `_data/csp.js`.
 */

// Allow the auto-reload script in local dev. Would be good to get rid of this magic
// string which would break on ungrades of 11ty.
const AUTO_RELOAD_SCRIPTS = [
  quote(
    cspHashGen(
      "//<![CDATA[\n    document.write(\"<script async src='/browser-sync/browser-sync-client.js?v=" +
        syncPackage.version +
        '\'><\\/script>".replace("HOST", location.hostname));\n//]]>'
    )
  ),
];

function quote(str) {
  return `'${str}'`;
}

const addCspHash = async (rawContent, outputPath) => {
  let content = rawContent;

  if (outputPath && outputPath.endsWith(".html")) {
    const dom = new JSDOM(content);
    const cspAble = [
      ...dom.window.document.querySelectorAll("script[csp-hash]"),
    ];

    const hashes = cspAble.map((element) => {
      const hash = cspHashGen(element.textContent);
      element.setAttribute("csp-hash", hash);
      return quote(hash);
    });
    if (isDevelopmentMode()) {
      hashes.push.apply(hashes, AUTO_RELOAD_SCRIPTS);
    }

    content = dom.serialize();

    // write CSP Policy in headers file
    const headersPath = "./_site/_headers";
    const filePath = outputPath.replace("_site/", "/"); // _site/blog/index.html ->  /blog/index.html
    const filePathPrettyURL = filePath.slice(0, -10); // blog/index.html ->  /blog/
    try {
      const headers = fs.readFileSync(headersPath, { encoding: "utf-8" });
      const regExp = /(# \[csp headers\]\n)([\s\S]*)(# \[end csp headers\])/;
      const match = headers.match(regExp);
      if (!match) {
        throw `Check your _headers file. I couldn't find the text block for the csp headers:
          # [csp headers]
          # this text will be replaced by apply-csp.js plugin
          # [end csp headers]`;
      }
      const oldCustomHeaders = headers.match(regExp)[2].toString();
      const CSPPolicy = `Content-Security-Policy: ${CSP.apply().regular.replace(
        "HASHES",
        hashes.join(" ")
      )}`;
      let newCustomHeaders = oldCustomHeaders.concat(
        "\n",
        filePath,
        "\n  ",
        CSPPolicy
      );
      if (filePath != filePathPrettyURL) {
        newCustomHeaders = newCustomHeaders.concat(
          "\n",
          filePathPrettyURL,
          "\n  ",
          CSPPolicy
        );
      }
      fs.writeFileSync(
        headersPath,
        headers.replace(regExp, `$1${newCustomHeaders}\n$3`)
      );
    } catch (error) {
      console.log(
        "[apply-csp] Something went wrong with the creation of the csp headers\n",
        error
      );
    }
  }

  return content;
};

function parseHeaders(headersFile) {
  let currentFilename;
  let headers = {};
  for (let line of headersFile.split(/\n+/)) {
    if (!line) continue;
    if (/^\S/.test(line)) {
      currentFilename = line;
      headers[currentFilename] = [];
    } else {
      line = line.trim();
      const h = line.split(/:\s+/);
      headers[currentFilename][h[0]] = h[1];
    }
  }
  return headers;
}

module.exports = {
  initArguments: {},
  configFunction: async (eleventyConfig, pluginOptions = {}) => {
    eleventyConfig.addTransform("csp", addCspHash);
  },
  parseHeaders: parseHeaders,
  cspDevMiddleware: function (req, res, next) {
    const url = new URL(req.originalUrl, `http://${req.headers.host}/)`);
    // add csp headers only for html pages (include pretty urls)
    if (url.pathname.endsWith("/") || url.pathname.endsWith(".html")) {
      let headers;
      try {
        headers = parseHeaders(
          fs.readFileSync("_site/_headers", {
            encoding: "utf-8",
          })
        )[url.pathname];
      } catch (error) {
        console.error(
          "[setBrowserSyncConfig] Something went wrong with the creation of the csp headers\n",
          error
        );
      }
      if (headers) {
        const csp = headers["Content-Security-Policy"];
        if (csp) {
          res.setHeader("Content-Security-Policy", csp);
        }
      }
    }
    next();
  },
};

function isDevelopmentMode() {
  return /serve|dev/.test(process.argv.join());
}
<commit_msg>Update apply-csp.js (#139)<commit_after>/**
 * Copyright (c) 2020 Google Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

const { JSDOM } = require("jsdom");
const cspHashGen = require("csp-hash-generator");
const syncPackage = require("browser-sync/package.json");
const fs = require("fs");
const CSP = require("../_data/csp");

/**
 * Substitute the magic `HASHES` string in the CSP with the actual values of the
 * loaded JS files.
 * The ACTUAL CSP is configured in `_data/csp.js`.
 */

// Allow the auto-reload script in local dev. Would be good to get rid of this magic
// string which would break on ungrades of 11ty.
const AUTO_RELOAD_SCRIPTS = [
  quote(
    cspHashGen(
      "//<![CDATA[\n    document.write(\"<script async src='/browser-sync/browser-sync-client.js?v=" +
        syncPackage.version +
        '\'><\\/script>".replace("HOST", location.hostname));\n//]]>'
    )
  ),
];

function quote(str) {
  return `'${str}'`;
}

const addCspHash = async (rawContent, outputPath) => {
  let content = rawContent;

  if (outputPath && outputPath.endsWith(".html")) {
    const dom = new JSDOM(content);
    const cspAble = [
      ...dom.window.document.querySelectorAll("script[csp-hash]"),
    ];

    const hashes = cspAble.map((element) => {
      const hash = cspHashGen(element.textContent);
      element.setAttribute("csp-hash", hash);
      return quote(hash);
    });
    if (isDevelopmentMode()) {
      hashes.push.apply(hashes, AUTO_RELOAD_SCRIPTS);
    }

    content = dom.serialize();

    // write CSP Policy in headers file
    const headersPath = "./_site/_headers";
    const filePath = outputPath.replace("_site/", "/"); // _site/blog/index.html ->  /blog/index.html
    const filePathPrettyURL = filePath.slice(0, -10); // blog/index.html ->  /blog/
    try {
      const headers = fs.readFileSync(headersPath, { encoding: "utf-8" });
      const regExp = /(# \[csp headers\][\r\n]+)([\s\S]*)(# \[end csp headers\])/;
      const match = headers.match(regExp);
      if (!match) {
        throw `Check your _headers file. I couldn't find the text block for the csp headers:
          # [csp headers]
          # this text will be replaced by apply-csp.js plugin
          # [end csp headers]`;
      }
      const oldCustomHeaders = headers.match(regExp)[2].toString();
      const CSPPolicy = `Content-Security-Policy: ${CSP.apply().regular.replace(
        "HASHES",
        hashes.join(" ")
      )}`;
      let newCustomHeaders = oldCustomHeaders.concat(
        "\n",
        filePath,
        "\n  ",
        CSPPolicy
      );
      if (filePath != filePathPrettyURL) {
        newCustomHeaders = newCustomHeaders.concat(
          "\n",
          filePathPrettyURL,
          "\n  ",
          CSPPolicy
        );
      }
      fs.writeFileSync(
        headersPath,
        headers.replace(regExp, `$1${newCustomHeaders}\n$3`)
      );
    } catch (error) {
      console.log(
        "[apply-csp] Something went wrong with the creation of the csp headers\n",
        error
      );
    }
  }

  return content;
};

function parseHeaders(headersFile) {
  let currentFilename;
  let headers = {};
  for (let line of headersFile.split(/[\r\n]+/)) {
    if (!line) continue;
    if (/^\S/.test(line)) {
      currentFilename = line;
      headers[currentFilename] = [];
    } else {
      line = line.trim();
      const h = line.split(/:\s+/);
      headers[currentFilename][h[0]] = h[1];
    }
  }
  return headers;
}

module.exports = {
  initArguments: {},
  configFunction: async (eleventyConfig, pluginOptions = {}) => {
    eleventyConfig.addTransform("csp", addCspHash);
  },
  parseHeaders: parseHeaders,
  cspDevMiddleware: function (req, res, next) {
    const url = new URL(req.originalUrl, `http://${req.headers.host}/)`);
    // add csp headers only for html pages (include pretty urls)
    if (url.pathname.endsWith("/") || url.pathname.endsWith(".html")) {
      let headers;
      try {
        headers = parseHeaders(
          fs.readFileSync("_site/_headers", {
            encoding: "utf-8",
          })
        )[url.pathname];
      } catch (error) {
        console.error(
          "[setBrowserSyncConfig] Something went wrong with the creation of the csp headers\n",
          error
        );
      }
      if (headers) {
        const csp = headers["Content-Security-Policy"];
        if (csp) {
          res.setHeader("Content-Security-Policy", csp);
        }
      }
    }
    next();
  },
};

function isDevelopmentMode() {
  return /serve|dev/.test(process.argv.join());
}
<|endoftext|>


<commit_before>const {createRobot} = require('probot')
const payloads = require('./fixtures/payloads')
const app = require('..')
const fs = require('fs')
const path = require('path')
const request = require('supertest')

function gimmeRobot (config = 'basic.yml', noConfig = false) {
  const cfg = fs.readFileSync(path.join(__dirname, 'fixtures', 'configs', config), 'utf8')
  let robot
  let github
  const content = (str) => Promise.resolve({ data: { content: Buffer.from(str) } })

  robot = createRobot()
  app(robot)

  github = {
    issues: {
      getForRepo: jest.fn().mockReturnValue(Promise.resolve({ data: [{ title: 'An issue that exists', state: 'open' }] })),
      create: jest.fn()
    },
    repos: {
      // Response for getting content from '.github/todo.yml'
      getContent: jest.fn((obj) => {
        if (obj.path.includes('config.yml')) {
          if (noConfig) {
            throw { code: 404 } // eslint-disable-line
          } else {
            return content(cfg)
          }
        } else if (obj.path === 'index.js') {
          return content('\n\n@todo Jason!\nsdfasd\nsdfas\ndsfsa\n\n\nsdfsdaf\n@existing An issue that exists\n\n\n\n')
        } else if (obj.path === 'another.js') {
          return content('\n\n@TODO Another one!\nsdfasd\nsdfas\n\n\n@todo One more issue!\ndsfsa\n\n\nsdfsdaf')
        }
      })
    },
    pullRequests: {
      getAll: jest.fn().mockReturnValue(Promise.resolve({ data: [{ head: { ref: 'master' }, number: 10 }] }))
    }
  }
  // Passes the mocked out GitHub API into out robot instance
  robot.auth = () => Promise.resolve(github)
  return { robot, github }
}

describe('todo', () => {
  describe('GET /', () => {
    it('returns the homepage', async () => {
      const {robot} = gimmeRobot()
      const app = robot.route()
      const res = await request(app).get('/')
      expect(res.text.startsWith('<!DOCTYPE html>')).toBe(true)
    })

    it('responds with the proper caching header', async () => {
      const {robot} = gimmeRobot()
      const app = robot.route()
      const res = await request(app).get('/')
      expect(res.header).toHaveProperty('cache-control', 'public, max-age=1200, s-maxage=3200')
    })
  })

  it('requests issues for the repo', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.basic)
    expect(github.issues.getForRepo.mock.calls.length).toBe(1)
  })

  it('requests issues for the repo', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.basic)
    expect(github.issues.getForRepo.mock.calls.length).toBe(1)
  })

  it('creates an issue', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.basic)
    expect(github.issues.create.mock.calls.length).toBe(1)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'pr.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!',
      assignee: 'JasonEtco'
    })
  })

  it('creates an issue without assigning anyone', async () => {
    const {robot, github} = gimmeRobot('autoAssignFalse.yml')
    await robot.receive(payloads.basic)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'autoAssignFalse.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!'
    })
  })

  it('creates an issue and assigns the configured user', async () => {
    const {robot, github} = gimmeRobot('autoAssignString.yml')
    await robot.receive(payloads.basic)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'autoAssignString.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!',
      assignee: 'matchai'
    })
  })

  it('creates an issue and assigns the configured users', async () => {
    const {robot, github} = gimmeRobot('autoAssignArr.yml')
    await robot.receive(payloads.basic)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'autoAssignArr.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!',
      assignees: ['JasonEtco', 'matchai', 'defunkt']
    })
  })

  it('works with a complex push (with multiple commits)', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(3)
  })

  it('respects the capitalization config', async () => {
    const {robot, github} = gimmeRobot('caseSensitive.yml')
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(1)
  })

  it('does not create any issues', async () => {
    const {robot, github} = gimmeRobot('caseSensitivePizza.yml')
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(0)
  })

  it('does not create an issues that already exists', async () => {
    const {robot, github} = gimmeRobot('existing.yml')
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(0)
  })

  it.only('works without a config present', async () => {
    const {robot, github} = gimmeRobot('basic.yml', true)
    await robot.receive(payloads.basic)
    expect(github.issues.create.mock.calls.length).toBe(1)
  })
})
<commit_msg>Fix test coverage<commit_after>const {createRobot} = require('probot')
const payloads = require('./fixtures/payloads')
const app = require('..')
const fs = require('fs')
const path = require('path')
const request = require('supertest')

function gimmeRobot (config = 'basic.yml', noConfig = false) {
  const cfg = fs.readFileSync(path.join(__dirname, 'fixtures', 'configs', config), 'utf8')
  let robot
  let github
  const content = (str) => Promise.resolve({ data: { content: Buffer.from(str) } })

  robot = createRobot()
  app(robot)

  github = {
    issues: {
      getForRepo: jest.fn().mockReturnValue(Promise.resolve({ data: [{ title: 'An issue that exists', state: 'open' }] })),
      create: jest.fn()
    },
    repos: {
      // Response for getting content from '.github/todo.yml'
      getContent: jest.fn((obj) => {
        if (obj.path.includes('config.yml')) {
          if (noConfig) {
            throw { code: 404 } // eslint-disable-line
          } else {
            return content(cfg)
          }
        } else if (obj.path === 'index.js') {
          return content('\n\n@todo Jason!\nsdfasd\nsdfas\ndsfsa\n\n\nsdfsdaf\n@existing An issue that exists\n\n\n\n')
        } else if (obj.path === 'another.js') {
          return content('\n\n@TODO Another one!\nsdfasd\nsdfas\n\n\n@todo One more issue!\ndsfsa\n\n\nsdfsdaf')
        }
      })
    },
    pullRequests: {
      getAll: jest.fn().mockReturnValue(Promise.resolve({ data: [{ head: { ref: 'master' }, number: 10 }] }))
    }
  }
  // Passes the mocked out GitHub API into out robot instance
  robot.auth = () => Promise.resolve(github)
  return { robot, github }
}

describe('todo', () => {
  describe('GET /', () => {
    it('returns the homepage', async () => {
      const {robot} = gimmeRobot()
      const app = robot.route()
      const res = await request(app).get('/')
      expect(res.text.startsWith('<!DOCTYPE html>')).toBe(true)
    })

    it('responds with the proper caching header', async () => {
      const {robot} = gimmeRobot()
      const app = robot.route()
      const res = await request(app).get('/')
      expect(res.header).toHaveProperty('cache-control', 'public, max-age=1200, s-maxage=3200')
    })
  })

  it('requests issues for the repo', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.basic)
    expect(github.issues.getForRepo.mock.calls.length).toBe(1)
  })

  it('requests issues for the repo', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.basic)
    expect(github.issues.getForRepo.mock.calls.length).toBe(1)
  })

  it('creates an issue', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.basic)
    expect(github.issues.create.mock.calls.length).toBe(1)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'pr.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!',
      assignee: 'JasonEtco'
    })
  })

  it('creates an issue without assigning anyone', async () => {
    const {robot, github} = gimmeRobot('autoAssignFalse.yml')
    await robot.receive(payloads.basic)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'autoAssignFalse.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!'
    })
  })

  it('creates an issue and assigns the configured user', async () => {
    const {robot, github} = gimmeRobot('autoAssignString.yml')
    await robot.receive(payloads.basic)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'autoAssignString.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!',
      assignee: 'matchai'
    })
  })

  it('creates an issue and assigns the configured users', async () => {
    const {robot, github} = gimmeRobot('autoAssignArr.yml')
    await robot.receive(payloads.basic)
    expect(github.issues.create).toBeCalledWith({
      body: fs.readFileSync(path.join(__dirname, 'fixtures', 'bodies', 'autoAssignArr.txt'), 'utf8'),
      number: undefined,
      owner: 'JasonEtco',
      repo: 'test',
      title: 'Jason!',
      assignees: ['JasonEtco', 'matchai', 'defunkt']
    })
  })

  it('works with a complex push (with multiple commits)', async () => {
    const {robot, github} = gimmeRobot()
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(3)
  })

  it('respects the capitalization config', async () => {
    const {robot, github} = gimmeRobot('caseSensitive.yml')
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(1)
  })

  it('does not create any issues', async () => {
    const {robot, github} = gimmeRobot('caseSensitivePizza.yml')
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(0)
  })

  it('does not create an issues that already exists', async () => {
    const {robot, github} = gimmeRobot('existing.yml')
    await robot.receive(payloads.complex)
    expect(github.issues.create.mock.calls.length).toBe(0)
  })

  it('works without a config present', async () => {
    const {robot, github} = gimmeRobot('basic.yml', true)
    await robot.receive(payloads.basic)
    expect(github.issues.create.mock.calls.length).toBe(1)
  })
})
<|endoftext|>


<commit_before>// (C) Copyright 2015 Martin Dougiamas
//
// 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.

describe('User can create notes in a course', function() {

    it('User can click notes icon', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('My courses');
        }).then(function() {
            return $('.tab-item.active.mm-courses-handler.mma-notes-view-handler').click();
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
        }).then(function () {
            done();
        });
    });

    it('User can see notes side tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('My courses');
        }).then(function() {
            return $('.tab-item.active.mm-courses-handler.mma-notes-view-handler').click();
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
            expect(MM.getView().getText()).toMatch('Site notes');
            expect(MM.getView().getText()).toMatch('Course notes');
            expect(MM.getView().getText()).toMatch('Personal notes');
        }).then(function () {
            done();
        });
    });

    it('User can click Site notes tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('My courses');
        }).then(function() {
            return $('.tab-item.active.mm-courses-handler.mma-notes-view-handler').click();
        }).then(function() {
            return MM.clickOn('Site notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
            expect(MM.getView().getText()).toMatch('Barbara Gardner');
            expect(MM.getView().getText()).toMatch('Please teachers and support staff -keep an eye on Barbara for any recurring bullying issues.');
        }).then(function () {
            done();
        });
    });

    it('User can click Course notes tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('My courses');
        }).then(function() {
            return $('.tab-item.active.mm-courses-handler.mma-notes-view-handler').click();
        }).then(function() {
            return MM.clickOn('Course notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
            expect(MM.getView().getText()).toMatch('There are no notes of this type yet');
        }).then(function () {
            done();
        });
    });

    it('User can click Personal notes tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('My courses');
        }).then(function() {
            return $('.tab-item.active.mm-courses-handler.mma-notes-view-handler').click();
        }).then(function() {
            return MM.clickOn('Personal notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
            expect(MM.getView().getText()).toMatch('There are no notes of this type yet');
        }).then(function () {
            done();
        });
    });

});

<commit_msg>MOBILE-2126 e2e: Fixed notes.spec.js<commit_after>// (C) Copyright 2015 Martin Dougiamas
//
// 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.

describe('User can create notes in a course', function() {

    it('User can click notes icon', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('Course overview');
        }).then(function() {
            browser.sleep(5000); // wait to render
            return $('[ng-click="showCourseActions($event)"]').click();
        }).then(function() {
            return MM.clickOn('Notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
        }).then(function () {
            done();
        });
    });

    it('User can see notes side tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('Course overview');
        }).then(function() {
            browser.sleep(5000); // wait to render
            return $('[ng-click="showCourseActions($event)"]').click();
        }).then(function() {
            return MM.clickOn('Notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Notes');
            expect(MM.getView().getText()).toMatch('Site notes');
            expect(MM.getView().getText()).toMatch('Course notes');
            expect(MM.getView().getText()).toMatch('Personal notes');
        }).then(function () {
            done();
        });
    });

    it('User can click Site notes tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('Course overview');
        }).then(function() {
            browser.sleep(5000); // wait to render
            return $('[ng-click="showCourseActions($event)"]').click();
        }).then(function() {
            return MM.clickOn('Notes');
        }).then(function() {
            return MM.clickOn('Site notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Site notes');
            expect(MM.getView().getText()).toMatch('Barbara Gardner');
            expect(MM.getView().getText()).toMatch('Please teachers and support staff -keep an eye on Barbara for any recurring bullying issues.');
        }).then(function () {
            done();
        });
    });

    it('User can click Course notes tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('Course overview');
        }).then(function() {
            browser.sleep(5000); // wait to render
            return $('[ng-click="showCourseActions($event)"]').click();
        }).then(function() {
            return MM.clickOn('Notes');
        }).then(function() {
            return MM.clickOn('Course notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Course notes');
            expect(MM.getView().getText()).toMatch('There are no notes of this type yet');
        }).then(function () {
            done();
        });
    });

    it('User can click Personal notes tabs', function (done) {
        return MM.loginAsTeacher().then(function () {
            return MM.clickOnInSideMenu('Course overview');
        }).then(function() {
            browser.sleep(5000); // wait to render
            return $('[ng-click="showCourseActions($event)"]').click();
        }).then(function() {
            return MM.clickOn('Notes');
        }).then(function() {
            return MM.clickOn('Personal notes');
        }).then(function() {
            expect(MM.getNavBar().getText()).toMatch('Personal notes');
            expect(MM.getView().getText()).toMatch('There are no notes of this type yet');
        }).then(function () {
            done();
        });
    });

});

<|endoftext|>


<commit_before>
"use strict";

describe('directive: mo-list-table', () => {
    let element;
    let scope;
    let compile;
    let items = [{id: 1, txt: 'foo'}, {id: 2, txt: 'bar'}];
    let tpl = angular.element(`
<mo-list module="test" columns="['id', 'txt']">
    <mo-list-table total="1" page="page" rows="items"></mo-list-table>
</mo-list>
    `);

    beforeEach(inject(($rootScope, $compile) => {
        scope = $rootScope;
        compile = $compile;
    }));

    it('should insert the table into the element', () => {
        scope.$apply(() => {
            scope.items = items;
            scope.page = 1;
        });
        element = compile(tpl)(scope);
        scope.$digest();
        expect(element.find('tbody tr').length).toBe(2);
        expect(element.find('thead').length).toBe(1);
        expect(element.find('tbody td').eq(0).text().replace(/\s+/g, '')).toEqual('1');
        expect(element.find('tbody td').eq(1).text().replace(/\s+/g, '')).toEqual('foo');
        expect(element.find('tbody td').eq(2).text().replace(/\s+/g, '')).toEqual('2');
        expect(element.find('tbody td').eq(3).text().replace(/\s+/g, '')).toEqual('bar');
    });
});

<commit_msg>columns on list-table<commit_after>
"use strict";

describe('directive: mo-list-table', () => {
    let element;
    let scope;
    let compile;
    let items = [{id: 1, txt: 'foo'}, {id: 2, txt: 'bar'}];
    let tpl = angular.element(`
<mo-list module="test">
    <mo-list-table columns="['id', 'txt']" total="1" page="page" rows="items"></mo-list-table>
</mo-list>
    `);

    beforeEach(inject(($rootScope, $compile) => {
        scope = $rootScope;
        compile = $compile;
    }));

    it('should insert the table into the element', () => {
        scope.$apply(() => {
            scope.items = items;
            scope.page = 1;
        });
        element = compile(tpl)(scope);
        scope.$digest();
        expect(element.find('tbody tr').length).toBe(2);
        expect(element.find('thead').length).toBe(1);
        expect(element.find('tbody td').eq(0).text().replace(/\s+/g, '')).toEqual('1');
        expect(element.find('tbody td').eq(1).text().replace(/\s+/g, '')).toEqual('foo');
        expect(element.find('tbody td').eq(2).text().replace(/\s+/g, '')).toEqual('2');
        expect(element.find('tbody td').eq(3).text().replace(/\s+/g, '')).toEqual('bar');
    });
});

<|endoftext|>


<commit_before>//
//   # Match
//
//   Monad pattern matching.
//
//      var m = _.match([
//                    ['Cons(Some(a), _)', function(a) { return a; }],
//                    ['Cons(None, _)', function(x, y, z) { return 0; }],
//                    ['_', function() { return -1; }]);
//          m(_.Cons(_.Some(1), _.Nil));
//
//   * `match(patterns)(value)` - Construction.
//
var match = (function() {

    /* Token */
    var Token = taggedSum('Token', {
            TString: ['string'],
            TNumber: ['number'],
            TIdent: ['ident'],
            TWildcard: ['wildcard']
        }),

        isToken = isInstanceOf(Token),
        isTString = isInstanceOf(Token.TString),
        isTNumber = isInstanceOf(Token.TNumber),
        isTIdent = isInstanceOf(Token.TIdent),
        isTWildcard = isInstanceOf(Token.TWildcard),

        /* Setup the Monadic parser */
        regexp = Parser.regexp,
        string = Parser.string,
        word = regexp(/^\w+/),
        quote = regexp(/^"/),
        number = regexp(/^[\+\-]?\d+(\.\d+)?/),
        ident = regexp(/^[a-zA-Z\_][a-zA-Z0-9\_\-\.]*/),
        wildcard = regexp(/^\_/),
        comma = regexp(/^(\s|\,|\s)*/),
        leftBracket = string('('),
        rightBracket = string(')'),
        optionalWhitespace = regexp(/^\s*/),
        wildcardAsString = '_',

        /* Tokens */
        stringToken = quote.chain(function() {
            return word.skip(optionalWhitespace).many().skip(quote);
        }).map(function(a) {
            return Token.TString(a);
        }),
        numberToken = number.map(function(a) {
            return Token.TNumber(parseFloat(a, 10));
        }),
        identToken = ident.map(function(a) {
            return Token.TIdent(a);
        }),
        wildcardToken = wildcard.map(function() {
            return Token.TWildcard(wildcardAsString);
        }),

        /* Block */
        block = identToken.many().also(function() {
            return leftBracket.skip(optionalWhitespace).chain(function() {
                return expr.many().skip(rightBracket);
            });
        }),
        expr = block.orElse(wildcardToken)
                    .orElse(stringToken)
                    .orElse(numberToken)
                    .orElse(identToken)
                    .skip(comma),
        parser = block.orElse(wildcardToken)
                      .orElse(identToken),

        /* Start extracting the possible patterns */
        extract = curry(function(args, key, x) {
            var result = recursiveMatch(args, x, key),
                flattened = squishy.chain(result, function(a) {
                    return recursiveFlatten([a]);
                }),
                failed = squishy.exists(flattened, function(a) {
                    return a.isFailure;
                }),
                filtered,
                mapped;

            if (failed) {
                return Option.None;
            } else {
                filtered = squishy.filter(flattened, function(a) {
                    return a.fold(
                        function(v) {
                            return v !== wildcardAsString;
                        },
                        constant(false)
                    );
                });
                mapped = squishy.map(filtered, function(a) {
                    return a.extract();
                });
                return Option.of(mapped);
            }
        }),

        /* Main access point */
        match = function(patterns) {
            var env = this,
                compile = compiler();

            return function(argument) {
                var key = Token.TIdent([functionName(argument)]),
                    args = supplied(argument, fields(argument, key)).getOrElse(constant([])),
                    result = until(patterns, function(c) {
                        var result = compile(c[0]),
                            value = result.fold(
                                extract(args, key),
                                constant(result)
                            );

                        return value.map(
                            function(x) {
                                return c[1].apply(env, x);
                            }
                        );
                    });

                return result.fold(
                    identity,
                    function() {
                        /* Handle the default case */
                        var defaultCase = env.find(patterns, function(x) {
                            return x[0] === wildcardAsString;
                        });
                        if (isArray(defaultCase)) {
                            return defaultCase[1].apply(this, []);
                        }

                        throw new TypeError('No default case found.');
                    }
                );
            };
        };

    //
    //  ## equal(b)
    //
    Token.prototype.equal = function(b) {
        return this.match({
            TIdent: function(c) {
                return isTIdent(b) && squishy.equal(b.ident, c);
            },
            TNumber: function(c) {
                return isTNumber(b) && squishy.equal(b.number, c);
            },
            TString: function(c) {
                return isTString(b) && squishy.equal(b.string, c);
            },
            TWildcard: constant(true)
        });
    };

    //
    //  ## same(b)
    //
    Token.prototype.same = function(b) {
        return this.match({
            TIdent: function(c) {
                return isArray(b) && squishy.equal(b.ident, c);
            },
            TNumber: function(c) {
                return isNumber(b) && squishy.equal(b.number, c);
            },
            TString: function(c) {
                return isString(b) && squishy.equal(b.string, c);
            },
            TWildcard: constant(true)
        });
    };

    /* Get the head of the parsed stream */
    function head(a) {
        if (isArray(a)) {
            return squishy.flatten(a)[0];
        }
        return a;
    }

    /* Get the tail of the parsed stream */
    function tail(a) {
        return a[0].slice(1)[0];
    }

    /* Recursively flatten the arguments */
    function recursiveFlatten(a) {
        return squishy.fold(a, [], function(x, y) {
            return squishy.concat(x, isArray(y) ? recursiveFlatten(y) : y);
        });
    }

    /* Compile the stream into an array and cache the results for later */
    function compiler() {
        var cache = {};
        return function(stream) {
            var result;
            if (!(stream in cache)) {
                result = parser.parse(stream).fold(
                    Option.of,
                    Option.empty
                );

                cache[stream] = result;
            }
            return cache[stream];
        };
    }

    /* Return the siblings of the taggedSum  */
    function siblings(value) {
        if (isObject(value)) {
            return Object.keys(value._constructors);
        }
        return [];
    }

    /* Return the fields of the taggedSum */
    function fields(a, b) {
        var key = b.match({
            TIdent: Option.of,
            TNumber: Option.empty,
            TString: Option.empty,
            TWildcard: Option.empty
        });
        return key.match({
            Some: function(x) {
                return a._constructors[x];
            },
            None: constant([])
        });
    }

    /* Return the values from the value using the fields of the taggedSum */
    function supplied(value, fields) {
        if(isArray(fields) && fields.length > 0) {
            return Option.Some(squishy.select(value, fields));
        }
        return Option.None;
    }

    /* Continue to iterate through the array until an Option.Some is located */
    function until(a, f) {
        var result,
            i;

        for(i = 0; i < a.length; i++) {
            result = f(a[i]);
            if (result.isSome) {
                return result;
            }
        }

        return Option.None;
    }

    /* Recursively match the parsed stream values against the taggedSum values */
    function recursiveMatch(args, a, key) {
        var zipped,
            rest;

        if (head(a).equal(key)) {

            zipped = squishy.zip(tail(a), args);

            return squishy.map(
                zipped,
                function(tuple) {
                    var name = tuple._1,
                        value = tuple._2,
                        possibleKey = Token.TIdent([functionName(value)]),
                        possibleArgs,
                        possibleSibling;

                    if (squishy.isArray(name)) {
                        possibleArgs = supplied(value, fields(value, possibleKey));

                        return possibleArgs.fold(
                            function(x) {
                                return recursiveMatch(x, [name], possibleKey);
                            },
                            function() {
                                return Attempt.Failure(['Invalid tokens']);
                            }
                        );
                    } else if (!isTWildcard(name)) {
                        possibleSibling = squishy.exists(siblings(value), function(x) {
                            return name === x;
                        });

                        if (possibleSibling && name.same(possibleKey)) {
                            return Attempt.Failure(['Invalid taggedSum sibling']);
                        }

                        if(name.same(value) || name.equal(value)) {
                            return Attempt.of(value);
                        }

                        return Attempt.Failure(['Invalid token']);
                    } else {
                        return Attempt.of(wildcardAsString);
                    }
                }
            );
        } else {
            return [Attempt.Failure(['Invalid namespace', head(a), key])];
        }
    }

    return match;
})();

//
//  append methods to the squishy environment.
//
squishy = squishy
    .property('match', match);
<commit_msg>Slowly fixing things.<commit_after>function println() {
    var a = squishy.map([].slice.call(arguments), function(x) {
            return JSON.stringify(x) + '   ';
        }),
        log = Function.prototype.bind.call(console.log, console);

    log.apply(console, a);
}
//
//   # Match
//
//   Monad pattern matching.
//
//      var m = _.match([
//                    ['Cons(Some(a), _)', function(a) { return a; }],
//                    ['Cons(None, _)', function(x, y, z) { return 0; }],
//                    ['_', function() { return -1; }]);
//          m(_.Cons(_.Some(1), _.Nil));
//
//   * `match(patterns)(value)` - Construction.
//
var match = (function() {

    /* Token */
    var Token = taggedSum('Token', {
            TString: ['string'],
            TNumber: ['number'],
            TIdent: ['ident'],
            TWildcard: ['wildcard']
        }),

        isToken = isInstanceOf(Token),
        isTString = isInstanceOf(Token.TString),
        isTNumber = isInstanceOf(Token.TNumber),
        isTIdent = isInstanceOf(Token.TIdent),
        isTWildcard = isInstanceOf(Token.TWildcard),

        /* Setup the Monadic parser */
        regexp = Parser.regexp,
        string = Parser.string,
        word = regexp(/^\w+/),
        quote = regexp(/^"/),
        number = regexp(/^[\+\-]?\d+(\.\d+)?/),
        ident = regexp(/^[a-zA-Z\_][a-zA-Z0-9\_\-\.]*/),
        wildcard = regexp(/^\_/),
        comma = regexp(/^(\s|\,|\s)*/),
        leftBracket = string('('),
        rightBracket = string(')'),
        optionalWhitespace = regexp(/^\s*/),
        wildcardAsString = '_',

        /* Tokens */
        stringToken = quote.chain(function() {
            return word.skip(optionalWhitespace).many().skip(quote);
        }).map(function(a) {
            return Token.TString(a);
        }),
        numberToken = number.map(function(a) {
            return Token.TNumber(parseFloat(a, 10));
        }),
        identToken = ident.map(function(a) {
            return Token.TIdent(a);
        }),
        wildcardToken = wildcard.map(function() {
            return Token.TWildcard(wildcardAsString);
        }),

        /* Block */
        block = identToken.many().also(function() {
            return leftBracket.skip(optionalWhitespace).chain(function() {
                return expr.many().skip(rightBracket);
            });
        }),
        expr = block.orElse(wildcardToken)
                    .orElse(stringToken)
                    .orElse(numberToken)
                    .orElse(identToken)
                    .skip(comma),
        parser = block.orElse(wildcardToken)
                      .orElse(identToken),

        /* Start extracting the possible patterns */
        extract = curry(function(args, key, x) {
            var result = recursiveMatch(args, x, key),
                flattened = squishy.chain(result, function(a) {
                    return recursiveFlatten([a]);
                }),
                failed = squishy.exists(flattened, function(a) {
                    return a.isFailure;
                }),
                filtered,
                mapped;

            if (failed) {
                return Option.None;
            } else {
                filtered = squishy.filter(flattened, function(a) {
                    return a.fold(
                        function(v) {
                            return v !== wildcardAsString;
                        },
                        constant(false)
                    );
                });
                mapped = squishy.map(filtered, function(a) {
                    return a.extract();
                });
                return Option.of(mapped);
            }
        }),

        /* Main access point */
        match = function(patterns) {
            var env = this,
                compile = compiler();

            return function(argument) {
                var key = Token.TIdent([functionName(argument)]),
                    args = supplied(argument, fields(argument, key)).getOrElse(constant([])),
                    result = until(patterns, function(c) {
                        var result = compile(c[0]),
                            value = result.fold(
                                extract(args, key),
                                constant(result)
                            );

                        return value.map(
                            function(x) {
                                return c[1].apply(env, x);
                            }
                        );
                    });

                return result.fold(
                    identity,
                    function() {
                        /* Handle the default case */
                        var defaultCase = env.find(patterns, function(x) {
                            return x[0] === wildcardAsString;
                        });
                        if (isArray(defaultCase)) {
                            return defaultCase[1].apply(this, []);
                        }

                        throw new TypeError('No default case found.');
                    }
                );
            };
        };

    //
    //  ## equal(b)
    //
    Token.prototype.equal = function(b) {
        return this.match({
            TIdent: function(c) {
                return isTIdent(b) && squishy.equal(b.ident, c);
            },
            TNumber: function(c) {
                return isTNumber(b) && squishy.equal(b.number, c);
            },
            TString: function(c) {
                return isTString(b) && squishy.equal(b.string, c);
            },
            TWildcard: constant(true)
        });
    };

    //
    //  ## same(b)
    //
    Token.prototype.same = function(b) {
        return this.match({
            TIdent: function(c) {
                return squishy.equal(c[0], functionName(b));
            },
            TNumber: function(c) {
                return isNumber(b) && squishy.equal(c, b);
            },
            TString: function(c) {
                return isString(b) && squishy.equal(c[0][0], b);
            },
            TWildcard: constant(true)
        });
    };

    /* Get the head of the parsed stream */
    function head(a) {
        if (isArray(a)) {
            return squishy.flatten(a)[0];
        }
        return a;
    }

    /* Get the tail of the parsed stream */
    function tail(a) {
        if (isArray(a)) {
            return a[0].slice(1)[0];
        }
        return [a];
    }

    /* Recursively flatten the arguments */
    function recursiveFlatten(a) {
        return squishy.fold(a, [], function(x, y) {
            return squishy.concat(x, isArray(y) ? recursiveFlatten(y) : y);
        });
    }

    /* Compile the stream into an array and cache the results for later */
    function compiler() {
        var cache = {};
        return function(stream) {
            var result;
            if (!(stream in cache)) {
                result = parser.parse(stream).fold(
                    Option.of,
                    Option.empty
                );

                cache[stream] = result;
            }
            return cache[stream];
        };
    }

    /* Return the siblings of the taggedSum  */
    function siblings(value) {
        if (isObject(value)) {
            return Object.keys(value._constructors);
        }
        return [];
    }

    /* Return the fields of the taggedSum */
    function fields(a, b) {
        var key = b.match({
            TIdent: Option.of,
            TNumber: Option.empty,
            TString: Option.empty,
            TWildcard: Option.empty
        });
        return key.match({
            Some: function(x) {
                return a._constructors[x];
            },
            None: constant([])
        });
    }

    /* Return the values from the value using the fields of the taggedSum */
    function supplied(value, fields) {
        if(isArray(fields) && fields.length > 0) {
            return Option.Some(squishy.select(value, fields));
        }
        return Option.None;
    }

    /* Continue to iterate through the array until an Option.Some is located */
    function until(a, f) {
        var result,
            i;

        for(i = 0; i < a.length; i++) {
            result = f(a[i]);
            if (result.isSome) {
                return result;
            }
        }

        return Option.None;
    }

    /* Recursively match the parsed stream values against the taggedSum values */
    function recursiveMatch(args, a, key) {
        var zipped,
            rest;

        if (head(a).equal(key)) {

            zipped = squishy.zip(tail(a), args);

            return squishy.map(
                zipped,
                function(tuple) {
                    var name = tuple._1,
                        value = tuple._2,
                        possibleKey = Token.TIdent([functionName(value)]),
                        possibleArgs,
                        possibleSibling;

                    if (squishy.isArray(name)) {
                        possibleArgs = supplied(value, fields(value, possibleKey));

                        return possibleArgs.fold(
                            function(x) {
                                return recursiveMatch(x, [name], possibleKey);
                            },
                            function() {
                                return Attempt.Failure(['Invalid tokens']);
                            }
                        );
                    } else if (!isTWildcard(name)) {
                        possibleSibling = squishy.exists(siblings(value), function(x) {
                            return name === x;
                        });

                        if (possibleSibling && name.same(possibleKey)) {
                            return Attempt.Failure(['Invalid taggedSum sibling']);
                        }

                        if(name.same(value) || name.equal(value)) {
                            return Attempt.of(value);
                        }

                        return Attempt.Failure(['Invalid token']);
                    } else {
                        return Attempt.of(wildcardAsString);
                    }
                }
            );
        } else {
            return [Attempt.Failure(['Invalid namespace', head(a), key])];
        }
    }

    return match;
})();

//
//  append methods to the squishy environment.
//
squishy = squishy
    .property('match', match);
<|endoftext|>


<commit_before>//media.js
//media has utility functions for image, video and audio manipulation (and
//maybe others like device, etc).
(function() {
  var Media = {};

  var Image = function() {};
  //post process an image by setting it to a texture with a specified fragment
  //and vertex shader.
  Image.postProcess = (function() {
    var plane = new PhiloGL.O3D.Plane({
      type: 'x,y',
      xlen: 1,
      ylen: 1,
      offset: 0
    }), camera = new PhiloGL.Camera(45, 1, 0.1, 500, {
      position: { x: 0, y: 0, z: 1.205 }
    }), scene = new PhiloGL.Scene({}, camera);

    return function(opt) {
      var program = app.program.$$family ? app.program : app.program[opt.program],
          textures = opt.fromTexture ? $.splat(opt.fromTexture) : [],
          framebuffer = opt.toFrameBuffer,
          screen = !!opt.toScreen,
          width = opt.width || app.canvas.width,
          height = opt.height || app.canvas.height,
          x = opt.viewportX || 0,
          y = opt.viewportY || 0;

      camera.aspect = opt.aspectRatio ? opt.aspectRatio : Math.max(height / width, width / height);
      camera.update();

      scene.program = program;

      plane.textures = textures;
      plane.program = program;

      if(!scene.models.length) {
          scene.add(plane);
      }

      if (framebuffer) {
        //create framebuffer
        if (!(framebuffer in app.frameBufferMemo)) {
          app.setFrameBuffer(framebuffer, {
            width: width,
            height: height,
            bindToTexture: {
              parameters: [{
                name: 'TEXTURE_MAG_FILTER',
                value: 'LINEAR'
              }, {
                name: 'TEXTURE_MIN_FILTER',
                value: 'LINEAR',
                generateMipmap: false
              }]
            },
            bindToRenderBuffer: false
          });
        }
        program.use();
        app.setFrameBuffer(framebuffer, true);
        gl.viewport(x, y, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        program.setUniforms(opt.uniforms || {});
        scene.renderToTexture(framebuffer);
        app.setFrameBuffer(framebuffer, false);
      }

      if (screen) {
        program.use();
        gl.viewport(x, y, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        program.setUniforms(opt.uniforms || {});
        scene.render();
      }

      return this;
    };
  })();

  Media.Image = Image;
  PhiloGL.Media = Media;
})();
<commit_msg>the postprocessing coordinates where not very precise. This fixes this which would have given accumulation errors<commit_after>//media.js
//media has utility functions for image, video and audio manipulation (and
//maybe others like device, etc).
(function() {
  var Media = {};

  var Image = function() {};
  //post process an image by setting it to a texture with a specified fragment
  //and vertex shader.
  Image.postProcess = (function() {
    //length given a 45 fov angle, and 0.2 distance to camera
    var length = 0.16568542494923805;
    var plane = new PhiloGL.O3D.Plane({
      type: 'x,y',
      xlen: length,
      ylen: length,
      offset: 0
    }), camera = new PhiloGL.Camera(45, 1, 0.1, 500, {
      position: { x: 0, y: 0, z: -0.2 }
    }), scene = new PhiloGL.Scene({}, camera);

    return function(opt) {
      var program = app.program.$$family ? app.program : app.program[opt.program],
          textures = opt.fromTexture ? $.splat(opt.fromTexture) : [],
          framebuffer = opt.toFrameBuffer,
          screen = !!opt.toScreen,
          width = opt.width || app.canvas.width,
          height = opt.height || app.canvas.height,
          x = opt.viewportX || 0,
          y = opt.viewportY || 0;

      camera.aspect = opt.aspectRatio ? opt.aspectRatio : Math.max(height / width, width / height);
      camera.update();

      scene.program = program;

      plane.textures = textures;
      plane.program = program;

      if(!scene.models.length) {
          scene.add(plane);
      }

      if (framebuffer) {
        //create framebuffer
        if (!(framebuffer in app.frameBufferMemo)) {
          app.setFrameBuffer(framebuffer, {
            width: width,
            height: height,
            bindToTexture: {
              parameters: [{
                name: 'TEXTURE_MAG_FILTER',
                value: 'LINEAR'
              }, {
                name: 'TEXTURE_MIN_FILTER',
                value: 'LINEAR',
                generateMipmap: false
              }]
            },
            bindToRenderBuffer: false
          });
        }
        program.use();
        app.setFrameBuffer(framebuffer, true);
        gl.viewport(x, y, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        program.setUniforms(opt.uniforms || {});
        scene.renderToTexture(framebuffer);
        app.setFrameBuffer(framebuffer, false);
      }

      if (screen) {
        program.use();
        gl.viewport(x, y, width, height);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        program.setUniforms(opt.uniforms || {});
        scene.render();
      }

      return this;
    };
  })();

  Media.Image = Image;
  PhiloGL.Media = Media;
})();
<|endoftext|>


<commit_before>
function handleFiles(files) {
    for (var i = 0; i < files.length; i++) {
        var f = files[i];
        if (!f.type.match("image.*")) {
            continue;
        }
        var reader = new FileReader();
        reader.onload = (function(theFile) {
            return function(e) {
                background_image.src = e.target.result;
                document.title = "Editing " + theFile.name;
                invalidate(background_image);
                edit_file_name = theFile.name;
                var savedMark = window.localStorage.getItem(edit_file_name);
                if (savedMark) {
                    var saved_lines = JSON.parse(savedMark);
                    mark_lines = [];
                    for (var i = 0; i < saved_lines.length; i++) {
                        var line = saved_lines[i];
                        if (line.color) {
                            mark_lines[i] = new ColorMark(new Point(line.position.x, line.position.y), line.color, new Point(line.lable.x, line.lable.y));
                        } else {
                            mark_lines[i] = new LineMark(new Point(line.start.x, line.start.y), new Point(line.end.x, line.end.y));
                            mark_lines[i]._cache_length = line._cache_length;
                        }
                    };
                    invalidate();
                }
            }
        })(f);
        reader.readAsDataURL(f);
        break;
    };
}

function handleSelectFile(event) {
    handleFiles(event.target.files);
}

function handleDragOver(event) {
    event.stopPropagation();
    event.preventDefault();
    event.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}

function handleDrop(event) {
    event.stopPropagation();
    event.preventDefault();
    var files = event.dataTransfer.files;
    handleFiles(files);
}

var select_file = document.getElementById('select-file');
select_file.addEventListener("change", handleSelectFile, false);
mark_layer.addEventListener("drop", handleDrop, false);
mark_layer.addEventListener("dragover", handleDragOver, false);<commit_msg>test 2<commit_after>
function handleFiles(files) {
    for (var i = 0; i < files.length; i++) {
        var f = files[i];
        if (!f.type.match("image.*")) {
            continue;
        }
        var reader = new FileReader();
        reader.onload = (function(theFile) {
            return function(e) {
                background_image.src = e.target.result;
                document.title = "Editing " + theFile.name;
                invalidate(background_image);
                edit_file_name = theFile.name;
                var savedMark = window.localStorage.getItem(edit_file_name);
                if (savedMark) {
                    var saved_lines = JSON.parse(savedMark);
                    mark_lines = [];
                    for (var i = 0; i < saved_lines.length; i++) {
                        var line = saved_lines[i];
                        if (line.color) {
                            mark_lines[i] = new ColorMark(new Point(line.position.x, line.position.y), line.color, new Point(line.lable.x, line.lable.y));
                        } else {
                            mark_lines[i] = new LineMark(new Point(line.start.x, line.start.y), new Point(line.end.x, line.end.y));
                            mark_lines[i]._cache_length = line._cache_length;
                        }
                    };
                    invalidate();
                }
            }
        })(f);
        reader.readAsDataURL(f);
        break;
    };
}

function handleSelectFile(event) {
    handleFiles(event.target.files);
}

function handleDragOver(event) {
    event.stopPropagation();
    event.preventDefault();
    event.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}

function handleDrop(event) {
    event.stopPropagation();
    event.preventDefault();
    var files = event.dataTransfer.files;
    handleFiles(files);
}

var select_file = document.getElementById('select-file');
select_file.addEventListener("change", handleSelectFile, false);
mark_layer.addEventListener("drop", handleDrop, false);
mark_layer.addEventListener("dragover", handleDragOver, false);

<|endoftext|>


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

function getReadableStream(data, options) {
  var readableStream = new stream.Duplex(options);

  readableStream._read = (function() {
    var d = data.slice();

    return function() {
      if (d.length > 0) {
        this.push(d.shift());
      } else {
        this.push(null);
      }
    };
  }());

  return readableStream;
}

module.exports = getReadableStream;
<commit_msg>Update getDuplexStream.js<commit_after>var stream = require('stream');

function getDuplexStream(data, options) {
  var duplexStream = new stream.Duplex(options);

  duplexStream._read = (function() {
    var d = data.slice();

    return function() {
      if (d.length > 0) {
        this.push(d.shift());
      } else {
        this.push(null);
      }
    };
  }());

  return duplexStream;
}

module.exports = getDuplexStream;
<|endoftext|>


<commit_before>import React from "react";
import Backbone from "backbone";

import PercentageGraph from "components/common/ui/PercentageGraph.react";

export default React.createClass({
    displayName: "ProviderSummaryLinePlot",

    propTypes: {
        providers: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        identities: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        instances: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        volumes: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        sizes: React.PropTypes.instanceOf(Backbone.Collection).isRequired
    },

    //
    // Helper Methods
    //

    getChartData: function() {
        var summaries = [];
        this.props.identities.map(function(identity) {
            var data = this.getDataForIdentity(identity);
            if (data) summaries.push(data);
        }.bind(this));

        return summaries;
    },

    getDataForIdentity: function(identity) {
        var provider = this.props.providers.get(identity.get("provider").id),
            sizes = this.props.sizes,
            instances = this.props.instances,
            volumes = this.props.volumes,
            quota = identity.get("quota");

        var providerInstances = this.getProviderInstances(instances, provider);
        var providerVolumes = this.getProviderVolumes(volumes, provider);

        // CPU Usage
        var cpuUsageStats = this.calculateCpuUsage(providerInstances, quota, sizes),
            cpuUsage = cpuUsageStats.percentUsed * 100;

        // Memory Usage
        var memoryUsageStats = this.calculateMemoryUsage(providerInstances, quota, sizes),
            memoryUsage = memoryUsageStats.percentUsed * 100;

        // Storage Usage
        var storageUsageStats = this.calculateStorageUsage(providerVolumes, quota),
            storageUsage = storageUsageStats.percentUsed * 100;

        // Volume Usage
        var volumeUsageStats = this.calculateStorageCountUsage(providerVolumes, quota),
            volumeUsage = volumeUsageStats.percentUsed * 100;

        var seriesData = {
            name: provider.get("name"),
            data: [cpuUsage, memoryUsage, storageUsage, volumeUsage],
            limits: {
                CPU: cpuUsageStats.maxAllocation,
                Memory: memoryUsageStats.maxAllocation,
                Storage: storageUsageStats.maxAllocation,
                Volumes: volumeUsageStats.maxAllocation
            },
            appendMessages: {
                CPU: "CPUs",
                Memory: "GBs of Memory",
                Storage: "GBs of Storage",
                Volumes: "Volumes"
            },
            borderWidth: 0,
            dataLabels: {
                enabled: true,
                formatter: function() {
                    if (this.y != 0) {
                        return (Math.round(this.y * 100) / 100) + "%";
                    } else {
                        return null;
                    }
                }
            },
            animation: false
        };

        return seriesData;
    },

    getProviderInstances: function(instances, provider) {
        return instances.filter(function(instance) {
            return instance.get("identity").provider === provider.id;
        });
    },

    getProviderVolumes: function(volumes, provider) {
        return volumes.filter(function(volume) {
            return volume.get("identity").provider === provider.id;
        });
    },

    calculateCpuUsage: function(instances, quota, sizes) {
        var maxCpuCount = quota.cpu;

        var currentCpuCount = instances.reduce(function(memo, instance) {
            var size = sizes.get(instance.get("size").id);
            return memo + size.get("cpu");
        }.bind(this), 0);

        return {
            currentUsage: currentCpuCount,
            maxAllocation: maxCpuCount,
            percentUsed: currentCpuCount / maxCpuCount
        };
    },

    calculateMemoryUsage: function(instances, quota, sizes) {
        var maxMemory = quota.memory;

        var currentMemory = instances.reduce(function(memo, instance) {
            var size = sizes.get(instance.get("size").id);
            return memo + size.get("mem");
        }.bind(this), 0);

        return {
            currentUsage: currentMemory,
            maxAllocation: maxMemory,
            percentUsed: currentMemory / maxMemory
        };
    },

    calculateStorageUsage: function(volumes, quota) {
        var maxStorage = quota.storage;

        var currentStorage = volumes.reduce(function(memo, volume) {
            return memo + volume.get("size")
        }.bind(this), 0);

        return {
            currentUsage: currentStorage,
            maxAllocation: maxStorage,
            percentUsed: currentStorage / maxStorage
        };
    },

    calculateStorageCountUsage: function(volumes, quota) {
        var maxStorageCount = quota.storage_count;

        var currentStorageCount = volumes.reduce(function(memo, volume) {
            return memo + 1;
        }.bind(this), 0);

        return {
            currentUsage: currentStorageCount,
            maxAllocation: maxStorageCount,
            percentUsed: currentStorageCount / maxStorageCount
        };
    },

    calculateAllocationUsage: function(allocation) {
        var maxAllocation = allocation.threshold;
        var currentAllocation = allocation.current;

        return {
            currentUsage: currentAllocation,
            maxAllocation: maxAllocation,
            percentUsed: currentAllocation / maxAllocation
        };
    },

    //
    // Render
    //

    render: function() {
        return (

Provider Resources

            <PercentageGraph seriesData={this.getChartData()} categories={["CPU", "Memory", "Storage", "Volumes"]} />

        );
    }
});
<commit_msg>add 0% over null value<commit_after>import React from "react";
import Backbone from "backbone";

import PercentageGraph from "components/common/ui/PercentageGraph.react";

export default React.createClass({
    displayName: "ProviderSummaryLinePlot",

    propTypes: {
        providers: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        identities: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        instances: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        volumes: React.PropTypes.instanceOf(Backbone.Collection).isRequired,
        sizes: React.PropTypes.instanceOf(Backbone.Collection).isRequired
    },

    //
    // Helper Methods
    //

    getChartData: function() {
        var summaries = [];
        this.props.identities.map(function(identity) {
            var data = this.getDataForIdentity(identity);
            if (data) summaries.push(data);
        }.bind(this));

        return summaries;
    },

    getDataForIdentity: function(identity) {
        var provider = this.props.providers.get(identity.get("provider").id),
            sizes = this.props.sizes,
            instances = this.props.instances,
            volumes = this.props.volumes,
            quota = identity.get("quota");

        var providerInstances = this.getProviderInstances(instances, provider);
        var providerVolumes = this.getProviderVolumes(volumes, provider);

        // CPU Usage
        var cpuUsageStats = this.calculateCpuUsage(providerInstances, quota, sizes),
            cpuUsage = cpuUsageStats.percentUsed * 100;

        // Memory Usage
        var memoryUsageStats = this.calculateMemoryUsage(providerInstances, quota, sizes),
            memoryUsage = memoryUsageStats.percentUsed * 100;

        // Storage Usage
        var storageUsageStats = this.calculateStorageUsage(providerVolumes, quota),
            storageUsage = storageUsageStats.percentUsed * 100;

        // Volume Usage
        var volumeUsageStats = this.calculateStorageCountUsage(providerVolumes, quota),
            volumeUsage = volumeUsageStats.percentUsed * 100;

        var seriesData = {
            name: provider.get("name"),
            data: [cpuUsage, memoryUsage, storageUsage, volumeUsage],
            limits: {
                CPU: cpuUsageStats.maxAllocation,
                Memory: memoryUsageStats.maxAllocation,
                Storage: storageUsageStats.maxAllocation,
                Volumes: volumeUsageStats.maxAllocation
            },
            appendMessages: {
                CPU: "CPUs",
                Memory: "GBs of Memory",
                Storage: "GBs of Storage",
                Volumes: "Volumes"
            },
            borderWidth: 0,
            dataLabels: {
                enabled: true,
                formatter: function() {
                    if (this.y != 0) {
                        return (Math.round(this.y * 100) / 100) + "%";
                    } else {
                        return "0%";
                    }
                }
            },
            animation: false
        };

        return seriesData;
    },

    getProviderInstances: function(instances, provider) {
        return instances.filter(function(instance) {
            return instance.get("identity").provider === provider.id;
        });
    },

    getProviderVolumes: function(volumes, provider) {
        return volumes.filter(function(volume) {
            return volume.get("identity").provider === provider.id;
        });
    },

    calculateCpuUsage: function(instances, quota, sizes) {
        var maxCpuCount = quota.cpu;

        var currentCpuCount = instances.reduce(function(memo, instance) {
            var size = sizes.get(instance.get("size").id);
            return memo + size.get("cpu");
        }.bind(this), 0);

        return {
            currentUsage: currentCpuCount,
            maxAllocation: maxCpuCount,
            percentUsed: currentCpuCount / maxCpuCount
        };
    },

    calculateMemoryUsage: function(instances, quota, sizes) {
        var maxMemory = quota.memory;

        var currentMemory = instances.reduce(function(memo, instance) {
            var size = sizes.get(instance.get("size").id);
            return memo + size.get("mem");
        }.bind(this), 0);

        return {
            currentUsage: currentMemory,
            maxAllocation: maxMemory,
            percentUsed: currentMemory / maxMemory
        };
    },

    calculateStorageUsage: function(volumes, quota) {
        var maxStorage = quota.storage;

        var currentStorage = volumes.reduce(function(memo, volume) {
            return memo + volume.get("size")
        }.bind(this), 0);

        return {
            currentUsage: currentStorage,
            maxAllocation: maxStorage,
            percentUsed: currentStorage / maxStorage
        };
    },

    calculateStorageCountUsage: function(volumes, quota) {
        var maxStorageCount = quota.storage_count;

        var currentStorageCount = volumes.reduce(function(memo, volume) {
            return memo + 1;
        }.bind(this), 0);

        return {
            currentUsage: currentStorageCount,
            maxAllocation: maxStorageCount,
            percentUsed: currentStorageCount / maxStorageCount
        };
    },

    calculateAllocationUsage: function(allocation) {
        var maxAllocation = allocation.threshold;
        var currentAllocation = allocation.current;

        return {
            currentUsage: currentAllocation,
            maxAllocation: maxAllocation,
            percentUsed: currentAllocation / maxAllocation
        };
    },

    //
    // Render
    //

    render: function() {
        return (

Provider Resources

            <PercentageGraph seriesData={this.getChartData()} categories={["CPU", "Memory", "Storage", "Volumes"]} />

        );
    }
});
<|endoftext|>