<commit_before>/* eslint-env jest */
import execa from 'execa'
import fs from 'fs-extra'
import os from 'os'
import path from 'path'
import { findPort, killProcess, renderViaHTTP, waitFor } from 'next-test-utils'
import webdriver from 'next-webdriver'

const packagesDir = path.join(__dirname, '..', '..', '..', '..', 'packages')

const APP_DIRS = {
  app: path.join(__dirname, '..', 'app'),
  'app-multi-page': path.join(__dirname, '..', 'app-multi-page'),
}

// runs a command showing logs and returning the stdout
const runCommand = (cwd, cmd, args) => {
  const proc = execa(cmd, [...args], {
    cwd,
    stdio: [process.stdin, 'pipe', process.stderr],
  })

  let stdout = ''
  proc.stdout.on('data', (data) => {
    const s = data.toString()
    process.stdout.write(s)
    stdout += s
  })
  return new Promise((resolve, reject) => {
    proc.on('exit', (code) => {
      if (code === 0) {
        return resolve({ ...proc, stdout })
      }
      reject(
        new Error(`Command ${cmd} ${args.join(' ')} failed with code ${code}`)
      )
    })
  })
}

const runNpm = (cwd, ...args) => execa('npm', [...args], { cwd })
const runPnpm = (cwd, ...args) => runCommand(cwd, 'npx', ['pnpm', ...args])

async function usingTempDir(fn) {
  const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2))
  await fs.mkdirp(folder)
  try {
    return await fn(folder)
  } finally {
    await fs.remove(folder)
  }
}

/**
 * Using 'npm pack', create a tarball of the given package in
 * directory `pkg` and write it to `cwd`.
 *
 * `pkg` is relative to the monorepo 'packages/' directory.
 *
 * Return the absolute path to the tarball.
 */
async function pack(cwd, pkg) {
  const pkgDir = path.join(packagesDir, pkg)
  const { stdout } = await runNpm(
    cwd,
    'pack',
    '--ignore-scripts', // Skip the prepublish script
    path.join(packagesDir, pkg)
  )
  const tarballFilename = stdout.match(/.*\.tgz/)[0]

  if (!tarballFilename) {
    throw new Error(
      `npm failed to pack "next" package tarball in directory ${pkgDir}.`
    )
  }

  return path.join(cwd, tarballFilename)
}

/**
 * Create a Next.js app in a temporary directory, and install dependencies with pnpm.
 *
 * "next" and its monorepo dependencies are installed by `npm pack`-ing tarballs from
 * 'next.js/packages/*', because installing "next" directly via
 * `pnpm add path/to/next.js/packages/next` results in a symlink:
 * 'app/node_modules/next' -> 'path/to/next.js/packages/next'.
 * This is undesired since modules inside "next" would be resolved to the
 * next.js monorepo 'node_modules' and lead to false test results;
 * installing from a tarball avoids this issue.
 *
 * The "next" package's monorepo dependencies (e.g. "@next/env", "@next/polyfill-module")
 * are not bundled with `npm pack next.js/packages/next`,
 * so they need to be packed individually.
 * To ensure that they are installed upon installing "next", a package.json "pnpm.overrides"
 * field is used to override these dependency paths at install time.
 */
async function usingPnpmCreateNextApp(appDir, fn) {
  await usingTempDir(async (tempDir) => {
    const nextTarballPath = await pack(tempDir, 'next')
    const dependencyTarballPaths = {
      '@next/env': await pack(tempDir, 'next-env'),
      '@next/polyfill-module': await pack(tempDir, 'next-polyfill-module'),
      '@next/polyfill-nomodule': await pack(tempDir, 'next-polyfill-nomodule'),
      '@next/react-dev-overlay': await pack(tempDir, 'react-dev-overlay'),
      '@next/react-refresh-utils': await pack(tempDir, 'react-refresh-utils'),
    }

    const tempAppDir = path.join(tempDir, 'app')
    await fs.copy(appDir, tempAppDir)

    // Inject dependency tarball paths into a "pnpm.overrides" field in package.json,
    // so that they are installed from packed tarballs rather than from the npm registry.
    const packageJsonPath = path.join(tempAppDir, 'package.json')
    const overrides = {}
    for (const [dependency, tarballPath] of Object.entries(
      dependencyTarballPaths
    )) {
      overrides[dependency] = `file:${tarballPath}`
    }
    const packageJsonWithOverrides = {
      ...(await fs.readJson(packageJsonPath)),
      pnpm: { overrides },
    }
    await fs.writeFile(
      packageJsonPath,
      JSON.stringify(packageJsonWithOverrides, null, 2)
    )

    await runPnpm(tempAppDir, 'install')
    await runPnpm(tempAppDir, 'add', `next@${nextTarballPath}`)

    await fs.copy(
      path.join(__dirname, '../../../../packages/next-swc/native'),
      path.join(tempAppDir, 'node_modules/next-swc/native')
    )

    await fn(tempAppDir)
  })
}

