<commit_before>/* @flow */
import React from 'react';
import { shallow } from 'enzyme';
import Table from '../Table';
import examples from '../../../website/app/demos/Table/examples';
import testDemoExamples from '../../../../utils/testDemoExamples';

function shallowTable(props = {}) {
  const tableProps = {
    data: [{ a: 'a1', b: 'b1' }, { a: 'a2', b: 'b2' }],
    title: 'test',
    ...props
  };

  return shallow(<Table {...tableProps} />);
}

describe('Table', () => {
  testDemoExamples(examples, {
    exclude: ['large-data-sets'],
    contextPolyfill: true
  });

  it('renders', () => {
    const table = shallowTable();

    expect(table.exists()).toEqual(true);
  });
});
<commit_msg>test(table): Add test coverage for column sorting and row selection<commit_after>/* @flow */
import React, { Component } from 'react';
import { mount, shallow } from 'enzyme';
import { mountInThemeProvider } from '../../../../utils/enzymeUtils';
import { ThemeProvider } from '../../themes';
import Checkbox from '../../Checkbox';
import Table from '../Table';
import TableBase from '../TableBase';
import TableBody from '../TableBody';
import TableHeader from '../TableHeader';
import TableRow from '../TableRow';
import TableSortableHeaderCell from '../TableSortableHeaderCell';
import examples from '../../../website/app/demos/Table/examples';
import testDemoExamples from '../../../../utils/testDemoExamples';

const defaultProps = {
  data: [
    { aa: 'aa0', ab: 'ab0', ac: 'ac0', ad: 'ad0' },
    { aa: 'aa2', ab: 'ab2', ac: 'ac2', ad: 'ad2' },
    { aa: 'aa1', ab: 'ab1', ac: 'ac1', ad: 'ad1' },
    { aa: 'aa3', ab: 'ab3', ac: 'ac3', ad: 'ad3', disabled: true }
  ],
  title: 'Test'
};
// $FlowFixMe
const nonDisabledRows = defaultProps.data.filter((item) => !item.disabled);

function shallowTable(props = {}) {
  const tableProps = {
    ...defaultProps,
    ...props
  };
  return shallow(<Table {...tableProps} />);
}

const mountTable = (props = {}) => {
  const tableProps = {
    ...defaultProps,
    ...props
  };

  return mountInThemeProvider(<Table {...tableProps} />);
};

/* NOTE: The mountApp() function and App component are provided for such cases
when one needs to call Enzyme functions, such as update(), setProps(),
setState(), etc. on the ReactWrapper but those are not available on the
ReactWrapper returned from mountTable() as it is not the root wrapper. */

const mountApp = (props = {}) => {
  const appProps = {
    ...defaultProps,
    ...props
  };

  return mount(<App {...appProps} />);
};

class App extends Component<*, *> {
  state = {
    data: this.props.data
  };

  render() {
    const tableProps = {
      ...this.props,
      data: this.state.data
    };

    return (
      <ThemeProvider>
        <Table {...tableProps} />
      </ThemeProvider>
    );
  }
}

const findHeaderCheckbox = (table) => {
  return table.find(TableHeader).find('input[type="checkbox"]');
};

const findCheckboxAtRowIndex = (table, index) => {
  return table
    .find(TableBody)
    .find(TableRow)
    .at(index)
    .find('input[type="checkbox"]');
};

const findCheckedCheckboxes = (table) => {
  return table
    .find(TableBody)
    .findWhere((n) => n.type() === Checkbox && n.props().checked);
};

// Needed to run jest:react for snapshot testing in old versions of React
const REGEX_REACT_TEXT = /<!-- react-text: \d+ -->(.*)<!-- \/react-text -->/g;
const stripReactTextTags = (string: string) => {
  return string.replace(REGEX_REACT_TEXT, '$1');
};