describe('pnpm support', () => {
  it('should build with dependencies installed via pnpm', async () => {
    await usingPnpmCreateNextApp(APP_DIRS['app'], async (appDir) => {
      expect(
        await fs.pathExists(path.join(appDir, 'pnpm-lock.yaml'))
      ).toBeTruthy()

      const packageJsonPath = path.join(appDir, 'package.json')
      const packageJson = await fs.readJson(packageJsonPath)
      expect(packageJson.dependencies['next']).toMatch(/^file:/)
      for (const dependency of [
        '@next/env',
        '@next/polyfill-module',
        '@next/polyfill-nomodule',
        '@next/react-dev-overlay',
        '@next/react-refresh-utils',
      ]) {
        expect(packageJson.pnpm.overrides[dependency]).toMatch(/^file:/)
      }

      const { stdout } = await runPnpm(appDir, 'run', 'build')

      expect(stdout).toMatch(/Compiled successfully/)
    })
  })

  it('should execute client-side JS on each page in outputStandalone', async () => {
    await usingPnpmCreateNextApp(APP_DIRS['app-multi-page'], async (appDir) => {
      const { stdout } = await runPnpm(appDir, 'run', 'build')

      expect(stdout).toMatch(/Compiled successfully/)

      let appPort
      let appProcess
      let browser
      try {
        appPort = await findPort()
        const standaloneDir = path.resolve(appDir, '.next/standalone/app')

        // simulate what happens in a Dockerfile
        await fs.remove(path.join(appDir, 'node_modules'))
        await fs.copy(
          path.resolve(appDir, './.next/static'),
          path.resolve(standaloneDir, './.next/static'),
          { overwrite: true }
        )
        appProcess = execa('node', ['server.js'], {
          cwd: standaloneDir,
          env: {
            PORT: appPort,
          },
          stdio: 'inherit',
        })

        await waitFor(1000)

        await renderViaHTTP(appPort, '/')

        browser = await webdriver(appPort, '/', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()

        browser = await webdriver(appPort, '/about', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()
      } finally {
        await killProcess(appProcess.pid)
        await waitFor(5000)
      }
    })
  })

  it('should execute client-side JS on each page', async () => {
    await usingPnpmCreateNextApp(APP_DIRS['app-multi-page'], async (appDir) => {
      const { stdout } = await runPnpm(appDir, 'run', 'build')

      expect(stdout).toMatch(/Compiled successfully/)

      let appPort
      let appProcess
      let browser
      try {
        appPort = await findPort()
        appProcess = execa('pnpm', ['run', 'start', '--', '--port', appPort], {
          cwd: appDir,
          stdio: 'inherit',
        })

        await waitFor(5000)

        await renderViaHTTP(appPort, '/')

        browser = await webdriver(appPort, '/', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()

        browser = await webdriver(appPort, '/about', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()
      } finally {
        await killProcess(appProcess.pid)
        await waitFor(5000)
      }
    })
  })
})
<commit_msg>Fix copying local swc binary for pnpm test (#37047)<commit_after>/* eslint-env jest */
import execa from 'execa'
import fs from 'fs-extra'
import os from 'os'
import path from 'path'
import { findPort, killProcess, renderViaHTTP, waitFor } from 'next-test-utils'
import webdriver from 'next-webdriver'

const packagesDir = path.join(__dirname, '..', '..', '..', '..', 'packages')

const APP_DIRS = {
  app: path.join(__dirname, '..', 'app'),
  'app-multi-page': path.join(__dirname, '..', 'app-multi-page'),
}

// runs a command showing logs and returning the stdout
const runCommand = (cwd, cmd, args) => {
  const proc = execa(cmd, [...args], {
    cwd,
    stdio: [process.stdin, 'pipe', process.stderr],
  })

  let stdout = ''
  proc.stdout.on('data', (data) => {
    const s = data.toString()
    process.stdout.write(s)
    stdout += s
  })
  return new Promise((resolve, reject) => {
    proc.on('exit', (code) => {
      if (code === 0) {
        return resolve({ ...proc, stdout })
      }
      reject(
        new Error(`Command ${cmd} ${args.join(' ')} failed with code ${code}`)
      )
    })
  })
}

const runNpm = (cwd, ...args) => execa('npm', [...args], { cwd })
const runPnpm = (cwd, ...args) => runCommand(cwd, 'npx', ['pnpm', ...args])

async function usingTempDir(fn) {
  const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2))
  await fs.mkdirp(folder)
  try {
    return await fn(folder)
  } finally {
    await fs.remove(folder)
  }
}

/**
 * Using 'npm pack', create a tarball of the given package in
 * directory `pkg` and write it to `cwd`.
 *
 * `pkg` is relative to the monorepo 'packages/' directory.
 *
 * Return the absolute path to the tarball.
 */
async function pack(cwd, pkg) {
  const pkgDir = path.join(packagesDir, pkg)
  const { stdout } = await runNpm(
    cwd,
    'pack',
    '--ignore-scripts', // Skip the prepublish script
    path.join(packagesDir, pkg)
  )
  const tarballFilename = stdout.match(/.*\.tgz/)[0]

  if (!tarballFilename) {
    throw new Error(
      `npm failed to pack "next" package tarball in directory ${pkgDir}.`
    )
  }

  return path.join(cwd, tarballFilename)
}

/**
 * Create a Next.js app in a temporary directory, and install dependencies with pnpm.
 *
 * "next" and its monorepo dependencies are installed by `npm pack`-ing tarballs from
 * 'next.js/packages/*', because installing "next" directly via
 * `pnpm add path/to/next.js/packages/next` results in a symlink:
 * 'app/node_modules/next' -> 'path/to/next.js/packages/next'.
 * This is undesired since modules inside "next" would be resolved to the
 * next.js monorepo 'node_modules' and lead to false test results;
 * installing from a tarball avoids this issue.
 *
 * The "next" package's monorepo dependencies (e.g. "@next/env", "@next/polyfill-module")
 * are not bundled with `npm pack next.js/packages/next`,
 * so they need to be packed individually.
 * To ensure that they are installed upon installing "next", a package.json "pnpm.overrides"
 * field is used to override these dependency paths at install time.
 */
async function usingPnpmCreateNextApp(appDir, fn) {
  await usingTempDir(async (tempDir) => {
    const nextTarballPath = await pack(tempDir, 'next')
    const dependencyTarballPaths = {
      '@next/env': await pack(tempDir, 'next-env'),
      '@next/polyfill-module': await pack(tempDir, 'next-polyfill-module'),
      '@next/polyfill-nomodule': await pack(tempDir, 'next-polyfill-nomodule'),
      '@next/react-dev-overlay': await pack(tempDir, 'react-dev-overlay'),
      '@next/react-refresh-utils': await pack(tempDir, 'react-refresh-utils'),
    }

    const tempAppDir = path.join(tempDir, 'app')
    await fs.copy(appDir, tempAppDir)

    // Inject dependency tarball paths into a "pnpm.overrides" field in package.json,
    // so that they are installed from packed tarballs rather than from the npm registry.
    const packageJsonPath = path.join(tempAppDir, 'package.json')
    const overrides = {}
    for (const [dependency, tarballPath] of Object.entries(
      dependencyTarballPaths
    )) {
      overrides[dependency] = `file:${tarballPath}`
    }
    const packageJsonWithOverrides = {
      ...(await fs.readJson(packageJsonPath)),
      pnpm: { overrides },
    }
    await fs.writeFile(
      packageJsonPath,
      JSON.stringify(packageJsonWithOverrides, null, 2)
    )

    await runPnpm(tempAppDir, 'install')
    await runPnpm(tempAppDir, 'add', `next@${nextTarballPath}`)

    await fs.copy(
      path.join(__dirname, '../../../../packages/next-swc/native'),
      path.join(tempAppDir, 'node_modules/@next/swc/native')
    )

    await fn(tempAppDir)
  })
}

describe('pnpm support', () => {
  it('should build with dependencies installed via pnpm', async () => {
    await usingPnpmCreateNextApp(APP_DIRS['app'], async (appDir) => {
      expect(
        await fs.pathExists(path.join(appDir, 'pnpm-lock.yaml'))
      ).toBeTruthy()

      const packageJsonPath = path.join(appDir, 'package.json')
      const packageJson = await fs.readJson(packageJsonPath)
      expect(packageJson.dependencies['next']).toMatch(/^file:/)
      for (const dependency of [
        '@next/env',
        '@next/polyfill-module',
        '@next/polyfill-nomodule',
        '@next/react-dev-overlay',
        '@next/react-refresh-utils',
      ]) {
        expect(packageJson.pnpm.overrides[dependency]).toMatch(/^file:/)
      }

      const { stdout } = await runPnpm(appDir, 'run', 'build')

      expect(stdout).toMatch(/Compiled successfully/)
    })
  })

  it('should execute client-side JS on each page in outputStandalone', async () => {
    await usingPnpmCreateNextApp(APP_DIRS['app-multi-page'], async (appDir) => {
      const { stdout } = await runPnpm(appDir, 'run', 'build')

      expect(stdout).toMatch(/Compiled successfully/)

      let appPort
      let appProcess
      let browser
      try {
        appPort = await findPort()
        const standaloneDir = path.resolve(appDir, '.next/standalone/app')

        // simulate what happens in a Dockerfile
        await fs.remove(path.join(appDir, 'node_modules'))
        await fs.copy(
          path.resolve(appDir, './.next/static'),
          path.resolve(standaloneDir, './.next/static'),
          { overwrite: true }
        )
        appProcess = execa('node', ['server.js'], {
          cwd: standaloneDir,
          env: {
            PORT: appPort,
          },
          stdio: 'inherit',
        })

        await waitFor(1000)

        await renderViaHTTP(appPort, '/')

        browser = await webdriver(appPort, '/', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()

        browser = await webdriver(appPort, '/about', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()
      } finally {
        await killProcess(appProcess.pid)
        await waitFor(5000)
      }
    })
  })

  it('should execute client-side JS on each page', async () => {
    await usingPnpmCreateNextApp(APP_DIRS['app-multi-page'], async (appDir) => {
      const { stdout } = await runPnpm(appDir, 'run', 'build')

      expect(stdout).toMatch(/Compiled successfully/)

      let appPort
      let appProcess
      let browser
      try {
        appPort = await findPort()
        appProcess = execa('pnpm', ['run', 'start', '--', '--port', appPort], {
          cwd: appDir,
          stdio: 'inherit',
        })

        await waitFor(5000)

        await renderViaHTTP(appPort, '/')

        browser = await webdriver(appPort, '/', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()

        browser = await webdriver(appPort, '/about', {
          waitHydration: false,
        })
        expect(await browser.waitForElementByCss('#world').text()).toBe('World')
        await browser.close()
      } finally {
        await killProcess(appProcess.pid)
        await waitFor(5000)
      }
    })
  })
})
<|endoftext|>


<commit_before>(function(jQuery) {

var $ = jQuery;

if (!window.Echo) window.Echo = {};

if (!Echo.GUI) Echo.GUI = {};

if (Echo.GUI.Tabs) return;

/**
 * @class Echo.GUI.Tabs
 * Class wrapper for bootstrap-tab.js.
 * The Echo.GUI.Tabs class provides a simplified interface to work with
 * the Bootstrap Tabs JS class.
 * Echo wrapper assembles the HTML code required for Bootstrap Tabs JS class
 * based on the parameters specified in the config and initializes
 * the corresponding Bootstrap JS class.
 *
 * Example:
 * 	var myTabs = new Echo.GUI.Tabs({
 * 		"target": ".css-selector",
 * 		"entries": [{
 * 			"id": "tab1",
 * 			"label": "Tab 1",
 * 			"panel": $(".panel-css-selector"),
 * 			"extraClass": "extra-class"
 * 		}, {
 * 			"id": "tab2",
 * 			"label": "Tab 2",
 * 			"panel": $(".panel-css-selector2"),
 * 		}],
 * 		"extraClass": "extra-class",
 * 		"select": function() {},
 * 		"show": function() {},
 * 		"shown": function() {}
 * 	});
 *
 * 	// add a new tab
 * 	myTabs.add({"id": "tab3", "label": "Tab 3"});
 *
 * 	// remove the second tab
 * 	myTabs.remove("tab2");
 *
 * @extends Echo.GUI
 *
 * @package gui.pack.js
 *
 * @constructor
 * Creates a new tabs in the container you have passed in the "config.target".
 *
 * @param {Object} config
 * Tabs configuration.
 *
 * @cfg {Mixed} target (required)
 * The container where the tabs should be located.
 * This parameter can have several types:
 *
 * + CSS selector (ex: "css-selector")
 * + HTMLElement (ex: document.getElementById("some-element-id"))
 * + jQuery object (ex: $(".css-selector"))
 *
 * @cfg {String} [idPrefix=""]
 * Prefix which helps to make the tab id unique across the page.
 * Every Echo.GUI.Tabs instance should have its own unique prefix.
 *
 * Examples: "my-tabs-section", "my-product-tabs".
 *
 * @cfg {Boolean} [noRandomId=false]
 * By default tab ids have random part to prevent interference of several
 * instances of the *same* application on the page. Setting this parameter to `true` will
 * remove random part so it should be used with care.
 *
 * @cfg {Array} [entries=[]]
 * Array of entries (tabs).
 *
 * @cfg {String} entries.id
 * Tab id.
 *
 * @cfg {String} entries.label
 * Tab label.
 *
 * @cfg {Mixed} [entries.panel]
 * HTML element which contains tab content.
 * If this parameter is not specified, the container will be created.
 *
 * @cfg {Boolean} [entries.disabled]
 * Specifies whether the tab is disabled.
 *
 * @cfg {String} [entries.extraClass]
 * Class name to be added to the tab element.
 *
 * @cfg {HTMLElement} [panels]
 * Container which contains the panels.
 * If this parameter is not specified, the container will be created.
 *
 * @cfg {String} [classPrefix="echo-tabs-"]
 * String to be added as a prefix to the tab components.
 * Element with tabs will get "**\<classPrefix\>**header" class name
 * and element with panels will get "**\<classPrefix\>**panels" class.
 *
 * @cfg {Function} [select]
 * Function which will be called when tab is selected.
 *
 * @cfg {HTMLElement} select.tab
 * Container which is the tab itself.
 *
 * @cfg {String} select.id
 * Id of selected tab.
 *
 * @cfg {Function} [show]
 * Function to be called before the active tab panel is displayed.
 *
 * @cfg {HTMLElement} show.tab
 * Container which is the tab itself.
 *
 * @cfg {HTMLElement} show.panel
 * Container which is a panel related to the tab.
 *
 * @cfg {String} show.id
 * Id of shown tab.
 *
 * @cfg {Number} show.index
 * Numerical index of the tab.
 *
 * @cfg {Function} [shown]
 * Function to be called as soon as the active tab is displayed.
 *
 * The parameters are passed to this function the same as in #show.
 */
Echo.GUI.Tabs = Echo.Utils.inherit(Echo.GUI, function(config) {
	config.panels = config.panels ? $(config.panels) : $("
");

	Echo.GUI.call(this, config, {
		"entries": [],
		"idPrefix": "",
		"noRandomId": false,
		"classPrefix": "echo-tabs-",
		"select": function() {},
		"show": function() {},
		"shown": function() {}
	});
});

Echo.GUI.Tabs.prototype.refresh = function() {
	var self = this;
	var entries = this.config.get("entries");
	var panels = this.config.get("panels");
	var target = this.config.get("target");

	target.empty();

	this._randomId = this.config.get("noRandomId") ? "" : "-" + Echo.Utils.getUniqueString();

	this.tabsContainer = $('
');
	target.append(this.tabsContainer);

	panels.addClass("tab-content " + this.config.get("classPrefix") + "panels");
	if (panels.parent().length === 0) {
		target.append(panels);
	}

	if (entries.length) {
		for (var i = 0; i < entries.length; i++) {
			this.add(entries[i]);
		}
		this.show(entries[this.config.get("selected", 0)].id);
	}

	this.tabsContainer.on("click.tab.data-api", ':not(.active) > [data-toggle="tab"]', function() {
		self.config.get("select").call(self,
			$(this),
			$(this).data("item")
		);
	});
};

/**
 * Method to get a DOM element which contains panels.
 *
 * @return {HTMLElement}
 * DOM element which contains panels.
 */
Echo.GUI.Tabs.prototype.getPanels = function() {
	return this.config.get("panels");
};

/**
 * Method to disable tab.
 *
 * @param {String} id
 * Tab id which should be disabled.
 */
Echo.GUI.Tabs.prototype.disable = function(id) {
	var tabIndex = this._getTabIndex(id);
	if (~tabIndex) {
		this.get(id)
			.removeAttr("data-toggle")
			.removeAttr("href")
			.parent().addClass("disabled");
	}
};

/**
 * Method to enable tab.
 *
 * @param {String} id
 * Tab id which should be enabled.
 */
Echo.GUI.Tabs.prototype.enable = function(id) {
	var tabIndex = this._getTabIndex(id);
	if (~tabIndex) {
		this.get(id)
			.attr("data-toggle", "tab")
			.attr("href", "#" + this._getTabFullId(id))
			.parent().removeClass("disabled");
	}
};

/**
 * Method to remove tab.
 *
 * @param {String} id
 * Tab id which should be removed.
 */
Echo.GUI.Tabs.prototype.remove = function(id) {
	this.get(id).remove();
};

/**
 * Method to add tab.
 *
 * @param {Object} tabConfig
 * Tab configuration.
 *
 * @param {String} tabConfig.id
 * Tab id.
 *
 * @param {String} tabConfig.label
 * Tab label which should be displayed.
 *
 * @param {Boolean} tabConfig.disabled
 * Specifies whether the tab disabled.
 *
 * @param {HTMLElement} tabConfig.panel
 * HTML Element which contains the tab content.
 *
 */
Echo.GUI.Tabs.prototype.add = function(tabConfig) {
	var self = this;
	if (!tabConfig || !tabConfig.id) return this.config.get("target");

	var fullId = this._getTabFullId(tabConfig.id);
	var classes = tabConfig.disabled ? "disabled" : "";
	if (tabConfig.extraClass) {
		classes += " " + tabConfig.extraClass;
	}
	var attrs = 'data-item="' + tabConfig.id + '"';
	if (!tabConfig.disabled) {
		attrs += ' href="#' + fullId + '" data-toggle="tab"';
	}
	var tab = $('
' + tabConfig.label  + '
');

	var a = $("a", tab);
	$.map(["show", "shown"], function(event) {
		a.on(event, function() {
			self.config.get(event).call(self,
				$(this),
				self._getPanel(tabConfig.id),
				tabConfig.id,
				self._getTabIndex(tabConfig.id)
			);
		});
	});

	$.each(tabConfig.data || {}, function(k, v) {
		a.data(k, v);
	});
	this.tabsContainer.append(tab);

	tabConfig.panel = tabConfig.panel ? $(tabConfig.panel) : $("
");
	if (tabConfig.panel.attr("id") !== fullId) {
		tabConfig.panel.attr("id", fullId);
	}
	this.config.get("panels").append(tabConfig.panel.addClass("tab-pane"));
	return this.config.get("target");
};

/**
 * Method to get tab DOM element.
 *
 * @param {String} id
 * Tab id.
 *
 * @return {HTMLElement}
 * DOM element which contains the tab.
 */
Echo.GUI.Tabs.prototype.get = function(id) {
	return this.config.get("target").find("a[data-item='" + id + "']");
};

/**
 * Method to check whether the tab with specified id already exists.
 *
 * @param {String} id
 * Tab id.
 *
 * @return {Boolean}
 * `true` if tab with specific id exists,
 * `false` otherwise.
 */
Echo.GUI.Tabs.prototype.has = function(id) {
	return !!this.config.get("target").has("a[data-item='" + id + "']").length;
};

/**
 * This method updates the tab according to the tab config.
 *
 * @param {String} id
 * Tab id which should be updated.
 *
 * @param {Object} config
 * Tab configuration.
 *
 * @param {String} config.label
 * Tab label.
 *
 * @param {String} config.extraClass
 * Class name to be added to the tab element.
 *
 * @param {String} config.content
 * Content of the tab (can contain HTML tags).
 */
Echo.GUI.Tabs.prototype.update = function(id, config) {
	var tabIndex = this._getTabIndex(id);
	if (~tabIndex) {
		config.content && this._getPanel(id).html(config.content);
		this.get(id).html(config.label).addClass(config.extraClass);
	}
};

/**
 * Method to show tab with specific id.
 *
 * @param {String} id
 * Tab id which should be shown.
 */
Echo.GUI.Tabs.prototype.show = function(id) {
	this.get(id).tab("show");
	// sometimes panel is in detached DOM so we explicitly activate it
	this._getPanel(id).addClass("active");
};

Echo.GUI.Tabs.prototype._getTabIndex = function(id) {
	var entries = this.config.get("entries");
	for (var i = 0; i < entries.length; i++) {
		if (entries[i].id === id) {
			return i;
		}
	}
	return -1;
}

Echo.GUI.Tabs.prototype._getPanel = function(id) {
	return this.getPanels().find("#" + this._getTabFullId(id));
};

Echo.GUI.Tabs.prototype._getTabFullId = function(id) {
	return this.config.get("idPrefix") + id + this._randomId;
};

})(Echo.jQuery);
<commit_msg>Add new tab to entries list otherwise we won't be able to enable/disable it later<commit_after>(function(jQuery) {

var $ = jQuery;

if (!window.Echo) window.Echo = {};

if (!Echo.GUI) Echo.GUI = {};

if (Echo.GUI.Tabs) return;

/**
 * @class Echo.GUI.Tabs
 * Class wrapper for bootstrap-tab.js.
 * The Echo.GUI.Tabs class provides a simplified interface to work with
 * the Bootstrap Tabs JS class.
 * Echo wrapper assembles the HTML code required for Bootstrap Tabs JS class
 * based on the parameters specified in the config and initializes
 * the corresponding Bootstrap JS class.
 *
 * Example:
 * 	var myTabs = new Echo.GUI.Tabs({
 * 		"target": ".css-selector",
 * 		"entries": [{
 * 			"id": "tab1",
 * 			"label": "Tab 1",
 * 			"panel": $(".panel-css-selector"),
 * 			"extraClass": "extra-class"
 * 		}, {
 * 			"id": "tab2",
 * 			"label": "Tab 2",
 * 			"panel": $(".panel-css-selector2"),
 * 		}],
 * 		"extraClass": "extra-class",
 * 		"select": function() {},
 * 		"show": function() {},
 * 		"shown": function() {}
 * 	});
 *
 * 	// add a new tab
 * 	myTabs.add({"id": "tab3", "label": "Tab 3"});
 *
 * 	// remove the second tab
 * 	myTabs.remove("tab2");
 *
 * @extends Echo.GUI
 *
 * @package gui.pack.js
 *
 * @constructor
 * Creates a new tabs in the container you have passed in the "config.target".
 *
 * @param {Object} config
 * Tabs configuration.
 *
 * @cfg {Mixed} target (required)
 * The container where the tabs should be located.
 * This parameter can have several types:
 *
 * + CSS selector (ex: "css-selector")
 * + HTMLElement (ex: document.getElementById("some-element-id"))
 * + jQuery object (ex: $(".css-selector"))
 *
 * @cfg {String} [idPrefix=""]
 * Prefix which helps to make the tab id unique across the page.
 * Every Echo.GUI.Tabs instance should have its own unique prefix.
 *
 * Examples: "my-tabs-section", "my-product-tabs".
 *
 * @cfg {Boolean} [noRandomId=false]
 * By default tab ids have random part to prevent interference of several
 * instances of the *same* application on the page. Setting this parameter to `true` will
 * remove random part so it should be used with care.
 *
 * @cfg {Array} [entries=[]]
 * Array of entries (tabs).
 *
 * @cfg {String} entries.id
 * Tab id.
 *
 * @cfg {String} entries.label
 * Tab label.
 *
 * @cfg {Mixed} [entries.panel]
 * HTML element which contains tab content.
 * If this parameter is not specified, the container will be created.
 *
 * @cfg {Boolean} [entries.disabled]
 * Specifies whether the tab is disabled.
 *
 * @cfg {String} [entries.extraClass]
 * Class name to be added to the tab element.
 *
 * @cfg {HTMLElement} [panels]
 * Container which contains the panels.
 * If this parameter is not specified, the container will be created.
 *
 * @cfg {String} [classPrefix="echo-tabs-"]
 * String to be added as a prefix to the tab components.
 * Element with tabs will get "**\<classPrefix\>**header" class name
 * and element with panels will get "**\<classPrefix\>**panels" class.
 *
 * @cfg {Function} [select]
 * Function which will be called when tab is selected.
 *
 * @cfg {HTMLElement} select.tab
 * Container which is the tab itself.
 *
 * @cfg {String} select.id
 * Id of selected tab.
 *
 * @cfg {Function} [show]
 * Function to be called before the active tab panel is displayed.
 *
 * @cfg {HTMLElement} show.tab
 * Container which is the tab itself.
 *
 * @cfg {HTMLElement} show.panel
 * Container which is a panel related to the tab.
 *
 * @cfg {String} show.id
 * Id of shown tab.
 *
 * @cfg {Number} show.index
 * Numerical index of the tab.
 *
 * @cfg {Function} [shown]
 * Function to be called as soon as the active tab is displayed.
 *
 * The parameters are passed to this function the same as in #show.
 */
Echo.GUI.Tabs = Echo.Utils.inherit(Echo.GUI, function(config) {
	config.panels = config.panels ? $(config.panels) : $("
");

	Echo.GUI.call(this, config, {
		"entries": [],
		"idPrefix": "",
		"noRandomId": false,
		"classPrefix": "echo-tabs-",
		"select": function() {},
		"show": function() {},
		"shown": function() {}
	});
});

Echo.GUI.Tabs.prototype.refresh = function() {
	var self = this;
	var entries = this.config.get("entries");
	var panels = this.config.get("panels");
	var target = this.config.get("target");

	target.empty();

	this._randomId = this.config.get("noRandomId") ? "" : "-" + Echo.Utils.getUniqueString();

	this.tabsContainer = $('
');
	target.append(this.tabsContainer);

	panels.addClass("tab-content " + this.config.get("classPrefix") + "panels");
	if (panels.parent().length === 0) {
		target.append(panels);
	}

	if (entries.length) {
		for (var i = 0; i < entries.length; i++) {
			this.add(entries[i]);
		}
		this.show(entries[this.config.get("selected", 0)].id);
	}

	this.tabsContainer.on("click.tab.data-api", ':not(.active) > [data-toggle="tab"]', function() {
		self.config.get("select").call(self,
			$(this),
			$(this).data("item")
		);
	});
};

/**
 * Method to get a DOM element which contains panels.
 *
 * @return {HTMLElement}
 * DOM element which contains panels.
 */
Echo.GUI.Tabs.prototype.getPanels = function() {
	return this.config.get("panels");
};

/**
 * Method to disable tab.
 *
 * @param {String} id
 * Tab id which should be disabled.
 */
Echo.GUI.Tabs.prototype.disable = function(id) {
	var tabIndex = this._getTabIndex(id);
	if (~tabIndex) {
		this.get(id)
			.removeAttr("data-toggle")
			.removeAttr("href")
			.parent().addClass("disabled");
	}
};

/**
 * Method to enable tab.
 *
 * @param {String} id
 * Tab id which should be enabled.
 */
Echo.GUI.Tabs.prototype.enable = function(id) {
	var tabIndex = this._getTabIndex(id);
	if (~tabIndex) {
		this.get(id)
			.attr("data-toggle", "tab")
			.attr("href", "#" + this._getTabFullId(id))
			.parent().removeClass("disabled");
	}
};

/**
 * Method to remove tab.
 *
 * @param {String} id
 * Tab id which should be removed.
 */
Echo.GUI.Tabs.prototype.remove = function(id) {
	this.get(id).remove();
};

/**
 * Method to add tab.
 *
 * @param {Object} tabConfig
 * Tab configuration.
 *
 * @param {String} tabConfig.id
 * Tab id.
 *
 * @param {String} tabConfig.label
 * Tab label which should be displayed.
 *
 * @param {Boolean} tabConfig.disabled
 * Specifies whether the tab disabled.
 *
 * @param {HTMLElement} tabConfig.panel
 * HTML Element which contains the tab content.
 *
 */
Echo.GUI.Tabs.prototype.add = function(tabConfig) {
	var self = this;
	if (!tabConfig || !tabConfig.id) return this.config.get("target");

	if (!~this._getTabIndex(tabConfig.id)) {
		this.config.get("entries").push(tabConfig);
	}

	var fullId = this._getTabFullId(tabConfig.id);
	var classes = tabConfig.disabled ? "disabled" : "";
	if (tabConfig.extraClass) {
		classes += " " + tabConfig.extraClass;
	}
	var attrs = 'data-item="' + tabConfig.id + '"';
	if (!tabConfig.disabled) {
		attrs += ' href="#' + fullId + '" data-toggle="tab"';
	}
	var tab = $('
' + tabConfig.label  + '
');

	var a = $("a", tab);
	$.map(["show", "shown"], function(event) {
		a.on(event, function() {
			self.config.get(event).call(self,
				$(this),
				self._getPanel(tabConfig.id),
				tabConfig.id,
				self._getTabIndex(tabConfig.id)
			);
		});
	});

	$.each(tabConfig.data || {}, function(k, v) {
		a.data(k, v);
	});
	this.tabsContainer.append(tab);

	tabConfig.panel = tabConfig.panel ? $(tabConfig.panel) : $("
");
	if (tabConfig.panel.attr("id") !== fullId) {
		tabConfig.panel.attr("id", fullId);
	}
	this.config.get("panels").append(tabConfig.panel.addClass("tab-pane"));
	return this.config.get("target");
};

/**
 * Method to get tab DOM element.
 *
 * @param {String} id
 * Tab id.
 *
 * @return {HTMLElement}
 * DOM element which contains the tab.
 */
Echo.GUI.Tabs.prototype.get = function(id) {
	return this.config.get("target").find("a[data-item='" + id + "']");
};

/**
 * Method to check whether the tab with specified id already exists.
 *
 * @param {String} id
 * Tab id.
 *
 * @return {Boolean}
 * `true` if tab with specific id exists,
 * `false` otherwise.
 */
Echo.GUI.Tabs.prototype.has = function(id) {
	return !!this.config.get("target").has("a[data-item='" + id + "']").length;
};

/**
 * This method updates the tab according to the tab config.
 *
 * @param {String} id
 * Tab id which should be updated.
 *
 * @param {Object} config
 * Tab configuration.
 *
 * @param {String} config.label
 * Tab label.
 *
 * @param {String} config.extraClass
 * Class name to be added to the tab element.
 *
 * @param {String} config.content
 * Content of the tab (can contain HTML tags).
 */
Echo.GUI.Tabs.prototype.update = function(id, config) {
	var tabIndex = this._getTabIndex(id);
	if (~tabIndex) {
		config.content && this._getPanel(id).html(config.content);
		this.get(id).html(config.label).addClass(config.extraClass);
	}
};

/**
 * Method to show tab with specific id.
 *
 * @param {String} id
 * Tab id which should be shown.
 */
Echo.GUI.Tabs.prototype.show = function(id) {
	this.get(id).tab("show");
	// sometimes panel is in detached DOM so we explicitly activate it
	this._getPanel(id).addClass("active");
};

Echo.GUI.Tabs.prototype._getTabIndex = function(id) {
	var entries = this.config.get("entries");
	for (var i = 0; i < entries.length; i++) {
		if (entries[i].id === id) {
			return i;
		}
	}
	return -1;
}

Echo.GUI.Tabs.prototype._getPanel = function(id) {
	return this.getPanels().find("#" + this._getTabFullId(id));
};

Echo.GUI.Tabs.prototype._getTabFullId = function(id) {
	return this.config.get("idPrefix") + id + this._randomId;
};

})(Echo.jQuery);
<|endoftext|>


<commit_before>define(function (require) {
   'use strict';

    var templates = require('js/templates'),
        template = templates['login'];

    return initialize;

    function initialize() {
        $('#app').fadeOut(function() {
            console.log(template);
            $('#app').html(template).fadeIn();
        });
    }
});<commit_msg>switch page correct<commit_after>define(function (require) {
   'use strict';

    var templates = require('js/templates'),
        template = templates['login'].render();

    return initialize;

    function initialize() {
        $('#app').fadeOut(function() {
            $('#app').html(template).fadeIn();
        });
    }
});<|endoftext|>


<commit_before>// Copyright (c) 2015 - 2017 Uber Technologies, 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.

import {WebMercatorViewport} from 'deck.gl/lib/viewports';
import test from 'tape-catch';
import {vec2, vec3} from 'gl-matrix';
import {WebMercatorViewport} from 'deck.gl';

/* eslint-disable */
const TEST_VIEWPORTS = [
  {
    mapState: {
      width: 793,
      height: 775,
      latitude: 37.751537058389985,
      longitude: -122.42694203247012,
      zoom: 11.5
    }
  },
  {
    mapState: {
      width: 793,
      height: 775,
      latitude: 20.751537058389985,
      longitude: 22.42694203247012,
      zoom: 15.5
    }
  },
  {
    mapState: {
      width: 793,
      height: 775,
      latitude: 50.751537058389985,
      longitude: 42.42694203247012,
      zoom: 15.5,
      bearing: -44.48928121059271,
      pitch: 43.670797287818566
    }
  }
];

test('WebMercatorViewport#imports', t => {
  t.ok(WebMercatorViewport, 'WebMercatorViewport import ok');
  t.end();
});

test('WebMercatorViewport#constructor', t => {
  t.ok(new WebMercatorViewport() instanceof WebMercatorViewport,
    'Created new WebMercatorViewport with default args');
  t.end();
});

test('WebMercatorViewport#constructor - 0 width/height', t => {
  const viewport = new WebMercatorViewport(Object.assign(TEST_VIEWPORTS[0].mapState, {
    width: 0,
    height: 0
  }));
  t.ok(viewport instanceof WebMercatorViewport,
    'WebMercatorViewport constructed successfully with 0 width and height');
  t.end();
});

test('WebMercatorViewport.projectFlat', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const tc of TEST_VIEWPORTS) {
      const lnglatIn = [tc.mapState.longitude, tc.mapState.latitude];
      const xy = viewport.projectFlat(lnglatIn);
      const lnglat = viewport.unprojectFlat(xy);
      t.comment(`Comparing [${lnglatIn}] to [${lnglat}]`);
      t.ok(vec2.equals(lnglatIn, lnglat));
    }
  }
  t.end();
});

test('WebMercatorViewport.project#3D', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const offset of [0, 0.5, 1.0, 5.0]) {
      const lnglatIn = [vc.mapState.longitude + offset, vc.mapState.latitude + offset];
      const xyz = viewport.project(lnglatIn);
      const lnglat = viewport.unproject(xyz);
      t.ok(vec2.equals(lnglatIn, lnglat), `Project/unproject ${lnglatIn} to ${lnglat}`);

      const lnglatIn3 = [vc.mapState.longitude + offset, vc.mapState.latitude + offset, 0];
      const xyz3 = viewport.project(lnglatIn3);
      const lnglat3 = viewport.unproject(xyz3);
      t.ok(vec3.equals(lnglatIn3, lnglat3),
        `Project/unproject ${lnglatIn3}=>${xyz3}=>${lnglat3}`);
    }
  }
  t.end();
});

test('WebMercatorViewport.project#2D', t => {
  // Cross check positions
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const tc of TEST_VIEWPORTS) {
      const lnglatIn = [tc.mapState.longitude, tc.mapState.latitude];
      const xy = viewport.project(lnglatIn);
      const lnglat = viewport.unproject(xy);
      t.comment(`Comparing [${lnglatIn}] to [${lnglat}]`);
      t.ok(vec2.equals(lnglatIn, lnglat));
    }
  }
  t.end();
});

test('WebMercatorViewport.getScales', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    const distanceScales = viewport.getDistanceScales();
    t.ok(Array.isArray(distanceScales.metersPerPixel), 'metersPerPixel defined');
    t.ok(Array.isArray(distanceScales.pixelsPerMeter), 'pixelsPerMeter defined');
    t.ok(Array.isArray(distanceScales.degreesPerPixel), 'degreesPerPixel defined');
    t.ok(Array.isArray(distanceScales.pixelsPerDegree), 'pixelsPerDegree defined');
  }
  t.end();
});

test('WebMercatorViewport.meterDeltas', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const tc of TEST_VIEWPORTS) {
      const coordinate = [tc.mapState.longitude, tc.mapState.latitude, 0];
      const deltaLngLat = viewport.metersToLngLatDelta(coordinate);
      const deltaMeters = viewport.lngLatDeltaToMeters(deltaLngLat);
      t.comment(`Comparing [${deltaMeters}] to [${coordinate}]`);
      t.ok(vec2.equals(deltaMeters, coordinate));
    }
  }
  t.end();
});
<commit_msg>Remove a leftover line from rebase in previous commit<commit_after>// Copyright (c) 2015 - 2017 Uber Technologies, 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.