describe('Table', () => {
  testDemoExamples(examples, {
    exclude: ['large-data-sets'],
    contextPolyfill: true
  });

  it('renders', () => {
    const table = shallowTable();

    expect(table.exists()).toEqual(true);
  });

  describe('selectable', () => {
    describe('defaultSelectedRows', () => {
      it('does not select without selectable', () => {
        const [, table] = mountTable({
          defaultSelectedRows: [defaultProps.data[0]]
        });
        const selectedRows = table.find(TableBase).props().selectable;

        expect(selectedRows).toBeUndefined();
      });

      it('selects default rows', () => {
        const [, table] = mountTable({
          defaultSelectedRows: [defaultProps.data[0]],
          selectable: true
        });

        const firstRowCheckbox = findCheckboxAtRowIndex(table, 0);
        const headerCheckbox = findHeaderCheckbox(table);

        expect(headerCheckbox.props().indeterminate).toBeTrue;
        expect(firstRowCheckbox.props().checked).toBeTrue;
      });

      it('does not select disabled rows', () => {
        const disabledRow = defaultProps.data[3];
        const [, table] = mountTable({
          defaultSelectedRows: [disabledRow],
          selectable: true
        });

        const disabledRowCheckbox = findCheckboxAtRowIndex(table, 3);
        const headerCheckbox = findHeaderCheckbox(table);

        expect(
          headerCheckbox.props().checked && headerCheckbox.props().indeterminate
        ).toBeFalse;
        expect(disabledRowCheckbox.props().checked).toBeFalse;
      });
    });

    describe('on click', () => {
      describe('single row', () => {
        it('selects row', () => {
          const app = mountApp({
            selectable: true
          });
          let table = app.find(Table);
          let firstRowCheckbox = findCheckboxAtRowIndex(table, 0);

          firstRowCheckbox.simulate('change');
          app.update();

          table = app.find(Table);
          const headerCheckbox = findHeaderCheckbox(table);
          firstRowCheckbox = findCheckboxAtRowIndex(table, 0);

          expect(headerCheckbox.props().indeterminate).toBeTrue;
          expect(firstRowCheckbox.props().checked).toBeTrue;
        });

        it('deselects row when initially selected', () => {
          const app = mountApp({
            defaultSelectedRows: [defaultProps.data[0]],
            selectable: true
          });
          let table = app.find(Table);
          let firstRowCheckbox = findCheckboxAtRowIndex(table, 0);

          firstRowCheckbox.simulate('change');
          app.update();

          table = app.find(Table);
          let headerCheckbox = findHeaderCheckbox(table);
          firstRowCheckbox = findCheckboxAtRowIndex(table, 0);

          expect(
            headerCheckbox.props().checked &&
              headerCheckbox.props().indeterminate
          ).toBeFalse;
          expect(firstRowCheckbox.props().checked).toBeFalse;
        });

        it('calls onToggleRow callback when provided', () => {
          const onToggleRow = jest.fn();
          const [, table] = mountTable({
            onToggleRow,
            selectable: true
          });
          const firstRowCheckbox = findCheckboxAtRowIndex(table, 0);

          firstRowCheckbox.simulate('change');

          expect(onToggleRow).toHaveBeenCalledWith(defaultProps.data[0], true);
        });
      });

      describe('all rows', () => {
        it('selects all non-disabled rows when no rows initially selected', () => {
          const app = mountApp({
            selectable: true
          });
          let table = app.find(Table);
          const headerCheckbox = findHeaderCheckbox(table);

          headerCheckbox.simulate('change');
          app.update();

          table = app.find(Table);
          const checkedCheckboxes = findCheckedCheckboxes(table);

          expect(headerCheckbox.props().checked).toBeTrue;
          expect(checkedCheckboxes.length).toEqual(nonDisabledRows.length);
        });

        it('deselects all rows when some rows initially selected', () => {
          const app = mountApp({
            defaultSelectedRows: [defaultProps.data[0]],
            selectable: true
          });
          let table = app.find(Table);
          const headerCheckbox = findHeaderCheckbox(table);

          headerCheckbox.simulate('change');
          app.update();

          table = app.find(Table);
          const checkedCheckboxes = findCheckedCheckboxes(table);

          expect(
            headerCheckbox.props().checked &&
              headerCheckbox.props().indeterminate
          ).toBeFalse;
          expect(checkedCheckboxes.length).toEqual(0);
        });

        it('deselects all rows when all rows initially selected', () => {
          const app = mountApp({
            defaultSelectedRows: defaultProps.data,
            selectable: true
          });
          let table = app.find(Table);
          const headerCheckbox = findHeaderCheckbox(table);

          headerCheckbox.simulate('change');
          app.update();

          table = app.find(Table);
          const checkedCheckboxes = findCheckedCheckboxes(table);

          expect(
            headerCheckbox.props().checked &&
              headerCheckbox.props().indeterminate
          ).toBeFalse;
          expect(checkedCheckboxes.length).toEqual(0);
        });

        it('calls onToggleAllRows callback when provided', () => {
          const onToggleAllRows = jest.fn();
          const [, table] = mountTable({
            onToggleAllRows,
            selectable: true
          });
          const headerCheckbox = findHeaderCheckbox(table);

          headerCheckbox.simulate('change');

          expect(onToggleAllRows).toHaveBeenCalledWith(nonDisabledRows, true);
        });
      });
    });
  });

  describe('sortable', () => {
    describe('enablement', () => {
      it('makes all columns sortable with sortable on Table', () => {
        const [, table] = mountTable({
          sortable: true
        });
        const header = table.find(TableHeader);

        expect(header.find(TableSortableHeaderCell).length).toEqual(4);
      });

      it('makes only the first column sortable with sortable in column definition', () => {
        const [, table] = mountTable({
          columns: [
            { key: 'aa', content: 'AA', sortable: true },
            { key: 'ab', content: 'AB' },
            { key: 'ac', content: 'AC' },
            { key: 'ad', content: 'AD' }
          ]
        });
        const header = table.find(TableHeader);

        expect(header.find(TableSortableHeaderCell).length).toEqual(1);
      });

      it('makes only the appropriate columns sortable with sortable in Table and column definition', () => {
        const [, table] = mountTable({
          columns: [
            { key: 'aa', content: 'AA', sortable: false },
            { key: 'ab', content: 'AB' },
            { key: 'ac', content: 'AC' },
            { key: 'ad', content: 'AD' }
          ],
          sortable: true
        });
        const header = table.find(TableHeader);

        expect(header.find(TableSortableHeaderCell).length).toEqual(3);
      });
    });

    describe('defaultSort', () => {
      it('sorts without sortable', () => {
        const [, table] = mountTable({
          defaultSort: { key: 'aa', descending: true }
        });
        const sortedData = table.find(TableBase).props().data;

        expect(sortedData).toMatchSnapshot();
      });

      it('sorts with sortable Table', () => {
        const [, table] = mountTable({
          defaultSort: { key: 'aa', descending: true },
          sortable: true
        });
        const sortedData = table.find(TableBase).props().data;

        expect(sortedData).toMatchSnapshot();
      });

      it('sorts with sortable column', () => {
        const [, table] = mountTable({
          columns: [
            { key: 'aa', content: 'AA', sortable: true },
            { key: 'ab', content: 'AB' },
            { key: 'ac', content: 'AC' },
            { key: 'ad', content: 'AD' }
          ],
          defaultSort: { key: 'aa', descending: true }
        });
        const sortedData = table.find(TableBase).props().data;

        expect(sortedData).toMatchSnapshot();
      });

      it('sorts with sortable Table and sortComparator', () => {
        const [, table] = mountTable({
          defaultSort: { key: 'aa', descending: true },
          sortable: true,
          sortComparator: () => 0
        });
        const sortedData = table.find(TableBase).props().data;

        expect(sortedData).toMatchSnapshot();
      });

      it('sorts with sortable column and sortComparator', () => {
        const tableSortComparator = jest.fn();

        const [, table] = mountTable({
          columns: [
            {
              key: 'aa',
              content: 'AA',
              sortable: true,
              sortComparator: () => 0
            },
            { key: 'ab', content: 'AB' },
            { key: 'ac', content: 'AC' },
            { key: 'ad', content: 'AD' }
          ],
          defaultSort: { key: 'aa', descending: true },
          sortComparator: tableSortComparator
        });
        const sortedData = table.find(TableBase).props().data;

        expect(sortedData).toMatchSnapshot();
        expect(tableSortComparator).not.toHaveBeenCalled();
      });
    });

    describe('on click', () => {
      let app, table;
      const onSort = jest.fn();

      beforeEach(() => {
        app = mountApp({
          onSort,
          sortable: true
        });

        table = app.find(Table);
        onSort.mockReset();
      });

      it('sorts ascending on first click', () => {
        let headerCell = table.find(TableSortableHeaderCell).first();
        const button = headerCell.find('button');

        button.simulate('click');

        app.update();
        table = app.find(Table);
        const sortedData = table.find(TableBase).props().data;
        const headerCellHtml = stripReactTextTags(headerCell.html());

        expect(sortedData).toMatchSnapshot();
        expect(headerCellHtml).toMatchSnapshot();
      });

      it('toggles sort direction on second click', () => {
        const headerCell = table.find(TableSortableHeaderCell).first();
        const button = headerCell.find('button');

        button.simulate('click');
        button.simulate('click');

        app.update();
        table = app.find(Table);
        const sortedData = table.find(TableBase).props().data;
        const headerCellHtml = stripReactTextTags(headerCell.html());

        expect(sortedData).toMatchSnapshot();
        expect(headerCellHtml).toMatchSnapshot();
      });

      it('sorts ascending when sorted column changes', () => {
        const headerCell = table.find(TableSortableHeaderCell).first();
        const secondHeaderCell = table.find(TableSortableHeaderCell).at(1);
        const button = headerCell.find('button');
        const secondButton = secondHeaderCell.find('button');

        button.simulate('click');
        secondButton.simulate('click');

        app.update();
        table = app.find(Table);
        const sortedData = table.find(TableBase).props().data;
        const headerCellHtml = stripReactTextTags(headerCell.html());
        const secondHeaderCellHtml = stripReactTextTags(
          secondHeaderCell.html()
        );

        expect(sortedData).toMatchSnapshot();
        expect(headerCellHtml).toMatchSnapshot('Idle');
        expect(secondHeaderCellHtml).toMatchSnapshot('Active');
      });

      it('calls onSort callback when provided', () => {
        const button = table
          .find(TableSortableHeaderCell)
          .first()
          .find('button');

        button.simulate('click');

        expect(onSort).toHaveBeenCalledWith({ key: 'aa', descending: false });
      });
    });

    it('maintains sort state when data changes', () => {
      const props = {
        columns: [
          { content: 'AA', key: 'aa' },
          { content: 'AB', key: 'ab' },
          { content: 'AC', key: 'ac' },
          { content: 'AD', key: 'ad' }
        ],
        data: [
          { aa: 'aa0', ab: 'ab0', ac: 'ac0', ad: 'ad0' },
          { aa: 'aa1', ab: 'ab1', ac: 'ac1', ad: 'ad1' },
          { aa: 'aa2', ab: 'ab2', ac: 'ac2', ad: 'ad2' },
          { aa: 'aa3', ab: 'ab3', ac: 'ac3', ad: 'ad3' }
        ],
        defaultSort: { key: 'aa', descending: true },
        sortable: true
      };

      const app = mountApp(props);

      app.setState({
        data: [...props.data, { aa: 'aa4', ab: 'ab4', ac: 'ac4', ad: 'ad4' }]
      });

      const sortedData = app.find(TableBase).props().data;

      expect(sortedData).toMatchSnapshot();
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 The Lovefield Project Authors. All Rights Reserved.
 *
 * 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.
 */
goog.setTestOnly();
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent.product');
goog.require('hr.bdb');
goog.require('hr.db');
goog.require('lf.Global');
goog.require('lf.schema.DataStoreType');
goog.require('lf.service.ServiceId');
goog.require('lf.testing.Capability');
goog.require('lf.testing.EndToEndTester');
goog.require('lf.testing.hrSchema.getSchemaBuilder');

/** @type {!goog.testing.AsyncTestCase} */
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'EndToEndTest');

/** @type {number} */
asyncTestCase.stepTimeout = 10 * 1000;  // 10 seconds

/** @type {!lf.testing.Capability} */
var capability;

/** @type {!goog.testing.PropertyReplacer} */
var stub;

function setUpPage() {
  capability = lf.testing.Capability.get();
  stub = new goog.testing.PropertyReplacer();
}

function tearDown() {
  stub.reset();
}

function testEndToEnd_StaticSchema() {
  asyncTestCase.waitForAsync('testEndToEnd_StaticSchema');
  var tester = new lf.testing.EndToEndTester(
      hr.db.getGlobal.bind(hr.db),
      hr.db.connect.bind(hr.db, {
        storeType: lf.schema.DataStoreType.MEMORY
      }));
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}

function testEndToEnd_StaticSchemaBundled() {
  if (!capability.indexedDb || goog.userAgent.product.IE) {
    // Due to sheer amount of data in this test, IE will prompt for permission,
    // which blocks test bot execution. As a result, it is skipped from this
    // test for now.
    return;
  }

  asyncTestCase.waitForAsync('testEndToEnd_StaticSchemaBundled');
  var dbGlobal;

  var globalFn = function() {
    return dbGlobal;
  };
  var connectFn = function() {
    stub.reset();
    var dbName = 'hrbdb' + goog.now();
    dbGlobal = new lf.Global();
    stub.replace(
        goog.getObjectByName('hr.bdb.schema.Database.prototype'),
        'name',
        function() { return dbName; });
    stub.replace(
        goog.getObjectByName('hr.bdb'),
        'getGlobal',
        function() {
          var serviceId = new lf.service.ServiceId(dbName);
          var global = lf.Global.get();
          if (!global.isRegistered(serviceId)) {
            global.registerService(serviceId, dbGlobal);
          }
          return dbGlobal;
        });
    return hr.bdb.connect();
  };

  var tester = new lf.testing.EndToEndTester(globalFn, connectFn);
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}

function testEndToEnd_DynamicSchema() {
  asyncTestCase.waitForAsync('testEndToEnd_DynamicSchema');
  var builder = lf.testing.hrSchema.getSchemaBuilder();
  var tester = new lf.testing.EndToEndTester(
      builder.getGlobal.bind(builder),
      builder.connect.bind(builder, {
        storeType: lf.schema.DataStoreType.MEMORY
      }));
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}

function testEndToEnd_DynamicSchemaBundled() {
  if (!capability.indexedDb || goog.userAgent.product.IE) {
    return;
  }

  asyncTestCase.waitForAsync('testEndToEnd_DynamicSchemaBundled');
  /** @type {!lf.schema.Builder} */
  var builder;
  var globalFn = function() {
    return builder.getGlobal();
  };
  var connectFn = function() {
    builder = lf.testing.hrSchema.getSchemaBuilder();
    builder.setPragma(/** @type {!lf.schema.Database.Pragma} */ (
        {enableBundledMode: true}));
    return builder.connect();
  };

  var tester = new lf.testing.EndToEndTester(globalFn, connectFn);
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}
<commit_msg>Lengthen end to end test timeout in hope of reducing flakiness. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=103244879<commit_after>/**
 * @license
 * Copyright 2014 The Lovefield Project Authors. All Rights Reserved.
 *
 * 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.
 */
goog.setTestOnly();
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent.product');
goog.require('hr.bdb');
goog.require('hr.db');
goog.require('lf.Global');
goog.require('lf.schema.DataStoreType');
goog.require('lf.service.ServiceId');
goog.require('lf.testing.Capability');
goog.require('lf.testing.EndToEndTester');
goog.require('lf.testing.hrSchema.getSchemaBuilder');

/** @type {!goog.testing.AsyncTestCase} */
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'EndToEndTest');

/** @type {number} */
asyncTestCase.stepTimeout = 30 * 1000;  // 30 seconds

/** @type {!lf.testing.Capability} */
var capability;

/** @type {!goog.testing.PropertyReplacer} */
var stub;

function setUpPage() {
  capability = lf.testing.Capability.get();
  stub = new goog.testing.PropertyReplacer();
}

function tearDown() {
  stub.reset();
}

function testEndToEnd_StaticSchema() {
  asyncTestCase.waitForAsync('testEndToEnd_StaticSchema');
  var tester = new lf.testing.EndToEndTester(
      hr.db.getGlobal.bind(hr.db),
      hr.db.connect.bind(hr.db, {
        storeType: lf.schema.DataStoreType.MEMORY
      }));
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}

function testEndToEnd_StaticSchemaBundled() {
  if (!capability.indexedDb || goog.userAgent.product.IE) {
    // Due to sheer amount of data in this test, IE will prompt for permission,
    // which blocks test bot execution. As a result, it is skipped from this
    // test for now.
    return;
  }

  asyncTestCase.waitForAsync('testEndToEnd_StaticSchemaBundled');
  var dbGlobal;

  var globalFn = function() {
    return dbGlobal;
  };
  var connectFn = function() {
    stub.reset();
    var dbName = 'hrbdb' + goog.now();
    dbGlobal = new lf.Global();
    stub.replace(
        goog.getObjectByName('hr.bdb.schema.Database.prototype'),
        'name',
        function() { return dbName; });
    stub.replace(
        goog.getObjectByName('hr.bdb'),
        'getGlobal',
        function() {
          var serviceId = new lf.service.ServiceId(dbName);
          var global = lf.Global.get();
          if (!global.isRegistered(serviceId)) {
            global.registerService(serviceId, dbGlobal);
          }
          return dbGlobal;
        });
    return hr.bdb.connect();
  };

  var tester = new lf.testing.EndToEndTester(globalFn, connectFn);
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}

function testEndToEnd_DynamicSchema() {
  asyncTestCase.waitForAsync('testEndToEnd_DynamicSchema');
  var builder = lf.testing.hrSchema.getSchemaBuilder();
  var tester = new lf.testing.EndToEndTester(
      builder.getGlobal.bind(builder),
      builder.connect.bind(builder, {
        storeType: lf.schema.DataStoreType.MEMORY
      }));
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}

function testEndToEnd_DynamicSchemaBundled() {
  if (!capability.indexedDb || goog.userAgent.product.IE) {
    return;
  }

  asyncTestCase.waitForAsync('testEndToEnd_DynamicSchemaBundled');
  /** @type {!lf.schema.Builder} */
  var builder;
  var globalFn = function() {
    return builder.getGlobal();
  };
  var connectFn = function() {
    builder = lf.testing.hrSchema.getSchemaBuilder();
    builder.setPragma(/** @type {!lf.schema.Database.Pragma} */ (
        {enableBundledMode: true}));
    return builder.connect();
  };

  var tester = new lf.testing.EndToEndTester(globalFn, connectFn);
  tester.run().then(function() {
    asyncTestCase.continueTesting();
  });
}
<|endoftext|>


<commit_before>describe("JanusWeb Render textures", function() {
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
  var client, janusweb, canvas;
  var resolution = '800x600';

  beforeEach(function(done) {
    done();
  });

  it("should initialize client", function(done) {
    try {
      elation.janusweb.init({
        resolution: resolution,
        autoload: false,
        showchat: false,
        networking: false
      }).then(function(newclient) {
        client = newclient;
        janusweb = client.janusweb;
        expect(client).toBeDefined();
        expect(janusweb).toBeDefined();
        done();
      });
    } catch (e) {
      console.log('exception happened!', e.stack);
    }
  });
  it("added canvas to document", function(done) {
    var canvases = document.getElementsByTagName('canvas');
    expect(canvases.length).toEqual(1);
    canvas = canvases[0];
    done();
  });
  it("defines testing assets", function(done) {
    setTimeout(function() {
      elation.engine.assets.loadJSON([
        { assettype: 'image', name: 'solid_red_jpg', src: '../tests/images/solid-red.jpg' },
        { assettype: 'image', name: 'solid_red_png', src: '../tests/images/solid-red.png' },
        { assettype: 'image', name: 'solid_blue_jpg', src: '../tests/images/solid-blue.jpg' },
        { assettype: 'image', name: 'solid_blue_png', src: '../tests/images/solid-blue.png' },
        { assettype: 'image', name: 'solid_green_jpg', src: '../tests/images/solid-green.jpg' },
        { assettype: 'image', name: 'solid_green_png', src: '../tests/images/solid-green.png' },

        { assettype: 'image', name: 'transparent_red_50_png', src: '../tests/images/transparent-red-50.png' },
        { assettype: 'image', name: 'transparent_red_50_gif', src: '../tests/images/transparent-red-50.gif' },
        { assettype: 'image', name: 'transparent_blue_50_png', src: '../tests/images/transparent-blue-50.png' },
        { assettype: 'image', name: 'transparent_blue_50_gif', src: '../tests/images/transparent-blue-50.gif' },
        { assettype: 'image', name: 'transparent_green_50_png', src: '../tests/images/transparent-green-50.png' },
        { assettype: 'image', name: 'transparent_green_50_gif', src: '../tests/images/transparent-green-50.gif' },
      ], elation.config.get('janusweb.datapath') + 'assets/');
      done();
    }, 1000);
  });

  it("loads a solid red texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Image id="solid_red_png" pos="0 1 2" scale="5 5 5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(255);
        expect(color[1]).toBe(0);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a solid green texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Image id="solid_green_png" pos="0 1 2" scale="5 5 5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(0);
        expect(color[1]).toBe(255);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a solid blue texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Image id="solid_blue_png" pos="0 1 2" scale="5 5 5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(0);
        expect(color[1]).toBe(0);
        expect(color[2]).toBe(255);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a transparent red texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Object id="plane" image_id="transparent_red_50_png" pos="0 1 2" scale="5 5 .5" lighting="false" zdir="0 0 -1"/></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(127);
        expect(color[1]).toBe(0);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a transparent red texture over a solid green texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Object id="plane" image_id="transparent_red_50_png" pos="0 1 2" scale="5 5 .5" lighting="false" zdir="0 0 -1"/><Object id="cube" image_id="solid_green_png" pos="0 1 3" scale="10 10 .5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
setTimeout(function() {
      client.view.getPixelAt(0,0).then(function(color) {
console.log('got a color', color);
        expect(color[0]).toBe(127);
        expect(color[1]).toBe(128);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
}, 10000);
    });
  });

  it("should stop when done", function(done) {
    elation.events.add(client.engine, 'engine_stop', function() {
      expect(client.engine.running).toBe(false);
      done();
    });
    client.engine.stop();
  });
});

<commit_msg>Removed 10s timeout<commit_after>describe("JanusWeb Render textures", function() {
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
  var client, janusweb, canvas;
  var resolution = '800x600';

  beforeEach(function(done) {
    done();
  });

  it("should initialize client", function(done) {
    try {
      elation.janusweb.init({
        resolution: resolution,
        autoload: false,
        showchat: false,
        networking: false
      }).then(function(newclient) {
        client = newclient;
        janusweb = client.janusweb;
        expect(client).toBeDefined();
        expect(janusweb).toBeDefined();
        done();
      });
    } catch (e) {
      console.log('exception happened!', e.stack);
    }
  });
  it("added canvas to document", function(done) {
    var canvases = document.getElementsByTagName('canvas');
    expect(canvases.length).toEqual(1);
    canvas = canvases[0];
    done();
  });
  it("defines testing assets", function(done) {
    setTimeout(function() {
      elation.engine.assets.loadJSON([
        { assettype: 'image', name: 'solid_red_jpg', src: '../tests/images/solid-red.jpg' },
        { assettype: 'image', name: 'solid_red_png', src: '../tests/images/solid-red.png' },
        { assettype: 'image', name: 'solid_blue_jpg', src: '../tests/images/solid-blue.jpg' },
        { assettype: 'image', name: 'solid_blue_png', src: '../tests/images/solid-blue.png' },
        { assettype: 'image', name: 'solid_green_jpg', src: '../tests/images/solid-green.jpg' },
        { assettype: 'image', name: 'solid_green_png', src: '../tests/images/solid-green.png' },

        { assettype: 'image', name: 'transparent_red_50_png', src: '../tests/images/transparent-red-50.png' },
        { assettype: 'image', name: 'transparent_red_50_gif', src: '../tests/images/transparent-red-50.gif' },
        { assettype: 'image', name: 'transparent_blue_50_png', src: '../tests/images/transparent-blue-50.png' },
        { assettype: 'image', name: 'transparent_blue_50_gif', src: '../tests/images/transparent-blue-50.gif' },
        { assettype: 'image', name: 'transparent_green_50_png', src: '../tests/images/transparent-green-50.png' },
        { assettype: 'image', name: 'transparent_green_50_gif', src: '../tests/images/transparent-green-50.gif' },
      ], elation.config.get('janusweb.datapath') + 'assets/');
      done();
    }, 1000);
  });

  it("loads a solid red texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Image id="solid_red_png" pos="0 1 2" scale="5 5 5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(255);
        expect(color[1]).toBe(0);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a solid green texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Image id="solid_green_png" pos="0 1 2" scale="5 5 5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(0);
        expect(color[1]).toBe(255);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a solid blue texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Image id="solid_blue_png" pos="0 1 2" scale="5 5 5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(0);
        expect(color[1]).toBe(0);
        expect(color[2]).toBe(255);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a transparent red texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Object id="plane" image_id="transparent_red_50_png" pos="0 1 2" scale="5 5 .5" lighting="false" zdir="0 0 -1"/></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
        expect(color[0]).toBe(127);
        expect(color[1]).toBe(0);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });
  it("loads a transparent red texture over a solid green texture", function(done) {
    var roomsrc = '<FireBoxRoom><Assets></Assets><Room skybox_left_id="black" skybox_right_id="black" skybox_top_id="black" skybox_bottom_id="black" skybox_front_id="black" skybox_back_id="black"><Object id="plane" image_id="transparent_red_50_png" pos="0 1 2" scale="5 5 .5" lighting="false" zdir="0 0 -1"/><Object id="cube" image_id="solid_green_png" pos="0 1 3" scale="10 10 .5" lighting="false" /></Room></FireBoxRoom>';

    var testroom = janusweb.loadFromSource(roomsrc, true);
    elation.events.add(testroom, 'room_load_complete', function() {
      client.view.getPixelAt(0,0).then(function(color) {
console.log('got a color', color);
        expect(color[0]).toBe(127);
        expect(color[1]).toBe(128);
        expect(color[2]).toBe(0);
        expect(color[3]).toBe(255);
        done();
      });
    });
  });

  it("should stop when done", function(done) {
    elation.events.add(client.engine, 'engine_stop', function() {
      expect(client.engine.running).toBe(false);
      done();
    });
    client.engine.stop();
  });
});

<|endoftext|>


<commit_before>module.exports = function (config) {
    config.set({
        frameworks: ['jasmine'],

        basePath: '../',

        files: [
            'app/vendor/angular/angular.js',
            'app/vendor/angular/angular-*.js',
            'app/vendor/*.js',
            'app/js/**/*.js',
            'app/js/controllers/**/*.js',
            'app/plugins/**/*.js',
            'test/vendor/angular/angular-mocks.js',
            'test/vendor/jquery-2.0.3.js',
            'test/vendor/jasmine-jquery.js',
            'test/unit/**/*.js',

            // fixtures
            {pattern: 'test/mock/*.json', watched: true, served: true, included: false}
        ],

        autoWatch: false,
        singleRun: true,

        browsers: ['Firefox'],

        junitReporter: {
          outputFile: 'test_out/unit.xml',
          suite: 'unit'
        },

        reporters: ['progress', 'coverage'],
        preprocessors: {
            'app/js/**/*.js': ['coverage']
        }
    });
};
<commit_msg>fix karma config jquery order<commit_after>module.exports = function (config) {
    config.set({
        frameworks: ['jasmine'],

        basePath: '../',

        files: [
            'app/vendor/angular/angular.js',
            'app/vendor/angular/angular-*.js',
            'app/vendor/jquery-2.0.3.js',
            'app/vendor/*.js',
            'app/js/**/*.js',
            'app/js/controllers/**/*.js',
            'app/plugins/**/*.js',
            'test/vendor/angular/angular-mocks.js',
            'test/vendor/jasmine-jquery.js',
            'test/unit/**/*.js',

            // fixtures
            {pattern: 'test/mock/*.json', watched: true, served: true, included: false}
        ],

        autoWatch: false,
        singleRun: true,

        browsers: ['Firefox'],

        junitReporter: {
          outputFile: 'test_out/unit.xml',
          suite: 'unit'
        },

        reporters: ['progress', 'coverage'],
        preprocessors: {
            'app/js/**/*.js': ['coverage']
        }
    });
};
<|endoftext|>


<commit_before>/* global Event */
import { run } from '@ember/runloop';

import { getOwner } from '@ember/application';
import Component from '@ember/component';
import Service from '@ember/service';
import hbs from 'htmlbars-inline-precompile';
import { moduleForComponent, test } from 'ember-qunit';
import ContextBoundEventListenersMixin from 'ember-lifeline/mixins/dom';
import { find, triggerEvent } from 'ember-native-dom-helpers';

moduleForComponent('ember-lifeline/mixins/dom', {
  integration: true,

  beforeEach() {
    let testContext = this;
    let name = 'component:under-test';

    this.owner = getOwner(this);
    this.owner.register(name, Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.componentInstance = this;
      }
    }));

    this.Component = this.owner.factoryFor ? this.owner.factoryFor(name) : this.owner._lookupFactory(name);
  }
});

[{
  testName: 'addEventListener(_,_,_,undefined)',
  testedOptions: undefined
}, {
  testName: 'addEventListener(_,_,_,{passive:false})',
  testedOptions: { passive: false }
}].forEach(({ testName, testedOptions }) => {

  test(`${testName} ensures arrays are not eagerly allocated`, function(assert) {
    assert.expect(1);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    assert.notOk(subject._listeners);
  });

  test(`${testName} adds event listener to child element`, function(assert) {
    assert.expect(4);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    let calls = 0;
    let hadRunloop = null;
    let handledEvent = null;
    subject.addEventListener('.foo', 'click', (event) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    subject.element.firstChild.dispatchEvent(new Event('click'));

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');
  });

  /*
   * app/views/manager/highlighter.js uses a second argument to the drag
   * handler, "delta". It is unclear if this value comes from a jQuery library
   * or where else. Before this test can be removed one should be certain
   * the codebase only contains uses of addEventListener expecting a single
   * event argument.
   *
   */
  test(`${testName} adds jquery event listener to child element with multiple handler args`, async function(assert) {
    assert.expect(4);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    let calls = 0;
    let hadRunloop = null;
    let handledArgs = null;
    subject.addEventListener('.foo', 'drag', (...args) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledArgs = args[0];
    }, testedOptions);

    let delta = {};
    await triggerEvent(subject.element.firstChild, 'drag', { details: { delta } });

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(handledArgs.target, 'callback passed a target');
    assert.equal(handledArgs.details.delta, delta, 'second argument can be present');
  });

  test(`${testName} adds event listener to non-child element`, async function(assert) {
    assert.expect(5);

    this.set('show', true);
    this.render(hbs`{{#if show}}{{under-test}}{{/if}}<span class="foo"></span>`);
    let subject = this.componentInstance;

    let ranCallback = 0;
    let hadRunloop = null;
    let handledEvent = null;
    let element = find('.foo');
    subject.addEventListener(element, 'click', (event) => {
      ranCallback++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    await triggerEvent(element, 'click');

    assert.equal(ranCallback, 1, 'callback was called once');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(!!handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');

    this.set('show', false);

    // Trigger the event on the non-child element again, after the component
    // is removed from DOM. The listener should not fire this time.
    await triggerEvent(element, 'click');

    assert.equal(ranCallback, 1, 'callback was not called a second time');
  });

  test(`${testName} throws when there is no element to attach to`, function(assert) {
    assert.expect(1);

    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Called \w+ with selector not found in DOM: .foo/);
  });

  test(`${testName} throws when attached before rendering`, function(assert) {
    assert.expect(1);

    let subject = this.Component.create();

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Called \w+ with a css selector before the component was rendered/);
  });

  test(`${testName} adds event listener to non-child element in tagless component`, async function(assert) {
    assert.expect(5);

    this.set('show', true);
    this.render(hbs`{{#if show}}{{under-test tagName=""}}{{/if}}<span class="foo"></span>`);
    let subject = this.componentInstance;

    let calls = 0;
    let hadRunloop = null;
    let handledEvent = null;
    subject.addEventListener(find('.foo'), 'click', (event) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(!!handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');

    this.set('show', false);

    // Trigger the event on the non-child element again, after the component
    // is removed from DOM. The listener should not fire this time.
    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback was not called again');
  });

  test(`${testName} throws when using a string selector in a tagless component`, function(assert) {
    assert.expect(1);

    this.render(hbs`{{under-test tagName=""}}<span class="foo"></span>`);
    let subject = this.componentInstance;

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Must provide an element/);
  });

  test(`${testName} listeners on different contexts can be torn down without impacting other contexts`, function(assert) {
    assert.expect(2);

    let testContext = this;
    this.register('component:under-test-a', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectA = this;
      }
    }));
    this.register('component:under-test-b', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectB = this;
      }
    }));

    this.set('showA', true);
    this.render(hbs`{{#if showA}}{{under-test-a}}{{/if}}{{under-test-b}}<span class="foo"></span>`);

    let { subjectA, subjectB } = this;

    let target = find('.foo');

    let calls = 0;
    let callback = () => {
      calls++;
    };
    subjectA.addEventListener(target, 'click', callback, testedOptions);
    subjectB.addEventListener(target, 'click', callback, testedOptions);

    target.click();
    assert.equal(calls, 2, 'two callbacks called');

    this.set('showA', false);

    target.click();
    assert.equal(calls, 3, 'one more callback called for remaining context');
  });

  test(`${testName} listeners are called with correct scope`, function(assert) {
    assert.expect(2);

    let testContext = this;
    this.register('component:under-test-a', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectA = this;
      }
    }));
    this.register('component:under-test-b', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectB = this;
      }
    }));

    this.render(hbs`{{under-test-a}}{{under-test-b}}<span class="foo"></span>`);

    let { subjectA, subjectB } = this;

    let target = find('.foo');

    let assertScope = (scope) => {
      return function() {
        assert.equal(this, scope);
      };
    };
    subjectA.addEventListener(target, 'click', assertScope(subjectA), testedOptions);
    subjectB.addEventListener(target, 'click', assertScope(subjectB), testedOptions);

    target.click();
  });

  test(`${testName.replace('add', 'remove')} removes event listener from child element`, async function(assert) {
    assert.expect(1);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    let calls = 0;
    let listener = () => {
      calls++;
    };
    subject.addEventListener('.foo', 'click', listener, testedOptions);

    subject.removeEventListener('.foo', 'click', listener, testedOptions);

    await triggerEvent(subject.element.firstChild, 'click');

    assert.equal(calls, 0, 'callback was not called');
  });

  test(`${testName} adds event listener when an element is passed in from a service and removes listener when instance is destroyed`, async function(assert) {
    assert.expect(5);

    let serviceName = 'service:under-test';
    let owner = getOwner(this);

    owner.register('service:under-test', Service.extend(ContextBoundEventListenersMixin));

    let factory = owner.factoryFor ? owner.factoryFor(serviceName) : owner._lookupFactory(serviceName);
    let subject = factory.create();

    this.render(hbs`<span class="foo"></span>`);

    let calls = 0;
    let hadRunloop = null;
    let handledEvent = null;
    subject.addEventListener(find('.foo'), 'click', (event) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(!!handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');

    run(() => subject.destroy()); // Listeners should be removed when the service is destroyed

    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback is not called again once the instance is destroyed');
    assert.notOk(subject._listeners);
  });

  test(`${testName} throws when a css selector is passed in from a service instance`, async function(assert) {
    assert.expect(1);

    let serviceName = 'service:under-test';
    let owner = getOwner(this);

    owner.register('service:under-test', Service.extend(ContextBoundEventListenersMixin));

    let factory = owner.factoryFor ? owner.factoryFor(serviceName) : owner._lookupFactory(serviceName);
    let subject = factory.create();

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Must provide an element/);
  });
});