import test from 'tape-catch';
import {vec2, vec3} from 'gl-matrix';
import {WebMercatorViewport} from 'deck.gl';

/* eslint-disable */
const TEST_VIEWPORTS = [
  {
    mapState: {
      width: 793,
      height: 775,
      latitude: 37.751537058389985,
      longitude: -122.42694203247012,
      zoom: 11.5
    }
  },
  {
    mapState: {
      width: 793,
      height: 775,
      latitude: 20.751537058389985,
      longitude: 22.42694203247012,
      zoom: 15.5
    }
  },
  {
    mapState: {
      width: 793,
      height: 775,
      latitude: 50.751537058389985,
      longitude: 42.42694203247012,
      zoom: 15.5,
      bearing: -44.48928121059271,
      pitch: 43.670797287818566
    }
  }
];

test('WebMercatorViewport#imports', t => {
  t.ok(WebMercatorViewport, 'WebMercatorViewport import ok');
  t.end();
});

test('WebMercatorViewport#constructor', t => {
  t.ok(new WebMercatorViewport() instanceof WebMercatorViewport,
    'Created new WebMercatorViewport with default args');
  t.end();
});

test('WebMercatorViewport#constructor - 0 width/height', t => {
  const viewport = new WebMercatorViewport(Object.assign(TEST_VIEWPORTS[0].mapState, {
    width: 0,
    height: 0
  }));
  t.ok(viewport instanceof WebMercatorViewport,
    'WebMercatorViewport constructed successfully with 0 width and height');
  t.end();
});

test('WebMercatorViewport.projectFlat', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const tc of TEST_VIEWPORTS) {
      const lnglatIn = [tc.mapState.longitude, tc.mapState.latitude];
      const xy = viewport.projectFlat(lnglatIn);
      const lnglat = viewport.unprojectFlat(xy);
      t.comment(`Comparing [${lnglatIn}] to [${lnglat}]`);
      t.ok(vec2.equals(lnglatIn, lnglat));
    }
  }
  t.end();
});

test('WebMercatorViewport.project#3D', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const offset of [0, 0.5, 1.0, 5.0]) {
      const lnglatIn = [vc.mapState.longitude + offset, vc.mapState.latitude + offset];
      const xyz = viewport.project(lnglatIn);
      const lnglat = viewport.unproject(xyz);
      t.ok(vec2.equals(lnglatIn, lnglat), `Project/unproject ${lnglatIn} to ${lnglat}`);

      const lnglatIn3 = [vc.mapState.longitude + offset, vc.mapState.latitude + offset, 0];
      const xyz3 = viewport.project(lnglatIn3);
      const lnglat3 = viewport.unproject(xyz3);
      t.ok(vec3.equals(lnglatIn3, lnglat3),
        `Project/unproject ${lnglatIn3}=>${xyz3}=>${lnglat3}`);
    }
  }
  t.end();
});