test('addEventListener(_,_,{passive: false}) permits stopPropogation', async function(assert) {
  assert.expect(2);

  this.register('template:components/under-test', hbs`<span class="outer"><span class="inner"></span></span>`);
  this.render(hbs`{{under-test}}`);
  let subject = this.componentInstance;

  let outerCalls = 0;
  subject.addEventListener('.outer', 'click', () => outerCalls++);

  let innerCalls = 0;
  subject.addEventListener('.inner', 'click', (e) => {
    innerCalls++;
    e.stopPropagation();
  }, { passive: false });

  await triggerEvent(subject.element.firstChild.firstChild, 'click', { bubbles: true });

  assert.equal(outerCalls, 0, 'outer callback never fires');
  assert.equal(innerCalls, 1, 'inner callback fires');
});

test('addEventListener(_,_,{once: true}) is only called once', async function(assert) {
  assert.expect(2);

  this.register('template:components/under-test', hbs`<span class="foo"></span>`);
  this.render(hbs`{{under-test}}`);
  let subject = this.componentInstance;

  let calls = 0;
  let listener = () => {
    calls++;
  };
  let element = find('.foo');

  subject.addEventListener('.foo', 'click', listener, { once: true });

  await triggerEvent(element, 'click');
  assert.equal(calls, 1, 'callback was called once');

  await triggerEvent(element, 'click');
  assert.equal(calls, 1, 'callback was called once');
});
<commit_msg>Update dom-test.js<commit_after>/* global Event */
import { run } from '@ember/runloop';