test('WebMercatorViewport.project#2D', t => {
  // Cross check positions
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const tc of TEST_VIEWPORTS) {
      const lnglatIn = [tc.mapState.longitude, tc.mapState.latitude];
      const xy = viewport.project(lnglatIn);
      const lnglat = viewport.unproject(xy);
      t.comment(`Comparing [${lnglatIn}] to [${lnglat}]`);
      t.ok(vec2.equals(lnglatIn, lnglat));
    }
  }
  t.end();
});

test('WebMercatorViewport.getScales', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    const distanceScales = viewport.getDistanceScales();
    t.ok(Array.isArray(distanceScales.metersPerPixel), 'metersPerPixel defined');
    t.ok(Array.isArray(distanceScales.pixelsPerMeter), 'pixelsPerMeter defined');
    t.ok(Array.isArray(distanceScales.degreesPerPixel), 'degreesPerPixel defined');
    t.ok(Array.isArray(distanceScales.pixelsPerDegree), 'pixelsPerDegree defined');
  }
  t.end();
});

test('WebMercatorViewport.meterDeltas', t => {
  for (const vc of TEST_VIEWPORTS) {
    const viewport = new WebMercatorViewport(vc.mapState);
    for (const tc of TEST_VIEWPORTS) {
      const coordinate = [tc.mapState.longitude, tc.mapState.latitude, 0];
      const deltaLngLat = viewport.metersToLngLatDelta(coordinate);
      const deltaMeters = viewport.lngLatDeltaToMeters(deltaLngLat);
      t.comment(`Comparing [${deltaMeters}] to [${coordinate}]`);
      t.ok(vec2.equals(deltaMeters, coordinate));
    }
  }
  t.end();
});
<|endoftext|>


<commit_before>'use strict'

import {Component}      from 'react'
import {Link}           from 'react-router'
import DocumentTitle    from 'react-document-title'

import Header           from '../components/Header'
import Footer           from '../components/Footer'
import CardLink         from '../components/CardLink'

class ContentSection extends Component {
  static propTypes: {
    markup: PropTypes.string.isRequired,
    className: PropTypes.string
  }

  render() {
    return(

    )
  }
}

class IntroPage extends Component {

  render() {

    return (
      <DocumentTitle title="Blockstack - Intro">

                    Intro to Blockstack

          <ContentSection className="m-b-50"
            markup="

              Blockstack is a new decentralized internet.

              With Blockstack, users control their data and apps run on their devices.
              There are no middlemen, no passwords, no massive data silos to breach,
              and no services tracking us around the internet.

              The applications on blockstack are server-less and decentralized.

              Developers start by building a single-page application in Javascript,

              Then, instead of plugging the frontend into a centralized API,
              they plug into an API run by the user.

              Developers install a library called 'blockstack.js' and
              don't have to worry about running servers, maintaining databases,
              or building out user management systems.

              Personal user APIs ship with the Blockstack app and
              handle everything from identity and authentication
              to data storage.

              Applications can request permissions from users and then
              gain read and write access to user resources.

              Data storage is simple and reliable and uses existing cloud infrastructure.

              Users connect with their Dropbox, Google Drive, etc and data is synced from
              their local device up to the cloud.

              Identity is user-controlled and utilizes the blockchain for secure management
              of keys, devices and usernames.

              When users login with apps, they are anonymous by default and use an
              app-specific key, but their full identity can be revealed and proven
              at any time.

              Keys are for signing and encryption and can be changed
              as devices need to be added or removed.

              Under the hood, Blockstack provides a decentralized domain name system (DNS),
              decentralized public key distribution system,
              and registry for apps and user identities.

              Here's a diagram laying out the major components of Blockstack and showing how it works under the hood:

" />

                    How Blockstack Works

          <ContentSection className="m-b-50 m-t-50"
            markup="

              To get started building apps on Blockstack,
              read the developer documentation,
              setup a Blockstack Core node,
              and preview the Blockstack Browser (in an experimantal alpha).

" />

                    <CardLink
                      href='/docs'
                      title='Docs'
                      body="Documentation for the Blockstack Browser, Blockstack Core, and Blockstack Explorer."
                      imageSrc="/images/article-photos/bookshelves.jpg"
                      cardsPerRow={3} />
                    <CardLink
                      href='https://github.com/blockstack/blockstack-cli'
                      title='Blockstack Core'
                      body="A server you can run that becomes a part of the Blockstack P2P network and maintains the DNS, PKI and identity system."
                      imageSrc="/images/article-photos/passport.jpg"
                      target="_blank"
                      cardsPerRow={3} />
                    <CardLink
                      href='https://github.com/blockstack/blockstack-browser/releases'
                      title='Blockstack Browser'
                      body="A desktop app you can install to upgrade your browsers and turn them into blockstack-enabled browsers."
                      imageSrc="/images/article-photos/astronaut.jpg"
                      target="_blank"
                      cardsPerRow={3} />

          <ContentSection className="m-b-50 m-t-50"
            markup="

                    To learn more about Blockstack, read the papers,
                    watch the videos, and check out the Blockstack Blog.

" />

                    <CardLink
                      href='/papers'
                      title='Papers'
                      body="Academic papers on Blockstack's DNS/naming, storage, identity, and authentication systems."
                      imageSrc="/images/article-photos/booklets.jpg"
                      cardsPerRow={3} />
                    <CardLink
                      href='/videos'
                      title='Videos'
                      body="Videos of talks given about what Blockstack is, how it works, and what can be built on top of it."
                      imageSrc="/images/article-photos/scribble.jpg"
                      cardsPerRow={3} />
                    <CardLink
                      href='/blog'
                      title='Blog'
                      body="Blog with the latest developments about Blockstack, including product announcements and technical writeups."
                      imageSrc="/images/article-photos/computer.jpg"
                      cardsPerRow={3} />

      </DocumentTitle>
    )
  }

}

export default IntroPage
<commit_msg>Small typo fixing in IntroPage.js<commit_after>'use strict'

import {Component}      from 'react'
import {Link}           from 'react-router'
import DocumentTitle    from 'react-document-title'

import Header           from '../components/Header'
import Footer           from '../components/Footer'
import CardLink         from '../components/CardLink'

class ContentSection extends Component {
  static propTypes: {
    markup: PropTypes.string.isRequired,
    className: PropTypes.string
  }

  render() {
    return(

    )
  }
}

class IntroPage extends Component {

  render() {

    return (
      <DocumentTitle title="Blockstack - Intro">

                    Intro to Blockstack

          <ContentSection className="m-b-50"
            markup="

              Blockstack is a new decentralized internet.

              With Blockstack, users control their data and apps run on their devices.
              There are no middlemen, no passwords, no massive data silos to breach,
              and no services tracking us around the internet.

              The applications on blockstack are server-less and decentralized.

              Developers start by building a single-page application in Javascript,

              Then, instead of plugging the frontend into a centralized API,
              they plug into an API run by the user.

              Developers install a library called 'blockstack.js' and
              don't have to worry about running servers, maintaining databases,
              or building out user management systems.

              Personal user APIs ship with the Blockstack app and
              handle everything from identity and authentication
              to data storage.

              Applications can request permissions from users and then
              gain read and write access to user resources.

              Data storage is simple and reliable and uses existing cloud infrastructure.

              Users connect with their Dropbox, Google Drive, etc and data is synced from
              their local device up to the cloud.

              Identity is user-controlled and utilizes the blockchain for secure management
              of keys, devices and usernames.

              When users login with apps, they are anonymous by default and use an
              app-specific key, but their full identity can be revealed and proven
              at any time.

              Keys are for signing and encryption and can be changed
              as devices need to be added or removed.

              Under the hood, Blockstack provides a decentralized domain name system (DNS),
              decentralized public key distribution system,
              and registry for apps and user identities.

              Here's a diagram laying out the major components of Blockstack and showing how it works under the hood:

" />

                    How Blockstack Works

          <ContentSection className="m-b-50 m-t-50"
            markup="

              To get started building apps on Blockstack,
              read the developer documentation,
              setup a Blockstack Core node,
              and preview the Blockstack Browser (in an experimental alpha).

" />

                    <CardLink
                      href='/docs'
                      title='Docs'
                      body="Documentation for the Blockstack Browser, Blockstack Core, and Blockstack Explorer."
                      imageSrc="/images/article-photos/bookshelves.jpg"
                      cardsPerRow={3} />
                    <CardLink
                      href='https://github.com/blockstack/blockstack-cli'
                      title='Blockstack Core'
                      body="A server you can run that becomes a part of the Blockstack P2P network and maintains the DNS, PKI and identity system."
                      imageSrc="/images/article-photos/passport.jpg"
                      target="_blank"
                      cardsPerRow={3} />
                    <CardLink
                      href='https://github.com/blockstack/blockstack-browser/releases'
                      title='Blockstack Browser'
                      body="A desktop app you can install to upgrade your browsers and turn them into blockstack-enabled browsers."
                      imageSrc="/images/article-photos/astronaut.jpg"
                      target="_blank"
                      cardsPerRow={3} />

          <ContentSection className="m-b-50 m-t-50"
            markup="

                    To learn more about Blockstack, read the papers,
                    watch the videos, and check out the Blockstack Blog.

" />

                    <CardLink
                      href='/papers'
                      title='Papers'
                      body="Academic papers on Blockstack's DNS/naming, storage, identity, and authentication systems."
                      imageSrc="/images/article-photos/booklets.jpg"
                      cardsPerRow={3} />
                    <CardLink
                      href='/videos'
                      title='Videos'
                      body="Videos of talks given about what Blockstack is, how it works, and what can be built on top of it."
                      imageSrc="/images/article-photos/scribble.jpg"
                      cardsPerRow={3} />
                    <CardLink
                      href='/blog'
                      title='Blog'
                      body="Blog with the latest developments about Blockstack, including product announcements and technical writeups."
                      imageSrc="/images/article-photos/computer.jpg"
                      cardsPerRow={3} />

      </DocumentTitle>
    )
  }

}