import { getOwner } from '@ember/application';
import Component from '@ember/component';
import Service from '@ember/service';
import hbs from 'htmlbars-inline-precompile';
import { moduleForComponent, test } from 'ember-qunit';
import ContextBoundEventListenersMixin from 'ember-lifeline/mixins/dom';
import { find, triggerEvent } from 'ember-native-dom-helpers';

moduleForComponent('ember-lifeline/mixins/dom', {
  integration: true,

  beforeEach() {
    let testContext = this;
    let name = 'component:under-test';

    this.owner = getOwner(this);
    this.owner.register(name, Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.componentInstance = this;
      }
    }));

    this.Component = this.owner.factoryFor ? this.owner.factoryFor(name) : this.owner._lookupFactory(name);
  }
});

[{
  testName: 'addEventListener(_,_,_,undefined)',
  testedOptions: undefined
}, {
  testName: 'addEventListener(_,_,_,{passive:false})',
  testedOptions: { passive: false }
}].forEach(({ testName, testedOptions }) => {

  test(`${testName} ensures arrays are not eagerly allocated`, function(assert) {
    assert.expect(1);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    assert.notOk(subject._listeners);
  });

  test(`${testName} adds event listener to child element`, function(assert) {
    assert.expect(4);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    let calls = 0;
    let hadRunloop = null;
    let handledEvent = null;
    subject.addEventListener('.foo', 'click', (event) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    subject.element.firstChild.dispatchEvent(new Event('click'));

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');
  });

  /*
   * app/views/manager/highlighter.js uses a second argument to the drag
   * handler, "delta". It is unclear if this value comes from a jQuery library
   * or where else. Before this test can be removed one should be certain
   * the codebase only contains uses of addEventListener expecting a single
   * event argument.
   *
   */
  test(`${testName} adds jquery event listener to child element with multiple handler args`, async function(assert) {
    assert.expect(4);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    let calls = 0;
    let hadRunloop = null;
    let handledArgs = null;
    subject.addEventListener('.foo', 'drag', (...args) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledArgs = args[0];
    }, testedOptions);

    let delta = {};
    await triggerEvent(subject.element.firstChild, 'drag', { details: { delta } });

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(handledArgs.target, 'callback passed a target');
    assert.equal(handledArgs.details.delta, delta, 'second argument can be present');
  });

  test(`${testName} adds event listener to non-child element`, async function(assert) {
    assert.expect(5);

    this.set('show', true);
    this.render(hbs`{{#if show}}{{under-test}}{{/if}}<span class="foo"></span>`);
    let subject = this.componentInstance;

    let ranCallback = 0;
    let hadRunloop = null;
    let handledEvent = null;
    let element = find('.foo');
    subject.addEventListener(element, 'click', (event) => {
      ranCallback++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    await triggerEvent(element, 'click');

    assert.equal(ranCallback, 1, 'callback was called once');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(!!handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');

    this.set('show', false);

    // Trigger the event on the non-child element again, after the component
    // is removed from DOM. The listener should not fire this time.
    await triggerEvent(element, 'click');

    assert.equal(ranCallback, 1, 'callback was not called a second time');
  });

  test(`${testName} throws when there is no element to attach to`, function(assert) {
    assert.expect(1);

    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Called \w+ with selector not found in DOM: .foo/);
  });

  test(`${testName} throws when attached before rendering`, function(assert) {
    assert.expect(1);

    let subject = this.Component.create();

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Called \w+ with a css selector before the component was rendered/);
  });

  test(`${testName} adds event listener to non-child element in tagless component`, async function(assert) {
    assert.expect(5);

    this.set('show', true);
    this.render(hbs`{{#if show}}{{under-test tagName=""}}{{/if}}<span class="foo"></span>`);
    let subject = this.componentInstance;

    let calls = 0;
    let hadRunloop = null;
    let handledEvent = null;
    subject.addEventListener(find('.foo'), 'click', (event) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(!!handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');

    this.set('show', false);

    // Trigger the event on the non-child element again, after the component
    // is removed from DOM. The listener should not fire this time.
    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback was not called again');
  });

  test(`${testName} throws when using a string selector in a tagless component`, function(assert) {
    assert.expect(1);

    this.render(hbs`{{under-test tagName=""}}<span class="foo"></span>`);
    let subject = this.componentInstance;

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Must provide an element/);
  });

  test(`${testName} listeners on different contexts can be torn down without impacting other contexts`, function(assert) {
    assert.expect(2);

    let testContext = this;
    this.register('component:under-test-a', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectA = this;
      }
    }));
    this.register('component:under-test-b', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectB = this;
      }
    }));

    this.set('showA', true);
    this.render(hbs`{{#if showA}}{{under-test-a}}{{/if}}{{under-test-b}}<span class="foo"></span>`);

    let { subjectA, subjectB } = this;

    let target = find('.foo');

    let calls = 0;
    let callback = () => {
      calls++;
    };
    subjectA.addEventListener(target, 'click', callback, testedOptions);
    subjectB.addEventListener(target, 'click', callback, testedOptions);

    target.click();
    assert.equal(calls, 2, 'two callbacks called');

    this.set('showA', false);

    target.click();
    assert.equal(calls, 3, 'one more callback called for remaining context');
  });

  test(`${testName} listeners are called with correct scope`, function(assert) {
    assert.expect(2);

    let testContext = this;
    this.register('component:under-test-a', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectA = this;
      }
    }));
    this.register('component:under-test-b', Component.extend(ContextBoundEventListenersMixin, {
      init() {
        this._super(...arguments);
        testContext.subjectB = this;
      }
    }));

    this.render(hbs`{{under-test-a}}{{under-test-b}}<span class="foo"></span>`);

    let { subjectA, subjectB } = this;

    let target = find('.foo');

    let assertScope = (scope) => {
      return function() {
        assert.equal(this, scope);
      };
    };
    subjectA.addEventListener(target, 'click', assertScope(subjectA), testedOptions);
    subjectB.addEventListener(target, 'click', assertScope(subjectB), testedOptions);

    target.click();
  });

  test(`${testName.replace('add', 'remove')} removes event listener from child element`, async function(assert) {
    assert.expect(1);

    this.register('template:components/under-test', hbs`<span class="foo"></span>`);
    this.render(hbs`{{under-test}}`);
    let subject = this.componentInstance;

    let calls = 0;
    let listener = () => {
      calls++;
    };
    subject.addEventListener('.foo', 'click', listener, testedOptions);

    subject.removeEventListener('.foo', 'click', listener, testedOptions);

    await triggerEvent(subject.element.firstChild, 'click');

    assert.equal(calls, 0, 'callback was not called');
  });

  test(`${testName} adds event listener when an element is passed in from a service and removes listener when instance is destroyed`, async function(assert) {
    assert.expect(6);

    let serviceName = 'service:under-test';
    let owner = getOwner(this);

    owner.register('service:under-test', Service.extend(ContextBoundEventListenersMixin));

    let factory = owner.factoryFor ? owner.factoryFor(serviceName) : owner._lookupFactory(serviceName);
    let subject = factory.create();

    this.render(hbs`<span class="foo"></span>`);

    let calls = 0;
    let hadRunloop = null;
    let handledEvent = null;
    subject.addEventListener(find('.foo'), 'click', (event) => {
      calls++;
      hadRunloop = !!run.currentRunLoop;
      handledEvent = event;
    }, testedOptions);

    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback was called');
    assert.ok(hadRunloop, 'callback was called in runloop');
    assert.ok(!!handledEvent.target, 'callback passed a target');
    assert.equal(handledEvent.target.className, 'foo', 'target has the expected class');

    run(() => subject.destroy()); // Listeners should be removed when the service is destroyed

    await triggerEvent('.foo', 'click');

    assert.equal(calls, 1, 'callback is not called again once the instance is destroyed');
    assert.notOk(subject._listeners);
  });

  test(`${testName} throws when a css selector is passed in from a service instance`, async function(assert) {
    assert.expect(1);

    let serviceName = 'service:under-test';
    let owner = getOwner(this);

    owner.register('service:under-test', Service.extend(ContextBoundEventListenersMixin));

    let factory = owner.factoryFor ? owner.factoryFor(serviceName) : owner._lookupFactory(serviceName);
    let subject = factory.create();

    assert.throws(() => {
      subject.addEventListener('.foo', 'click', () => {}, testedOptions);
    }, /Must provide an element/);
  });
});

test('addEventListener(_,_,{passive: false}) permits stopPropogation', async function(assert) {
  assert.expect(2);

  this.register('template:components/under-test', hbs`<span class="outer"><span class="inner"></span></span>`);
  this.render(hbs`{{under-test}}`);
  let subject = this.componentInstance;

  let outerCalls = 0;
  subject.addEventListener('.outer', 'click', () => outerCalls++);

  let innerCalls = 0;
  subject.addEventListener('.inner', 'click', (e) => {
    innerCalls++;
    e.stopPropagation();
  }, { passive: false });

  await triggerEvent(subject.element.firstChild.firstChild, 'click', { bubbles: true });

  assert.equal(outerCalls, 0, 'outer callback never fires');
  assert.equal(innerCalls, 1, 'inner callback fires');
});

test('addEventListener(_,_,{once: true}) is only called once', async function(assert) {
  assert.expect(2);

  this.register('template:components/under-test', hbs`<span class="foo"></span>`);
  this.render(hbs`{{under-test}}`);
  let subject = this.componentInstance;

  let calls = 0;
  let listener = () => {
    calls++;
  };
  let element = find('.foo');

  subject.addEventListener('.foo', 'click', listener, { once: true });

  await triggerEvent(element, 'click');
  assert.equal(calls, 1, 'callback was called once');

  await triggerEvent(element, 'click');
  assert.equal(calls, 1, 'callback was called once');
});
<|endoftext|>


<commit_before>/**
 *  nacl
 *  copyright(c) 2016 - 2019 Andela Kenya Ltd
 *  MIT Lincensed
 */

(function() {
  'use strict';
  require('colors');
  require('./includes');
  var helper = require('./helpers');
  var log = require('npmlog');
  var unless = require('express-unless');

  var opt = {
    denied: {
      status: 403,
      success: false,
      error: 'ACCESS DENIED'
    }
  };

  /**
   * [config Loads the rules from our config file]
   * @param  {[options]} options [defines where the
   * config file is located, and the encoding type]
   *
   */

  var config = function(options) {
    var path, rules, encoding;
    var yml = false;

    /**
     * Get the filename
     */

    var filename = yml ? 'config.yml' : 'config.json';

    filename = options && options.filename ? options.filename : filename;

    /**
     * Get the path
     */

    path = options && options.path ? options.path : path;

    /**
     * Merge filename and path
     */

    path = filename && path ? (path + '/' + filename) : filename;

    if (options && options.baseUrl) {
      yml = options.yml;
      encoding = options.encoding;
      opt.baseUrl = options.baseUrl;
    }

    rules = helper.readJson(path, encoding, yml);

    if (!Array.isArray(rules)) {
      log.warn('WARNING', rules);
      return rules;
    }

    opt.rules = rules;

    return rules;
  };

  var getRules = function() {
    return opt.rules;
  };

  /**
   * [authorize Express middleware]
   * @param  {[type]}   req  [Th request object]
   * @param  {[type]}   res  [The response object]
   * @param  {Function} next [description]
   * @return {[type]}        [description]
   */

  var authorize = function(req, res, next) {
    var method = req.method;
    var role, resource, methods, index, action, group, length, boolean,
      policy, currResource;

    /**
     * Get the role from req.decoded or req.session
     */

    resource = helper.resource(next, req.originalUrl, opt.baseUrl);
    /**
     * if not resource terminate script
     */

    if (!resource) {
      return;
    }

    /**
     * [group description]
     * @type {[type]}
     */

    role = helper.role(res, req.decoded, req.session);

    /**
     * get resource from the url
     */

    group = helper.group(res, opt.rules, role);

    /**
     * if no group
     */

    if (group) {
      policy = group.permissions[0];
      currResource = policy.resource;
      length = group.permissions.length;
      methods = policy.methods;
    } else {
      return;
    }

    /**
     * Globs/ resources
     * 1. action: "allow"
     */

    if (length === 1 && currResource === '*' && policy.action === 'allow') {
      /*
       * Allow traffic to all  resources
       * 1. Check for methods
       * 2. If its a string and a glob '*'
       * 3. Allow traffic on all methods
       * 4. If methods are defined
       * 5. Allow traffic on the defined methods and deny the rest
       *
       * If the method is a glob '*' grant access
       */

      if (typeof methods === 'string' && methods === '*') {

        return next();

        /* istanbul ignore else */
      } else if (typeof methods === 'string' && methods !== '*') {
        /* istanbul ignore next */

        throw new Error('DefinationError: Unrecognised glob, use "*"');

      }

      /**
       * [if Its an array of  methods]
       * 1. check if the method is defined
       * 2. If defined Allow traffic else deny access
       */

      if (Array.isArray(methods)) {

        index = methods.indexOf(method);

        switch (index) {
          case -1:
            return res
              .status(403)
              .send(opt.denied);
          default:
            return next();

        }
      }
    }

    /**
     * 2. Action: "deny";
     */

    if (length === 1 && currResource === '*' && policy.action === 'deny') {
      /*
       * Allow traffic to all  resources
       * 1. Check for methods
       * 2. If its a string and a glob '*'
       * 3. Allow traffic on all methods
       * 4. If methods are defined
       * 5. Allow traffic on the defined methods and deny the rest
       */

      if (typeof methods === 'string' && methods === '*') {

        return res
          .status(403)
          .send(opt.denied);
        /* istanbul ignore else */
      }

      if (typeof methods === 'string' && methods !== '*') {
        /* istanbul ignore next */

        throw new Error('DefinationError: Unrecognised glob, use "*"');
      }

      if (Array.isArray(methods)) {

        index = methods.indexOf(method);

        switch (index) {
          case -1:
            return next();
          default:
            return res
              .status(403)
              .send(opt.denied);

        }
      }

    }

    /**
     * If we have more that one group and we no glob '*'
     */

    if (length >= 1 && resource !== '*') {

      /**
       * [methods Get all the methods defined on the group]
       * @param {[Object]} [group]
       * @param {string} [resource]
       * @type {[Array]}
       */

      policy = helper.policy(group, resource);

      if (!policy) {
        return res
          .status(403)
          .send(opt.denied);
      }

      methods = policy.methods;

      /**
       * If the methods are defined with a glob "*"
       */

      if (methods && typeof methods === 'string' && methods === '*') {
        action = policy.action;

        switch (action) {
          case 'deny':
            return res
              .status(403)
              .send(opt.denied);

          case 'allow':
            return next();

        }
        /* istanbul ignore else */
      }

      if (methods && typeof methods === 'string' && methods !== '*') {

        /* istanbul ignore next */
        throw new Error('DefinationError: Unrecognised glob. use "*"');
      }

      /**
       * If the methods are defined in an array
       */

      if (Array.isArray(methods)) {
        boolean = methods.includes(method);
        switch (boolean) {
          case true:
            action = policy.action;
            switch (action) {
              case 'allow':
                return next();

              case 'deny':
                return res
                  .status(403)
                  .send(opt.denied);
            }
            /* istanbul ignore next */
            break;

          case false:
            action = policy.action;
            switch (action) {
              case 'allow':
                return res
                  .status(403)
                  .send(opt.denied);

              case 'deny':
                return next();

            }
        }
      }

    }
  };

  /**
   * Add unless to the authorize middleware.
   * By default express-acl will block all traffic to routes that have no plocy
   * defined against them, this module will enable express-acl to exclude them
   */

  authorize.unless = unless;

  /**
   * export the functionality
   *
   */

  module.exports = {
    config: config,
    getRules: getRules,
    authorize: authorize
  };

})();
<commit_msg>Fix failing tests<commit_after>/**
 *  nacl
 *  copyright(c) 2016 - 2019 Andela Kenya Ltd
 *  MIT Lincensed
 */