export default IntroPage
<|endoftext|>


<commit_before>const chai = require('chai');
const expect = chai.expect;
const _ = require('lodash');
const { enrichment } = require('../../../../src/server/external-services/gprofiler');

describe('Test Enrichment Analysis Service', function () {
  this.timeout(500000);
  it('parameters: valid genes', function () {
    return (enrichment(['AFF4'])).then(
      //resolved
      function (res) {
      const result = {
        "pathwayInfo": {
          "GO:0006354": {
            "p_value": 0.0087,
            "description": "DNA-templated transcription, elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "GO:0006368": {
            "p_value": 0.0087,
            "description": "transcription elongation from RNA polymerase II promoter",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:674695": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Pre-transcription Events",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:75955": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Transcription Elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:112382": {
            "p_value": 0.00775,
            "description": "Formation of RNA Pol II elongation complex",
            "intersection": [
              "AFF4"
            ]
          }
        }
      };
      expect(res).to.deep.equal(result);
    },
    //rejected
    rej => {
    console.log("rejected");
    }
    );
  });

  it('parameters: valid genes, valid minSetSize, valid maxSetSize, empty backgroundGenes', function () {
    return (enrichment(['AFF4'], {minSetSize: 3, maxSetSize:400, backgroundGenes: []})).then(
      //resolved
      res=> {
      const result = {
        "pathwayInfo": {
          "GO:0006354": {
            "p_value": 0.0087,
            "description": "DNA-templated transcription, elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "GO:0006368": {
            "p_value": 0.0087,
            "description": "transcription elongation from RNA polymerase II promoter",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:674695": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Pre-transcription Events",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:75955": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Transcription Elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:112382": {
            "p_value": 0.00775,
            "description": "Formation of RNA Pol II elongation complex",
            "intersection": [
              "AFF4"
            ]
          }
        }
      };
      expect(res).to.deep.equal(result);
    },
    //rejected
    rej => {
    console.log("rejected")
    }
    );
  });

  it('parameters: valid genes, valid minSetSize, invalid maxSetSize, empty backgroundGenes', function () {
    return (enrichment(['AFF4'], {minSetSize: 3, maxSetSize:"not a number", backgroundGenes: []})).then(
      //resolved
      res => {
      console.log("resolved");
      },
      //rejected
      rej => {
      expect(true);
      }
    );
  });

  it('parameters: valid genes, valid minSetSize, valid maxSetSize, valid backgroundGenes', function () {
    return (enrichment(["DOT1L","AFF4","NAP1L3","BRPF1","TCF20","HLTF","SIRT1","TDG","SUV39H2","CBX7","DNMT1","DPY30","ING5","MLLT6","CHD1L","USP27X","BRPF3","ELP4","HCFC1","MARCH5","SCML2","PRDM10","SUPT16H","TRIM24","GTF2H1","KDM3A","PAF1","PCGF5","BAZ1B","NCOA1","UBE2B","SGF29","KDM5B","MTA3","PCMT1","GTF3C4","MTA2","RBBP4","RNF20","SETD2","SSRP1","MBD1","POLR2B","TP53BP1","UBR7","ARID4B","ASH1L","BRD4","HAT1","HDAC1","KAT2A","MBD3","MSL3","RPA3","BAZ2A","JMJD6","PHF7","SIN3B","SP100","ZMYND11"],
     {minSetSize: 5, maxSetSize: 250,
      backgroundGenes: ["HDAC3","TRIM24","PRDM6","ATR","PBRM1","PHF3","ING4","DNMT1","NCOA1","TDG","BRD4","BRPF1","AFF4","ATRX","MTA1","ASH1L","USP27X","DOT1L","ELP4","RING1","JMJD4","HDAC4","KAT6A","NCOR1","PSIP1","RBBP5","ASXL3","MLLT6","MARCH5","PARP2","TRIM28","INO80","TCF20","CBX7","POLR2B","TDRD6","NCOR2","PRMT5","HDAC8","SMARCA2","CHD1","DMAP1","KDM5A","HLTF","KMT2A","MUM1","DPY30","HCFC1","KAT2A","MTA3","NAP1L3","HDGFL2","NSD2","CHD5","RAI1","ELP3","CBX2","PRDM10","CBX5","NSD1","PHF12","BAZ1B","BRPF3","PCGF5","SUV39H2","PRDM1","SCML2","BOP1","TRIM33","ING5","PRDM16","EP300","PRMT1","SIRT1","SMARCD1","BAZ2B","KDM3B","EPC2","FBXO44","KDM5D","KIAA2026","PCMT1","PRDM14","GTF3C4","HSPBAP1","L3MBTL2","PHC1","SETD2","SETDB1","SMNDC1","DNMT3B","ZCWPW2","GTF2B","TDRD3","KDM4B","PADI4","BRD2","EZH2","KDM4D","LBR","SFMBT1","SP140","SSRP1","ATM","SIN3B","SUPT16H","TP53BP1","CHD1L","CHD4","PHF7","PRMT8","RAG2","ARID4B","ERCC5","KDM5B","MBD1","MTF2","PRDM5","RPA3","ZMYND11","FKBP1A","MEN1","SIRT4","SIRT7","SMYD4","KAT2B","KAT8","KDM2A","KDM2B","L3MBTL3","RNF20","SETD5","ASH2L","SETDB2","USP17L5","GTF2F1","HR","KDM3A","PAF1","UBE2B","CBX4","GTF2H1","PRMT7","FBXL19","HDAC1","SETD6","SFMBT2","SMYD1","TDRD5","CDY2A","CHD3","ING3","JMJD6","MBTD1","NAP1L1","PADI1","SETD1A","SIRT5","SMN1","TAF1","USP22","BAZ1A","SGF29","KAT5","MBD3","MTA2","PADI3","PHF8","PRDM12","PRMT6","RBBP4","RBBP7","SETMAR","SP110","BPTF","CDY1","MSL3","PHF6","PHIP","TDRKH","UBR7","CDYL2","CLOCK","GADD45B","HAT1","PHF13","PRKAA2","BAZ2A","BRWD3","L3MBTL4","MLLT10","RNF217","SMYD5","PHF11","PHF16","KMT5B","WDR82","BRD1","GLYR1","HDAC2","KANSL1","KDM4E","PAXIP1","JADE1","SP100","SP140L","TDRD10","TRIM66","EED","EZH1","ORC1","PHC3","PRDM9","SIRT2","ZGPAT","CREBBP","DNMT3A","HELLS","KAT7","RNF17","TAF1L","ZMYND8","AIRE","RIOX1","CARM1","EHMT2","EP400","HDAC7","KDM1A","MBD2","MBD4","PRKAA1","SHPRH","SMARCC2","BRD3","ING2","JMJD8","MPHOSPH8","PHF21A","SATB1","SCMH1","TET1","UBE2E1","CHAF1A","FKBP2","H2AFZ","HDAC11","KAT6B","KDM6A","NCOA3","PADI6","PRDM15","PWWP2B","SCML4","SIN3A","SMARCE1","USP51","ASXL1","CHD7","CHD9","DNMT3L","FBXW9","INTS12","L3MBTL1","MBD5","MECP2","NAP1L2","PHF2","KMT5A","SMARCA4","SRCAP","ASXL2","CHAF1B","CSTL1","FKBP5","FMR1","FXR2","HDAC6","ING1","IWS1","JARID2","KDM4A","PCGF6","PHF20","PHF21B","PRMT2","SETD7","SIRT6","SMYD3","DPF2","PCGF2","PHC2","PRMT3","STK31","TDRD12","TET2","TET3","UHRF1","WDR5","CDYL","CECR2","CXXC1","EHMT1","G2E3","HDAC10","KDM4C","KDM6B","KDM8","PARP1","PCGF1","PRDM13","SIRT3","SMARCA1","SMARCC1","TDRD7","UBE2A","UHRF2","AFF1","AKAP1","ARID4A","ATAD2","BRD8","HDAC5","MORF4L1","PHF10","PYGO2","SMYD2","SUV39H1","TCEA1","TCF19","TDRD1","TDRD9","NSD3","BRD9","CBX1","HDGFL1","HIRA","KDM5C","MECOM","KMT2E","PHF1","PHRF1","PRDM2","PRKCD","RNF2","SMARCA5","SUZ12","BMI1","BRDT","CHD2","CHD6","EPC1","JMJD1C","KMT2C","KMT2D","MSH6","PHF19","PHF20L1","PHF23","PRDM4","SETD1B","TAF3","UTY","ATAD2B","ATAT1","AURKB","BRWD1","CHD8","HDGFRP3","JMJD7-PLA2G4B","KDM1B","JADE2","KMT5C","BRD7","CBX8","DIDO1","FBXO17","GAPDH","PHF5A","PPARGC1A","PRDM11","PRDM7","REN","RPH3A","SETD3","UBE2I","ZCWPW1","HIF1AN","PRDM8","SETD4","SMARCD3","CBX3","CBX6","GADD45A","HDAC9","PADI2","ACTL6B","DPF3","PHF14","RNF40","PYGO1","RSF1","SND1","HDGF","RIOX2","MYC","DPF1"]})).then(
      //resolved
      res => {
        const result = {
          "pathwayInfo": {
            "GO:0006354": {
              "p_value": 0.0289,
              "description": "DNA-templated transcription, elongation",
              "intersection": [
                "PAF1",
                "ZMYND11",
                "POLR2B",
                "AFF4",
                "SUPT16H",
                "ELP4",
                "GTF2H1",
                "BRD4",
                "SSRP1",
                "SETD2"
              ]
            },
            "GO:0006368": {
              "p_value": 0.0289,
              "description": "transcription elongation from RNA polymerase II promoter",
              "intersection": [
                "PAF1",
                "ZMYND11",
                "POLR2B",
                "AFF4",
                "SUPT16H",
                "ELP4",
                "GTF2H1",
                "BRD4",
                "SSRP1",
                "SETD2"
              ]
            }
          }
        };
        expect(res).to.deep.equal(result);
      },
      //rejected
      rej => {
        console.log("rejected");
      }
    );
  });
});<commit_msg>Accomodating test for changes to analysis API<commit_after>const chai = require('chai');
const expect = chai.expect;
const _ = require('lodash');
const { enrichment } = require('../../../../src/server/external-services/gprofiler');

describe('Test Enrichment Analysis Service', function () {
  this.timeout(500000);
  it('parameters: valid genes', function () {
    return (enrichment(['AFF4'])).then(
      //resolved
      function (res) {
      const result = {
        "pathwayInfo": {
          "GO:0006354": {
            "p_value": 0.0087,
            "description": "DNA-templated transcription, elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "GO:0006368": {
            "p_value": 0.0087,
            "description": "transcription elongation from RNA polymerase II promoter",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:674695": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Pre-transcription Events",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:75955": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Transcription Elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:112382": {
            "p_value": 0.00775,
            "description": "Formation of RNA Pol II elongation complex",
            "intersection": [
              "AFF4"
            ]
          }
        }
      };
      expect(res).to.deep.equal(result);
    },
    //rejected
    rej => {
    console.log("rejected");
    }
    );
  });

  it('parameters: valid genes, valid minSetSize, valid maxSetSize, empty background', function () {
    return (enrichment(['AFF4'], {minSetSize: 3, maxSetSize:400, background: []})).then(
      //resolved
      res=> {
      const result = {
        "pathwayInfo": {
          "GO:0006354": {
            "p_value": 0.0087,
            "description": "DNA-templated transcription, elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "GO:0006368": {
            "p_value": 0.0087,
            "description": "transcription elongation from RNA polymerase II promoter",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:674695": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Pre-transcription Events",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:75955": {
            "p_value": 0.00775,
            "description": "RNA Polymerase II Transcription Elongation",
            "intersection": [
              "AFF4"
            ]
          },
          "REAC:112382": {
            "p_value": 0.00775,
            "description": "Formation of RNA Pol II elongation complex",
            "intersection": [
              "AFF4"
            ]
          }
        }
      };
      expect(res).to.deep.equal(result);
    },
    //rejected
    rej => {
    console.log("rejected")
    }
    );
  });

  it('parameters: valid genes, valid minSetSize, invalid maxSetSize, empty background', function () {
    return (enrichment(['AFF4'], {minSetSize: 3, maxSetSize:"not a number", background: []})).then(
      //resolved
      res => {
      console.log("resolved");
      },
      //rejected
      rej => {
      expect(true);
      }
    );
  });

  it('parameters: valid genes, valid minSetSize, valid maxSetSize, valid background', function () {
    return (enrichment(["DOT1L","AFF4","NAP1L3","BRPF1","TCF20","HLTF","SIRT1","TDG","SUV39H2","CBX7","DNMT1","DPY30","ING5","MLLT6","CHD1L","USP27X","BRPF3","ELP4","HCFC1","MARCH5","SCML2","PRDM10","SUPT16H","TRIM24","GTF2H1","KDM3A","PAF1","PCGF5","BAZ1B","NCOA1","UBE2B","SGF29","KDM5B","MTA3","PCMT1","GTF3C4","MTA2","RBBP4","RNF20","SETD2","SSRP1","MBD1","POLR2B","TP53BP1","UBR7","ARID4B","ASH1L","BRD4","HAT1","HDAC1","KAT2A","MBD3","MSL3","RPA3","BAZ2A","JMJD6","PHF7","SIN3B","SP100","ZMYND11"],
     {minSetSize: 5, maxSetSize: 250,
      background: ["HDAC3","TRIM24","PRDM6","ATR","PBRM1","PHF3","ING4","DNMT1","NCOA1","TDG","BRD4","BRPF1","AFF4","ATRX","MTA1","ASH1L","USP27X","DOT1L","ELP4","RING1","JMJD4","HDAC4","KAT6A","NCOR1","PSIP1","RBBP5","ASXL3","MLLT6","MARCH5","PARP2","TRIM28","INO80","TCF20","CBX7","POLR2B","TDRD6","NCOR2","PRMT5","HDAC8","SMARCA2","CHD1","DMAP1","KDM5A","HLTF","KMT2A","MUM1","DPY30","HCFC1","KAT2A","MTA3","NAP1L3","HDGFL2","NSD2","CHD5","RAI1","ELP3","CBX2","PRDM10","CBX5","NSD1","PHF12","BAZ1B","BRPF3","PCGF5","SUV39H2","PRDM1","SCML2","BOP1","TRIM33","ING5","PRDM16","EP300","PRMT1","SIRT1","SMARCD1","BAZ2B","KDM3B","EPC2","FBXO44","KDM5D","KIAA2026","PCMT1","PRDM14","GTF3C4","HSPBAP1","L3MBTL2","PHC1","SETD2","SETDB1","SMNDC1","DNMT3B","ZCWPW2","GTF2B","TDRD3","KDM4B","PADI4","BRD2","EZH2","KDM4D","LBR","SFMBT1","SP140","SSRP1","ATM","SIN3B","SUPT16H","TP53BP1","CHD1L","CHD4","PHF7","PRMT8","RAG2","ARID4B","ERCC5","KDM5B","MBD1","MTF2","PRDM5","RPA3","ZMYND11","FKBP1A","MEN1","SIRT4","SIRT7","SMYD4","KAT2B","KAT8","KDM2A","KDM2B","L3MBTL3","RNF20","SETD5","ASH2L","SETDB2","USP17L5","GTF2F1","HR","KDM3A","PAF1","UBE2B","CBX4","GTF2H1","PRMT7","FBXL19","HDAC1","SETD6","SFMBT2","SMYD1","TDRD5","CDY2A","CHD3","ING3","JMJD6","MBTD1","NAP1L1","PADI1","SETD1A","SIRT5","SMN1","TAF1","USP22","BAZ1A","SGF29","KAT5","MBD3","MTA2","PADI3","PHF8","PRDM12","PRMT6","RBBP4","RBBP7","SETMAR","SP110","BPTF","CDY1","MSL3","PHF6","PHIP","TDRKH","UBR7","CDYL2","CLOCK","GADD45B","HAT1","PHF13","PRKAA2","BAZ2A","BRWD3","L3MBTL4","MLLT10","RNF217","SMYD5","PHF11","PHF16","KMT5B","WDR82","BRD1","GLYR1","HDAC2","KANSL1","KDM4E","PAXIP1","JADE1","SP100","SP140L","TDRD10","TRIM66","EED","EZH1","ORC1","PHC3","PRDM9","SIRT2","ZGPAT","CREBBP","DNMT3A","HELLS","KAT7","RNF17","TAF1L","ZMYND8","AIRE","RIOX1","CARM1","EHMT2","EP400","HDAC7","KDM1A","MBD2","MBD4","PRKAA1","SHPRH","SMARCC2","BRD3","ING2","JMJD8","MPHOSPH8","PHF21A","SATB1","SCMH1","TET1","UBE2E1","CHAF1A","FKBP2","H2AFZ","HDAC11","KAT6B","KDM6A","NCOA3","PADI6","PRDM15","PWWP2B","SCML4","SIN3A","SMARCE1","USP51","ASXL1","CHD7","CHD9","DNMT3L","FBXW9","INTS12","L3MBTL1","MBD5","MECP2","NAP1L2","PHF2","KMT5A","SMARCA4","SRCAP","ASXL2","CHAF1B","CSTL1","FKBP5","FMR1","FXR2","HDAC6","ING1","IWS1","JARID2","KDM4A","PCGF6","PHF20","PHF21B","PRMT2","SETD7","SIRT6","SMYD3","DPF2","PCGF2","PHC2","PRMT3","STK31","TDRD12","TET2","TET3","UHRF1","WDR5","CDYL","CECR2","CXXC1","EHMT1","G2E3","HDAC10","KDM4C","KDM6B","KDM8","PARP1","PCGF1","PRDM13","SIRT3","SMARCA1","SMARCC1","TDRD7","UBE2A","UHRF2","AFF1","AKAP1","ARID4A","ATAD2","BRD8","HDAC5","MORF4L1","PHF10","PYGO2","SMYD2","SUV39H1","TCEA1","TCF19","TDRD1","TDRD9","NSD3","BRD9","CBX1","HDGFL1","HIRA","KDM5C","MECOM","KMT2E","PHF1","PHRF1","PRDM2","PRKCD","RNF2","SMARCA5","SUZ12","BMI1","BRDT","CHD2","CHD6","EPC1","JMJD1C","KMT2C","KMT2D","MSH6","PHF19","PHF20L1","PHF23","PRDM4","SETD1B","TAF3","UTY","ATAD2B","ATAT1","AURKB","BRWD1","CHD8","HDGFRP3","JMJD7-PLA2G4B","KDM1B","JADE2","KMT5C","BRD7","CBX8","DIDO1","FBXO17","GAPDH","PHF5A","PPARGC1A","PRDM11","PRDM7","REN","RPH3A","SETD3","UBE2I","ZCWPW1","HIF1AN","PRDM8","SETD4","SMARCD3","CBX3","CBX6","GADD45A","HDAC9","PADI2","ACTL6B","DPF3","PHF14","RNF40","PYGO1","RSF1","SND1","HDGF","RIOX2","MYC","DPF1"]})).then(
      //resolved
      res => {
        const result = {
          "pathwayInfo": {
            "GO:0006354": {
              "p_value": 0.0289,
              "description": "DNA-templated transcription, elongation",
              "intersection": [
                "PAF1",
                "ZMYND11",
                "POLR2B",
                "AFF4",
                "SUPT16H",
                "ELP4",
                "GTF2H1",
                "BRD4",
                "SSRP1",
                "SETD2"
              ]
            },
            "GO:0006368": {
              "p_value": 0.0289,
              "description": "transcription elongation from RNA polymerase II promoter",
              "intersection": [
                "PAF1",
                "ZMYND11",
                "POLR2B",
                "AFF4",
                "SUPT16H",
                "ELP4",
                "GTF2H1",
                "BRD4",
                "SSRP1",
                "SETD2"
              ]
            }
          }
        };
        expect(res).to.deep.equal(result);
      },
      //rejected
      rej => {
        console.log("rejected");
      }
    );
  });
});<|endoftext|>


<commit_before>const crypto = require('crypto');
const { declareInjections } = require('@cardstack/di');

module.exports = declareInjections({
  key: 'config:encryption-key'
},

class Encryptor {

  static create({ key }) {
    return new this(key);
  }

  constructor(key) {
    if (!(key instanceof Buffer) || key.length < 32) {
      throw new Error("key must be a buffer of at least 32 bytes");
    }
    this.key = key;
  }

  encryptAndSign(value) {
    // 32 bytes because our cipher block size is 32 bytes
    let iv = crypto.randomBytes(32);

    // Curious onlookers should realize that picking the wrong thing
    // here can be fatal -- openssl includes some cipher modes that
    // look similar that you should never ever use, like
    // aes-256-ecb. And we are relying on the fact that gcm mode does
    // both integrity and confidentiality.
    let cipher = crypto.createCipheriv('aes-256-gcm', this.key, iv);

    let ciphertext = cipher.update(JSON.stringify(value), 'utf8', 'base64');
    ciphertext += cipher.final('base64');

    return `${ciphertext}--${iv.toString('base64')}--${cipher.getAuthTag().toString('base64')}`;
  }

  verifyAndDecrypt(value) {
    let parts = value.split('--');
    if (parts.length !== 3) {
      throw new Error("Not a valid signed message");
    }
    let [ciphertext, iv, authTag] = parts;
    let authTagBuffer = Buffer.from(authTag, 'base64');
    if(authTagBuffer.length !== 16){
      throw new Error("Not a valid signed message");
    }
    let decipher = crypto.createDecipheriv('aes-256-gcm', this.key, Buffer.from(iv, 'base64'));
    decipher.setAuthTag(authTagBuffer);
    let decrypted = decipher.update(ciphertext, 'base64', 'utf8');
    decrypted += decipher.final('utf8');
    return JSON.parse(decrypted);
  }

});
<commit_msg>fixed authTag value<commit_after>const crypto = require('crypto');
const { declareInjections } = require('@cardstack/di');

module.exports = declareInjections({
  key: 'config:encryption-key'
},

class Encryptor {

  static create({ key }) {
    return new this(key);
  }

  constructor(key) {
    if (!(key instanceof Buffer) || key.length < 32) {
      throw new Error("key must be a buffer of at least 32 bytes");
    }
    this.key = key;
  }

  encryptAndSign(value) {
    // 32 bytes because our cipher block size is 32 bytes
    let iv = crypto.randomBytes(32);

    // Curious onlookers should realize that picking the wrong thing
    // here can be fatal -- openssl includes some cipher modes that
    // look similar that you should never ever use, like
    // aes-256-ecb. And we are relying on the fact that gcm mode does
    // both integrity and confidentiality.
    let cipher = crypto.createCipheriv('aes-256-gcm', this.key, iv);

    let ciphertext = cipher.update(JSON.stringify(value), 'utf8', 'base64');
    ciphertext += cipher.final('base64');

    return `${ciphertext}--${iv.toString('base64')}--${cipher.getAuthTag().toString('base64')}`;
  }

  verifyAndDecrypt(value) {
    let parts = value.split('--');
    if (parts.length !== 3) {
      throw new Error("Not a valid signed message");
    }
    let [ciphertext, iv, authTag] = parts;
    let authTagBuffer = Buffer.from(authTag, 'base64');
    if(authTagBuffer.length !== 16){
      throw new Error("unable to authenticate data");
    }
    let decipher = crypto.createDecipheriv('aes-256-gcm', this.key, Buffer.from(iv, 'base64'));
    decipher.setAuthTag(authTagBuffer);
    let decrypted = decipher.update(ciphertext, 'base64', 'utf8');
    decrypted += decipher.final('utf8');
    return JSON.parse(decrypted);
  }

});
<|endoftext|>


<commit_before>describe('PodViewController', function() {

    var vm, $rootScope, $state, $q, podSpy, notificationServiceMock, confirmServiceMock, confirmPromise;

    beforeEach(function() {
        notificationServiceMock = jasmine.createSpyObj('notificationService', ['success', 'error']);
        confirmServiceMock = jasmine.createSpyObj('confirmService', ['confirm']);
        podServiceMock = jasmine.createSpyObj('podService', ['save', 'submit']);
        podSpy = jasmine.createSpyObj('pod', ['isValid', 'isLineItemValid']);

        module('proof-of-delivery-view', function($provide) {
            $provide.service('notificationService', function() {
                return notificationServiceMock;
            });

            $provide.service('confirmService', function() {
                return confirmServiceMock;
            });

            $provide.service('podService', function() {
                return podServiceMock;
            });
        });

        inject(function(_$rootScope_, _$state_, _$q_, $controller) {
            $rootScope = _$rootScope_;
            $state = _$state_;
            $q = _$q_;

            vm = $controller('PodViewController', {
                pod: podSpy
            });
        });

        spyOn($state, 'reload').andReturn();

        confirmPromise = $q.when();
        confirmServiceMock.confirm.andReturn(confirmPromise);
    });

    it('initialization should expose pod', function() {
        expect(vm.pod).toEqual(podSpy);
    });

    describe('savePod', function() {

        var deferred;

        beforeEach(function() {
            deferred = $q.defer();
            podServiceMock.save.andReturn(deferred.promise);

            vm.savePod();
            $rootScope.$apply();
        });

        it('should show confirmation modal', function() {
            expect(confirmServiceMock.confirm).toHaveBeenCalledWith('msg.orders.savePodQuestion');
        });

        it('should save pod', function() {
            expect(podServiceMock.save).toHaveBeenCalledWith(podSpy);
        });

        it('should show success notification if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect(notificationServiceMock.success).toHaveBeenCalledWith('msg.podSaved');
        });

        it('should reload state if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect($state.reload).toHaveBeenCalled();
        });

        it('should show error notification if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect(notificationServiceMock.error).toHaveBeenCalledWith('msg.podSavedFailed');
        });

        it('should not reload state if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect($state.reload).not.toHaveBeenCalled();
        });

    });

    describe('submitPod', function() {

        var deferred;

        beforeEach(function() {
            deferred = $q.defer();
            podServiceMock.submit.andReturn(deferred.promise);

            vm.submitPod();
            $rootScope.$apply();
        });

        it('should show confirmation modal', function() {
            expect(confirmServiceMock.confirm).toHaveBeenCalledWith('msg.orders.submitPodQuestion');
        });

        it('should submit pod', function() {
            expect(podServiceMock.submit).toHaveBeenCalledWith(podSpy);
        });

        it('should show success notification if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect(notificationServiceMock.success).toHaveBeenCalledWith('msg.podSubmit');
        });

        it('should reload state if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect($state.reload).toHaveBeenCalled();
        });

        it('should show error notification if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect(notificationServiceMock.error).toHaveBeenCalledWith('msg.podSubmitFailed');
        });

        it('should not reload state if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect($state.reload).not.toHaveBeenCalled();
        });

    });

    describe('periodDisplayName', function() {

        beforeEach(function() {
            podSpy.order = {
                processingPeriod: {
                    startDate: [2015, 5, 1],
                    endDate: [2015, 5, 31]
                }
            };
        });

        it('should parse period properly', function() {
            expect(vm.periodDisplayName()).toEqual('2015/5/1 - 2015/5/31');
        });

    });

    describe('typeMessage', function() {

        var order;

        beforeEach(function() {
            podSpy.order = {};
            order = podSpy.order;
        });

        it('should return emergency if pod order is emergency', function() {
            order.emergency = true;

            var result = vm.typeMessage();

            expect(result).toEqual('msg.emergency');
        });

        it('should return regular if pod order is not emergency', function() {
            order.emergency = false;

            var result = vm.typeMessage();

            expect(result).toEqual('msg.regular');
        });

    });

});
<commit_msg>OLMIS-1550: Added test to PodViewController<commit_after>describe('PodViewController', function() {

    var vm, $rootScope, $state, $q, podSpy, notificationServiceMock, confirmServiceMock, confirmPromise;

    beforeEach(function() {
        notificationServiceMock = jasmine.createSpyObj('notificationService', ['success', 'error']);
        confirmServiceMock = jasmine.createSpyObj('confirmService', ['confirm']);
        podServiceMock = jasmine.createSpyObj('podService', ['save', 'submit']);
        podSpy = jasmine.createSpyObj('pod', ['isValid', 'isLineItemValid']);
        podSpy.proofOfDeliveryLineItems = [
            {
                id: '1',
                $program: {
                    productCategoryDisplayName: 'firstCategory'
                }
            },
            {
                id: '2',
                $program: {
                    productCategoryDisplayName: 'secondCategory'
                }
            },
            {
                id: '3',
                $program: {
                    productCategoryDisplayName: 'secondCategory'
                }
            }
        ];

        module('proof-of-delivery-view', function($provide) {
            $provide.service('notificationService', function() {
                return notificationServiceMock;
            });

            $provide.service('confirmService', function() {
                return confirmServiceMock;
            });

            $provide.service('podService', function() {
                return podServiceMock;
            });
        });

        inject(function(_$rootScope_, _$state_, _$q_, $controller) {
            $rootScope = _$rootScope_;
            $state = _$state_;
            $q = _$q_;

            vm = $controller('PodViewController', {
                pod: podSpy
            });
        });

        spyOn($state, 'reload').andReturn();

        confirmPromise = $q.when();
        confirmServiceMock.confirm.andReturn(confirmPromise);
    });

    it('initialization should expose pod', function() {
        expect(vm.pod).toEqual(podSpy);
    });

    it('initalization should expose product categories with attached programs', function() {
        var result = {
            firstCategory: [
                podSpy.proofOfDeliveryLineItems[0]
            ],
            secondCategory: [
                podSpy.proofOfDeliveryLineItems[1],
                podSpy.proofOfDeliveryLineItems[2]
            ]
        };
        expect(vm.categories).toEqual(result);
    });

    describe('savePod', function() {

        var deferred;

        beforeEach(function() {
            deferred = $q.defer();
            podServiceMock.save.andReturn(deferred.promise);

            vm.savePod();
            $rootScope.$apply();
        });

        it('should show confirmation modal', function() {
            expect(confirmServiceMock.confirm).toHaveBeenCalledWith('msg.orders.savePodQuestion');
        });

        it('should save pod', function() {
            expect(podServiceMock.save).toHaveBeenCalledWith(podSpy);
        });

        it('should show success notification if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect(notificationServiceMock.success).toHaveBeenCalledWith('msg.podSaved');
        });

        it('should reload state if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect($state.reload).toHaveBeenCalled();
        });

        it('should show error notification if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect(notificationServiceMock.error).toHaveBeenCalledWith('msg.podSavedFailed');
        });

        it('should not reload state if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect($state.reload).not.toHaveBeenCalled();
        });

    });

    describe('submitPod', function() {

        var deferred;

        beforeEach(function() {
            deferred = $q.defer();
            podServiceMock.submit.andReturn(deferred.promise);

            vm.submitPod();
            $rootScope.$apply();
        });

        it('should show confirmation modal', function() {
            expect(confirmServiceMock.confirm).toHaveBeenCalledWith('msg.orders.submitPodQuestion');
        });

        it('should submit pod', function() {
            expect(podServiceMock.submit).toHaveBeenCalledWith(podSpy);
        });

        it('should show success notification if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect(notificationServiceMock.success).toHaveBeenCalledWith('msg.podSubmit');
        });

        it('should reload state if save was successful', function() {
            deferred.resolve();
            $rootScope.$apply();

            expect($state.reload).toHaveBeenCalled();
        });

        it('should show error notification if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect(notificationServiceMock.error).toHaveBeenCalledWith('msg.podSubmitFailed');
        });

        it('should not reload state if save failed', function() {
            deferred.reject();
            $rootScope.$apply();

            expect($state.reload).not.toHaveBeenCalled();
        });

    });

    describe('periodDisplayName', function() {

        beforeEach(function() {
            podSpy.order = {
                processingPeriod: {
                    startDate: [2015, 5, 1],
                    endDate: [2015, 5, 31]
                }
            };
        });

        it('should parse period properly', function() {
            expect(vm.periodDisplayName()).toEqual('2015/5/1 - 2015/5/31');
        });

    });

    describe('typeMessage', function() {

        var order;

        beforeEach(function() {
            podSpy.order = {};
            order = podSpy.order;
        });

        it('should return emergency if pod order is emergency', function() {
            order.emergency = true;

            var result = vm.typeMessage();

            expect(result).toEqual('msg.emergency');
        });

        it('should return regular if pod order is not emergency', function() {
            order.emergency = false;

            var result = vm.typeMessage();

            expect(result).toEqual('msg.regular');
        });

    });

});
<|endoftext|>