(function() {
  'use strict';
  require('colors');
  require('./includes');
  var helper = require('./helpers');
  var log = require('npmlog');
  var unless = require('express-unless');

  var opt = {
    denied: {
      status: 403,
      success: false,
      error: 'ACCESS DENIED'
    }
  };

  /**
   * [config Loads the rules from our config file]
   * @param  {[options]} options [defines where the
   * config file is located, and the encoding type]
   *
   */

  var config = function(options) {
    var path, rules, encoding;
    var yml = false;

    /**
     * Get the filename
     */

    var filename = yml ? 'nacl.yml' : 'nacl.json';

    filename = options && options.filename ? options.filename : filename;

    /**
     * Get the path
     */

    path = options && options.path ? options.path : path;

    /**
     * Merge filename and path
     */

    path = filename && path ? (path + '/' + filename) : filename;

    if (options && options.baseUrl) {
      yml = options.yml;
      encoding = options.encoding;
      opt.baseUrl = options.baseUrl;
    }

    rules = helper.readJson(path, encoding, yml);

    if (!Array.isArray(rules)) {
      log.warn('WARNING', rules);
      return rules;
    }

    opt.rules = rules;

    return rules;
  };

  var getRules = function() {
    return opt.rules;
  };

  /**
   * [authorize Express middleware]
   * @param  {[type]}   req  [Th request object]
   * @param  {[type]}   res  [The response object]
   * @param  {Function} next [description]
   * @return {[type]}        [description]
   */

  var authorize = function(req, res, next) {
    var method = req.method;
    var role, resource, methods, index, action, group, length, boolean,
      policy, currResource;

    /**
     * Get the role from req.decoded or req.session
     */

    resource = helper.resource(next, req.originalUrl, opt.baseUrl);
    /**
     * if not resource terminate script
     */

    if (!resource) {
      return;
    }

    /**
     * [group description]
     * @type {[type]}
     */

    role = helper.role(res, req.decoded, req.session);

    /**
     * get resource from the url
     */

    group = helper.group(res, opt.rules, role);

    /**
     * if no group
     */

    if (group) {
      policy = group.permissions[0];
      currResource = policy.resource;
      length = group.permissions.length;
      methods = policy.methods;
    } else {
      return;
    }

    /**
     * Globs/ resources
     * 1. action: "allow"
     */

    if (length === 1 && currResource === '*' && policy.action === 'allow') {
      /*
       * Allow traffic to all  resources
       * 1. Check for methods
       * 2. If its a string and a glob '*'
       * 3. Allow traffic on all methods
       * 4. If methods are defined
       * 5. Allow traffic on the defined methods and deny the rest
       *
       * If the method is a glob '*' grant access
       */

      if (typeof methods === 'string' && methods === '*') {

        return next();

        /* istanbul ignore else */
      } else if (typeof methods === 'string' && methods !== '*') {
        /* istanbul ignore next */

        throw new Error('DefinationError: Unrecognised glob, use "*"');

      }

      /**
       * [if Its an array of  methods]
       * 1. check if the method is defined
       * 2. If defined Allow traffic else deny access
       */

      if (Array.isArray(methods)) {

        index = methods.indexOf(method);

        switch (index) {
          case -1:
            return res
              .status(403)
              .send(opt.denied);
          default:
            return next();

        }
      }
    }

    /**
     * 2. Action: "deny";
     */

    if (length === 1 && currResource === '*' && policy.action === 'deny') {
      /*
       * Allow traffic to all  resources
       * 1. Check for methods
       * 2. If its a string and a glob '*'
       * 3. Allow traffic on all methods
       * 4. If methods are defined
       * 5. Allow traffic on the defined methods and deny the rest
       */

      if (typeof methods === 'string' && methods === '*') {

        return res
          .status(403)
          .send(opt.denied);
        /* istanbul ignore else */
      }

      if (typeof methods === 'string' && methods !== '*') {
        /* istanbul ignore next */

        throw new Error('DefinationError: Unrecognised glob, use "*"');
      }

      if (Array.isArray(methods)) {

        index = methods.indexOf(method);

        switch (index) {
          case -1:
            return next();
          default:
            return res
              .status(403)
              .send(opt.denied);

        }
      }

    }

    /**
     * If we have more that one group and we no glob '*'
     */

    if (length >= 1 && resource !== '*') {

      /**
       * [methods Get all the methods defined on the group]
       * @param {[Object]} [group]
       * @param {string} [resource]
       * @type {[Array]}
       */

      policy = helper.policy(group, resource);

      if (!policy) {
        return res
          .status(403)
          .send(opt.denied);
      }

      methods = policy.methods;

      /**
       * If the methods are defined with a glob "*"
       */

      if (methods && typeof methods === 'string' && methods === '*') {
        action = policy.action;

        switch (action) {
          case 'deny':
            return res
              .status(403)
              .send(opt.denied);

          case 'allow':
            return next();

        }
        /* istanbul ignore else */
      }

      if (methods && typeof methods === 'string' && methods !== '*') {

        /* istanbul ignore next */
        throw new Error('DefinationError: Unrecognised glob. use "*"');
      }

      /**
       * If the methods are defined in an array
       */

      if (Array.isArray(methods)) {
        boolean = methods.includes(method);
        switch (boolean) {
          case true:
            action = policy.action;
            switch (action) {
              case 'allow':
                return next();

              case 'deny':
                return res
                  .status(403)
                  .send(opt.denied);
            }
            /* istanbul ignore next */
            break;

          case false:
            action = policy.action;
            switch (action) {
              case 'allow':
                return res
                  .status(403)
                  .send(opt.denied);

              case 'deny':
                return next();

            }
        }
      }

    }
  };

  /**
   * Add unless to the authorize middleware.
   * By default express-acl will block all traffic to routes that have no plocy
   * defined against them, this module will enable express-acl to exclude them
   */

  authorize.unless = unless;

  /**
   * export the functionality
   *
   */

  module.exports = {
    config: config,
    getRules: getRules,
    authorize: authorize
  };

})();
<|endoftext|>


<commit_before>import Ember from 'ember';
import { task, all, allSettled } from 'ember-concurrency';

module('Unit: yieldables');

test("all behaves like Promise.all", function(assert) {
  assert.expect(6);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      let allPromise = all([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
      assert.equal(typeof allPromise.then, 'function');
      let values = yield allPromise;
      assert.deepEqual(values, ['a', 'b', 'c']);
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      let value = yield defer.promise;
      return value;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().resolve('a'));
  assert.equal(childTask.get('concurrency'), 2);
  Ember.run(() => defers.shift().resolve('b'));
  assert.equal(childTask.get('concurrency'), 1);
  Ember.run(() => defers.shift().resolve('c'));
  assert.equal(childTask.get('concurrency'), 0);
});

test("all cancels all other joined tasks if one of them fails", function(assert) {
  assert.expect(3);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      try {
        yield all([
          task.perform(),
          task.perform(),
          task.perform(),
        ]);
      } catch(e) {
        assert.equal(e.wat, 'lol');
      }
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      yield defer.promise;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().reject({ wat: 'lol' }));
  assert.equal(childTask.get('concurrency'), 0);
});

test("all cancels all joined tasks if parent task is canceled", function(assert) {
  assert.expect(2);

  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      yield all([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
    }),

    child: task(function * () {
      yield Ember.RSVP.defer().promise;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => obj.get('parent').cancelAll());
  assert.equal(childTask.get('concurrency'), 0);
});

test("allSettled behaves like Promise.allSettled", function(assert) {
  assert.expect(6);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      let allPromise = allSettled([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
      assert.equal(typeof allPromise.then, 'function');
      let values = yield allPromise;
      assert.deepEqual(values, [{ state: 'fulfilled', value: 'a' }, { state: 'fulfilled', value: 'b' }, { state: 'fulfilled', value: 'c' }]);
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      let value = yield defer.promise;
      return value;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().resolve('a'));
  assert.equal(childTask.get('concurrency'), 2);
  Ember.run(() => defers.shift().resolve('b'));
  assert.equal(childTask.get('concurrency'), 1);
  Ember.run(() => defers.shift().resolve('c'));
  assert.equal(childTask.get('concurrency'), 0);
});

test("allSettled does not cancel all other joined tasks if one of them fails", function(assert) {
  assert.expect(6);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      let allPromise = allSettled([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
      assert.equal(typeof allPromise.then, 'function');
      let values = yield allPromise;
      assert.deepEqual(values, [{ state: 'fulfilled', value: 'a' }, { state: 'rejected', reason: { wat: 'lol' } }, { state: 'fulfilled', value: 'c' }]);
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      let value = yield defer.promise;
      return value;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().resolve('a'));
  assert.equal(childTask.get('concurrency'), 2);
  Ember.run(() => defers.shift().reject({ wat: 'lol' }));
  assert.equal(childTask.get('concurrency'), 1);
  Ember.run(() => defers.shift().resolve('c'));
  assert.equal(childTask.get('concurrency'), 0);
});

test("allSettled cancels all joined tasks if parent task is canceled", function(assert) {
  assert.expect(2);

  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      yield allSettled([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
    }),

    child: task(function * () {
      yield Ember.RSVP.defer().promise;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => obj.get('parent').cancelAll());
  assert.equal(childTask.get('concurrency'), 0);
});
<commit_msg>Fixing deepEqual compare errors<commit_after>import Ember from 'ember';
import { task, all, allSettled } from 'ember-concurrency';

module('Unit: yieldables');

test("all behaves like Promise.all", function(assert) {
  assert.expect(6);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      let allPromise = all([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
      assert.equal(typeof allPromise.then, 'function');
      let values = yield allPromise;
      assert.deepEqual(values, ['a', 'b', 'c']);
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      let value = yield defer.promise;
      return value;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().resolve('a'));
  assert.equal(childTask.get('concurrency'), 2);
  Ember.run(() => defers.shift().resolve('b'));
  assert.equal(childTask.get('concurrency'), 1);
  Ember.run(() => defers.shift().resolve('c'));
  assert.equal(childTask.get('concurrency'), 0);
});

test("all cancels all other joined tasks if one of them fails", function(assert) {
  assert.expect(3);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      try {
        yield all([
          task.perform(),
          task.perform(),
          task.perform(),
        ]);
      } catch(e) {
        assert.equal(e.wat, 'lol');
      }
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      yield defer.promise;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().reject({ wat: 'lol' }));
  assert.equal(childTask.get('concurrency'), 0);
});

test("all cancels all joined tasks if parent task is canceled", function(assert) {
  assert.expect(2);

  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      yield all([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
    }),

    child: task(function * () {
      yield Ember.RSVP.defer().promise;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => obj.get('parent').cancelAll());
  assert.equal(childTask.get('concurrency'), 0);
});

test("allSettled behaves like Promise.allSettled", function(assert) {
  assert.expect(6);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      let allPromise = allSettled([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
      assert.equal(typeof allPromise.then, 'function');
      let values = yield allPromise;
      assert.deepEqual(values, [{ state: 'fulfilled', value: 'a' }, { state: 'fulfilled', value: 'b' }, { state: 'fulfilled', value: 'c' }]);
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      let value = yield defer.promise;
      return value;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().resolve('a'));
  assert.equal(childTask.get('concurrency'), 2);
  Ember.run(() => defers.shift().resolve('b'));
  assert.equal(childTask.get('concurrency'), 1);
  Ember.run(() => defers.shift().resolve('c'));
  assert.equal(childTask.get('concurrency'), 0);
});

test("allSettled does not cancel all other joined tasks if one of them fails", function(assert) {
  assert.expect(9);

  let defers = [];
  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      let allPromise = allSettled([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
      assert.equal(typeof allPromise.then, 'function');
      let values = yield allPromise;
      let fulfilled = values.filter((value) => value.state === 'fulfilled');
      let rejected = values.filter((value) => value.state !== 'fulfilled');
      assert.deepEqual(fulfilled, [{ state: 'fulfilled', value: 'a' }, { state: 'fulfilled', value: 'c' }]);
      assert.equal(rejected.length, 1);
      assert.equal(rejected[0].state, 'rejected');
      assert.equal(rejected[0].reason.message, 'wat');
    }),

    child: task(function * () {
      let defer = Ember.RSVP.defer();
      defers.push(defer);
      let value = yield defer.promise;
      return value;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => defers.shift().resolve('a'));
  assert.equal(childTask.get('concurrency'), 2);
  Ember.run(() => defers.shift().reject(new Error('wat')));
  assert.equal(childTask.get('concurrency'), 1);
  Ember.run(() => defers.shift().resolve('c'));
  assert.equal(childTask.get('concurrency'), 0);
});

test("allSettled cancels all joined tasks if parent task is canceled", function(assert) {
  assert.expect(2);

  let Obj = Ember.Object.extend({
    parent: task(function * () {
      let task = this.get('child');
      yield allSettled([
        task.perform(),
        task.perform(),
        task.perform(),
      ]);
    }),

    child: task(function * () {
      yield Ember.RSVP.defer().promise;
    }),
  });

  let obj;
  Ember.run(() => {
    obj = Obj.create();
    obj.get('parent').perform();
  });

  let childTask = obj.get('child');
  assert.equal(childTask.get('concurrency'), 3);
  Ember.run(() => obj.get('parent').cancelAll());
  assert.equal(childTask.get('concurrency'), 0);
});
<|endoftext|>


<commit_before>/*
Copyright 2011 Timothy J Fontaine <tjfontaine@gmail.com>

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

*/

"use strict";

var unpack = function (buff, pos) {
  var hit_label = false,
    read_size = 0,
    start_pos = pos,
    end,
    offset,
    parts = [],
    len = buff.readUInt8(pos);

  while (len !== 0) {
    if (len & 0xC0) {
      offset = len - 0xC0;
      if (offset === 0) {
        pos = buff.readUInt8(pos + 1);
        if (!hit_label) {
          read_size += 1;
        }
      } else {
        pos = offset;
      }
      len = buff.readUInt8(pos);
      hit_label = true;
      continue;
    }
    pos++;
    if (!hit_label) {
      read_size += 1;
    }
    end = pos + len;
    parts.push(buff.toString('ascii', pos, end));
    pos += len;
    if (!hit_label) {
      read_size += len;
    }
    len = buff.readUInt8(pos);
  }
  return {
    value: parts.join('.'),
    position: start_pos + read_size + 1,
  };
};
exports.unpack = unpack;

var pack = function (str) {
  var a = str.split('.'), b, i,
    buff = new Buffer(str.length + 2),
    pos = 0;

  for (i = 0; i < a.length; i++) {
    b = a[i];
    if (b.length) {
      buff.writeUInt8(b.length, pos);
      pos++;
      buff.write(b, pos, b.length);
      pos += b.length;
    }
  }
  buff.writeUInt8(0, pos);
  return buff;
};
exports.pack = pack;
<commit_msg>remove usage of continue, use else statement<commit_after>/*
Copyright 2011 Timothy J Fontaine <tjfontaine@gmail.com>

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

*/

"use strict";

var unpack = function (buff, pos) {
  var hit_label = false,
    read_size = 0,
    start_pos = pos,
    end,
    offset,
    parts = [],
    len = buff.readUInt8(pos);

  while (len !== 0) {
    if (len & 0xC0) {
      offset = len - 0xC0;
      if (offset === 0) {
        pos = buff.readUInt8(pos + 1);
        if (!hit_label) {
          read_size += 1;
        }
      } else {
        pos = offset;
      }
      len = buff.readUInt8(pos);
      hit_label = true;
    } else {
      pos++;
      if (!hit_label) {
        read_size += 1;
      }
      end = pos + len;
      parts.push(buff.toString('ascii', pos, end));
      pos += len;
      if (!hit_label) {
        read_size += len;
      }
      len = buff.readUInt8(pos);
    }
  }
  return {
    value: parts.join('.'),
    position: start_pos + read_size + 1,
  };
};
exports.unpack = unpack;

var pack = function (str) {
  var a = str.split('.'), b, i,
    buff = new Buffer(str.length + 2),
    pos = 0;

  for (i = 0; i < a.length; i++) {
    b = a[i];
    if (b.length) {
      buff.writeUInt8(b.length, pos);
      pos++;
      buff.write(b, pos, b.length);
      pos += b.length;
    }
  }
  buff.writeUInt8(0, pos);
  return buff;
};
exports.pack = pack;
<|endoftext|>