<commit_before>/**
 * @file Tr component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, Fragment} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Td from '../_Td';

import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableCalculation from '../_vendors/TableCalculation';

class Tr extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    isCollapsed = () => {

        const {idProp, data, expandRows} = this.props;

        if (!expandRows || expandRows.length < 1) {
            return true;
        }

        return TableCalculation.indexOfNodeInValue(data, expandRows, idProp) === -1;

    };

    handleMouseEnter = e => {
        const {rowIndex, onMouseEnter} = this.props;
        onMouseEnter && onMouseEnter(e, rowIndex);
    };

    handleMouseLeave = e => {
        const {rowIndex, onMouseLeave} = this.props;
        onMouseLeave && onMouseLeave(e, rowIndex);
    };

    handleClick = e => {
        const {data, rowIndex, disabled, onRowClick} = this.props;
        !disabled && onRowClick && onRowClick(data, rowIndex, e);
    };

    render() {

        const {

                className, columns, hoverRowIndex, rowIndex, data, parentData, tableData,
                isChecked, disabled, baseColIndex, depth, index, path,

                ...respProps

            } = this.props,
            collapsed = this.isCollapsed(),
            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.BODY, columns, data, rowIndex),
            nodePath = path || [{index, node: data}];

        return (
            <Fragment>

                <tr className={classNames({
                    checked: isChecked,
                    expanded: !collapsed,
                    hover: hoverRowIndex === rowIndex,
                    [data.rowClassName]: data.rowClassName,
                    [className]: className
                })}
                    style={data.rowStyle}
                    disabled={disabled}
                    onMouseEnter={this.handleMouseEnter}
                    onMouseLeave={this.handleMouseLeave}
                    onClick={this.handleClick}>
                    {
                        columnsWithSpan && columnsWithSpan.map(({column, span}, colIndex) => column ?
                            <Td {...respProps}
                                key={colIndex}
                                className={column.bodyClassName}
                                style={column.bodyStyle}
                                rowIndex={rowIndex}
                                colIndex={baseColIndex + colIndex}
                                data={data}
                                parentData={parentData}
                                tableData={tableData}
                                collapsed={collapsed}
                                renderer={column.bodyRenderer}
                                align={column.bodyAlign || column.align}
                                span={span}
                                disabled={disabled}
                                noWrap={TableCalculation.handleNoWrap(column.bodyNoWrap, column.noWrap, {
                                    data,
                                    rowIndex,
                                    colIndex: baseColIndex + colIndex,
                                    tableData
                                })}
                                depth={depth}
                                path={nodePath}
                                sortable={column.sortable}
                                sortingProp={column.sortingProp}/>
                            :
                            null
                        )
                    }

                {
                    /*rowHasChildren && */!collapsed && data && data.children && data.children.length > 0 ?
                    data.children.map((item, index) =>
                        <Tr {...this.props}
                            key={index}
                            index={index}
                            data={item}
                            parentData={data}
                            depth={depth + 1}
                            path={
                                nodePath ?
                                    [...nodePath, {index, node: item}]
                                    :
                                    [{index, node: item}]
                            }/>
                    )
                    :
                    null
                }

            </Fragment>
        );

    }
}

Tr.propTypes = {

    className: PropTypes.string,

    hoverRowIndex: PropTypes.number,
    rowIndex: PropTypes.number,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.object,
    parentData: PropTypes.object,
    tableData: PropTypes.array,
    isChecked: PropTypes.bool,
    disabled: PropTypes.bool,
    expandRows: PropTypes.array,
    baseColIndex: PropTypes.number,
    depth: PropTypes.number,
    index: PropTypes.number,
    path: PropTypes.array,
    idProp: PropTypes.string,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),

    /**
     * callback
     */
    onRowClick: PropTypes.func,
    onCellClick: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func,
    onExpandChange: PropTypes.func

};

Tr.defaultProps = {
    rowIndex: 0,
    isChecked: false,
    disabled: false,
    expandRows: [],
    baseColIndex: 0,
    depth: 0,
    idProp: 'id'
};

export default Tr;
<commit_msg>update Tr<commit_after>/**
 * @file Tr component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, Fragment} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Td from '../_Td';

import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableCalculation from '../_vendors/TableCalculation';

class Tr extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    isCollapsed = () => {

        const {idProp, data, expandRows} = this.props;

        if (!expandRows || expandRows.length < 1) {
            return true;
        }

        return TableCalculation.indexOfNodeInValue(data, expandRows, idProp) === -1;

    };

    handleMouseEnter = e => {
        const {isMouseEventForbidden, rowIndex, onMouseEnter} = this.props;
        !isMouseEventForbidden && onMouseEnter && onMouseEnter(e, rowIndex);
    };

    handleMouseLeave = e => {
        const {isMouseEventForbidden, rowIndex, onMouseLeave} = this.props;
        !isMouseEventForbidden && onMouseLeave && onMouseLeave(e, rowIndex);
    };

    handleClick = e => {
        const {data, rowIndex, disabled, onRowClick} = this.props;
        !disabled && onRowClick && onRowClick(data, rowIndex, e);
    };

    render() {

        const {

                className, columns, hoverRowIndex, rowIndex, data, parentData, tableData,
                isChecked, disabled, baseColIndex, depth, index, path,

                ...respProps

            } = this.props,
            collapsed = this.isCollapsed(),
            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.BODY, columns, data, rowIndex),
            nodePath = path || [{index, node: data}];

        return (
            <Fragment>

                <tr className={classNames({
                    checked: isChecked,
                    expanded: !collapsed,
                    hover: hoverRowIndex === rowIndex,
                    [data.rowClassName]: data.rowClassName,
                    [className]: className
                })}
                    style={data.rowStyle}
                    disabled={disabled}
                    onMouseEnter={this.handleMouseEnter}
                    onMouseLeave={this.handleMouseLeave}
                    onClick={this.handleClick}>
                    {
                        columnsWithSpan && columnsWithSpan.map(({column, span}, colIndex) => column ?
                            <Td {...respProps}
                                key={colIndex}
                                className={column.bodyClassName}
                                style={column.bodyStyle}
                                rowIndex={rowIndex}
                                colIndex={baseColIndex + colIndex}
                                data={data}
                                parentData={parentData}
                                tableData={tableData}
                                collapsed={collapsed}
                                renderer={column.bodyRenderer}
                                align={column.bodyAlign || column.align}
                                span={span}
                                disabled={disabled}
                                noWrap={TableCalculation.handleNoWrap(column.bodyNoWrap, column.noWrap, {
                                    data,
                                    rowIndex,
                                    colIndex: baseColIndex + colIndex,
                                    tableData
                                })}
                                depth={depth}
                                path={nodePath}
                                sortable={column.sortable}
                                sortingProp={column.sortingProp}/>
                            :
                            null
                        )
                    }

                {
                    /*rowHasChildren && */!collapsed && data && data.children && data.children.length > 0 ?
                    data.children.map((item, index) =>
                        <Tr {...this.props}
                            key={index}
                            index={index}
                            data={item}
                            parentData={data}
                            depth={depth + 1}
                            path={
                                nodePath ?
                                    [...nodePath, {index, node: item}]
                                    :
                                    [{index, node: item}]
                            }/>
                    )
                    :
                    null
                }

            </Fragment>
        );

    }
}

Tr.propTypes = {

    className: PropTypes.string,

    hoverRowIndex: PropTypes.number,
    rowIndex: PropTypes.number,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.object,
    parentData: PropTypes.object,
    tableData: PropTypes.array,
    isChecked: PropTypes.bool,
    disabled: PropTypes.bool,
    expandRows: PropTypes.array,
    baseColIndex: PropTypes.number,
    depth: PropTypes.number,
    index: PropTypes.number,
    path: PropTypes.array,
    idProp: PropTypes.string,
    isMouseEventForbidden: PropTypes.bool,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),

    /**
     * callback
     */
    onRowClick: PropTypes.func,
    onCellClick: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func,
    onExpandChange: PropTypes.func

};

Tr.defaultProps = {
    rowIndex: 0,
    isChecked: false,
    disabled: false,
    expandRows: [],
    baseColIndex: 0,
    depth: 0,
    idProp: 'id',
    isMouseEventForbidden: false
};

export default Tr;
<|endoftext|>


<commit_before>import test from 'ava'
import path from 'path'
import fs from 'fs'
import Jimp from 'jimp'

function existsSync (uri) {
  try {
    fs.statSync(uri)
    return true
  } catch (error) {
    return false
  }
}

test.afterEach.always(t => {
  // this runs after each test and other test hooks, even if they failed
  // remove created file
  try {
    fs.unlinkSync(t.context.outputPath)
  } catch(err) {}
})

test.beforeEach(t => {
  let jamPath = '../dist/index.js'
  t.context = {
    jamPath: path.resolve(__dirname, jamPath),
    resolution: '160x120'
  }
})

// note : use this with the node xxx command to debug in chrome: --inspect --debug-brk

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(stl)', t => {
  // FIXME: can only be run locally (webgl support needed), commented out for now for travisCI
  // see https://github.com/stackgl/headless-gl/blob/master/.travis.yml
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/cube.stl')
  const outputPath = path.resolve(__dirname, './test.stl.png')
  const expImagePath = path.resolve(__dirname, './data/exp.cube.stl.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} ${inputPath} ${t.context.resolution} ${outputPath} `
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})
  // t.deepEqual(meshSource[0], 'fakeModel.stl')
  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      const [exp, obs] = values
      const diff = Jimp.diff(exp, obs)
      const dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(3mf)', t => {
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/cube_gears.3mf') // cube_gears.3mf'// dodeca_chain_loop_color.3mf'// pyramid_vertexcolor.3mf'
  const outputPath = path.resolve(__dirname, './test.3mf.png')
  const expImagePath = path.resolve(__dirname, './data/exp.cube_gears.3mf.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} ${inputPath} ${t.context.resolution} ${outputPath} `
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})
  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      let [exp, obs] = values
      let diff = Jimp.diff(exp, obs)
      let dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(obj)', t => {
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/cube.obj')
  const outputPath = path.resolve(__dirname, './test.obj.png')
  const expImagePath = path.resolve(__dirname, './data/exp.cube.obj.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} ${inputPath} ${t.context.resolution} ${outputPath} `
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})

  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      let [exp, obs] = values
      let diff = Jimp.diff(exp, obs)
      let dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(ctm)', t => {
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/LeePerry.ctm')
  const outputPath = path.resolve(__dirname, './test.ctm.png')
  const expImagePath = path.resolve(__dirname, './data/exp.LeePerry.ctm.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} ${inputPath} ${t.context.resolution} ${outputPath} `
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})

  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      let [exp, obs] = values
      let diff = Jimp.diff(exp, obs)
      let dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})
<commit_msg>test(updated api): modified all calls to the CLI tool to use new API<commit_after>import test from 'ava'
import path from 'path'
import fs from 'fs'
import Jimp from 'jimp'

function existsSync (uri) {
  try {
    fs.statSync(uri)
    return true
  } catch (error) {
    return false
  }
}

test.afterEach.always(t => {
  // this runs after each test and other test hooks, even if they failed
  // remove created file
  try {
    fs.unlinkSync(t.context.outputPath)
  } catch(err) {}
})

test.beforeEach(t => {
  let jamPath = '../dist/index.js'
  t.context = {
    jamPath: path.resolve(__dirname, jamPath),
    resolution: '160x120'
  }
})

// note : use this with the node xxx command to debug in chrome: --inspect --debug-brk

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(stl)', t => {
  // FIXME: can only be run locally (webgl support needed), commented out for now for travisCI
  // see https://github.com/stackgl/headless-gl/blob/master/.travis.yml
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/cube.stl')
  const outputPath = path.resolve(__dirname, './test.stl.png')
  const expImagePath = path.resolve(__dirname, './data/exp.cube.stl.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} input=${inputPath} output=${outputPath} resolution=${t.context.resolution}`
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})
  // t.deepEqual(meshSource[0], 'fakeModel.stl')
  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      const [exp, obs] = values
      const diff = Jimp.diff(exp, obs)
      const dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(3mf)', t => {
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/cube_gears.3mf') // cube_gears.3mf'// dodeca_chain_loop_color.3mf'// pyramid_vertexcolor.3mf'
  const outputPath = path.resolve(__dirname, './test.3mf.png')
  const expImagePath = path.resolve(__dirname, './data/exp.cube_gears.3mf.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} input=${inputPath} output=${outputPath} resolution=${t.context.resolution}`
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})
  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      let [exp, obs] = values
      let diff = Jimp.diff(exp, obs)
      let dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(obj)', t => {
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/cube.obj')
  const outputPath = path.resolve(__dirname, './test.obj.png')
  const expImagePath = path.resolve(__dirname, './data/exp.cube.obj.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} input=${inputPath} output=${outputPath} resolution=${t.context.resolution}`
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})

  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      let [exp, obs] = values
      let diff = Jimp.diff(exp, obs)
      let dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})

test('server side renderer: can take a path to a file as input, generate a render of that 3d file as ouput(ctm)', t => {
  const jamPath = t.context.jamPath
  const inputPath = path.resolve(__dirname, './data/LeePerry.ctm')
  const outputPath = path.resolve(__dirname, './test.ctm.png')
  const expImagePath = path.resolve(__dirname, './data/exp.LeePerry.ctm.png')
  t.context = Object.assign({}, t.context, {outputPath})

  const cmd = `node ${jamPath} input=${inputPath} output=${outputPath} resolution=${t.context.resolution}`
  require('child_process').execSync(cmd, {stdio: [0, 1, 2]})

  t.deepEqual(true, existsSync(outputPath))

  return Promise.all([Jimp.read(expImagePath), Jimp.read(outputPath)])
    .then(function (values) {
      let [exp, obs] = values
      let diff = Jimp.diff(exp, obs)
      let dist = Jimp.distance(exp, obs)
      const identical = (dist < 0.1 && diff.percent < 0.1)
      t.deepEqual(true, identical)
    }).catch(function () {
    t.fail('Files are not identical', expImagePath, outputPath)
  })
})
<|endoftext|>


<commit_before>function basic_sum_AB_test( assert, mode ) {
	var f = GPU(function(a, b) {
		var ret = a[this.thread.x] + b[this.thread.x];
		return ret;
	}, {
		thread : [3],
		block : [1],
		mode : mode
	});

	assert.ok( f !== null, "function generated test");
	assert.deepEqual(f( [1, 2, 3], [4, 5, 6] ), [5, 7, 9], "basic sum function test");
}

QUnit.test( "basic_sum_AB (auto)", function( assert ) {
	basic_sum_AB_test(assert, null);
});

QUnit.test( "basic_sum_AB (GPU)", function( assert ) {
	basic_sum_AB_test(assert, "gpu");
});

QUnit.test( "basic_sum_AB (CPU)", function( assert ) {
	basic_sum_AB_test(assert, "cpu");
});

/*
// EXAMPLE GLSL

// boilerplate begin!!!
float _W_ = XXXX; // HARDCODE FROM PARSER
float _H_ = XXXX; // HARDCODE FROM PARSER

float _blockX_ = 1; // HARDCODE FROM PARSER
float _blockY_ = 1; // HARDCODE FROM PARSER
float _blockZ_ = 1; // HARDCODE FROM PARSER
float _blockDimX_ = 1; // HARDCODE FROM PARSER
float _blockDimY_ = 1; // HARDCODE FROM PARSER
float _blockDimZ_ = 1; // HARDCODE FROM PARSER
float _threadDimX_ = 1; // HARDCODE FROM PARSER
float _threadDimY_ = 1; // HARDCODE FROM PARSER
float _threadDimZ_ = 1; // HARDCODE FROM PARSER

float _coordToIndex_(vec3 coord) {
	return coord.x + _threadDimX_ * (coord.y + _threadDimY_ * coord.z);
}

vec3 _indexTo3DCoord_(float index) {
	vec3 ret;

	ret.z = round(index / (_threadDimX_ * _threadDimY_));
	ret.y = round((index - ret.z * _threadDimY_) / _threadDimX_);
	ret.x = index - _threadDimX_ * (ret.y + _threadDimY_ * ret.z);

	return ret;
}

vec2 _indexTo2DCoord_(float index) {
	vec2 ret;

	ret.y = mod(index, _W_);
	ret.x = round(index / _W_);

	return ret;
}

float _coordToIndex_(vec2 coord) {
	return coord.x + _W_ * coord.y;
}

void main(float* a, float* b) {
    vec2 _vecId_ = get_global_id();
	float _id_ = _vecId_.x + _vecId_.y * _W_;

	float _thread_ = _indexTo3D_(_id_);

	float _threadZ_ =  _thread_.z;
	float _threadY_ =  _thread_.y;
	float _threadX_ =  _thread_.x;
// boilerplate end!!!

	float ret = a[_indexTo2DCoord_(_threadX_)] + b[_indexTo2DCoord_(_threadX_)];
	out_float = ret; // FROM RETURN
	return;
}
 */
<commit_msg>bugfix in boilerplate<commit_after>function basic_sum_AB_test( assert, mode ) {
	var f = GPU(function(a, b) {
		var ret = a[this.thread.x] + b[this.thread.x];
		return ret;
	}, {
		thread : [3],
		block : [1],
		mode : mode
	});

	assert.ok( f !== null, "function generated test");
	assert.deepEqual(f( [1, 2, 3], [4, 5, 6] ), [5, 7, 9], "basic sum function test");
}

QUnit.test( "basic_sum_AB (auto)", function( assert ) {
	basic_sum_AB_test(assert, null);
});

QUnit.test( "basic_sum_AB (GPU)", function( assert ) {
	basic_sum_AB_test(assert, "gpu");
});

QUnit.test( "basic_sum_AB (CPU)", function( assert ) {
	basic_sum_AB_test(assert, "cpu");
});

/*
// EXAMPLE GLSL

// boilerplate begin!!!
float _W_ = XXXX; // HARDCODE FROM PARSER
float _H_ = XXXX; // HARDCODE FROM PARSER

float _blockX_ = 1; // HARDCODE FROM PARSER
float _blockY_ = 1; // HARDCODE FROM PARSER
float _blockZ_ = 1; // HARDCODE FROM PARSER
float _blockDimX_ = 1; // HARDCODE FROM PARSER
float _blockDimY_ = 1; // HARDCODE FROM PARSER
float _blockDimZ_ = 1; // HARDCODE FROM PARSER
float _threadDimX_ = 1; // HARDCODE FROM PARSER
float _threadDimY_ = 1; // HARDCODE FROM PARSER
float _threadDimZ_ = 1; // HARDCODE FROM PARSER

float _coordToIndex_(vec3 coord) {
	return coord.x + _threadDimX_ * (coord.y + _threadDimY_ * coord.z);
}

vec3 _indexTo3DCoord_(float index) {
	vec3 ret;

	ret.z = round(index / (_threadDimX_ * _threadDimY_));
	ret.y = round((index - ret.z * _threadDimY_) / _threadDimX_);
	ret.x = index - _threadDimX_ * (ret.y + _threadDimY_ * ret.z);

	return ret;
}

vec2 _indexTo2DCoord_(float index) {
	vec2 ret;

	ret.y = mod(index, _W_) / _H_;
	ret.x = (round(index / _W_)) / _W_;

	return ret;
}

float _coordToIndex_(vec2 coord) {
	return (coord.x * _W_) + _W_ * (coord.y * _H_);
}

void main(float* a, float* b) {
    vec2 _vecId_ = get_global_id();
	float _id_ = _vecId_.x + _vecId_.y * _W_;

	float _thread_ = _indexTo3D_(_id_);

	float _threadZ_ =  _thread_.z;
	float _threadY_ =  _thread_.y;
	float _threadX_ =  _thread_.x;
// boilerplate end!!!

	float ret = a[_indexTo2DCoord_(_threadX_)] + b[_indexTo2DCoord_(_threadX_)];
	out_float = ret; // FROM RETURN
	return;
}
 */
<|endoftext|>


<commit_before>/**
 * Copyright 2010 Ajax.org B.V.
 *
 * This product includes software developed by
 * Ajax.org B.V. (http://www.ajax.org/).
 *
 * Author: Fabian Jaokbs <fabian@ajax.org>
 */

var assert = require("assert");
var BitBucket = require("./index").BitBucket;

module.exports = {

    setUp: function() {
        this.bitbucket = new BitBucket(true);
        this.repoApi = this.bitbucket.getRepoApi();
    },

//    "test: search repos" : function(finished) {
//        this.repoApi.search("php github api", function(err, repos) {
//            assert.ok(repos.length > 0);
//            assert.ok(repos[0].name !== undefined);
//            finished();
//        });
//    },
//
//    "test: show repository" : function(finished) {
//        this.repoApi.show("fjakobs", "qxoo", function(err, repo) {
//           assert.equal(repo.name, "qxoo");
//           finished();
//        });
//    },

    "test: get user repos" : function(finished) {
        this.repoApi.getUserRepos("fjakobstest", function(err, repos) {
            assert.equal(err, null);
            assert.ok(repos.length > 0);
            assert.ok(repos[0].name !== undefined);
            finished();
        });
    },
//
//    "test: get repo tags" : function(finished) {
//        this.repoApi.getRepoTags("fjakobs", "node", function(err, tags) {
//            assert.ok(tags["v0.1.0"] == "813b53938b40484f63e7324c030e33711f26a149");
//            finished();
//        });
//    },
//
//    "test: get repo languages" : function(finished) {
//        this.repoApi.getRepoLanguages("fjakobs", "node", function(err, languages) {
//            assert.ok(languages['C++'] != undefined);
//            finished();
//        });
//    },
//
//    "test: get repo branches" : function(finished) {
//        this.repoApi.getRepoBranches("fjakobs", "node", function(err, branches) {
//            assert.ok(branches["master"] !== undefined);
//            finished();
//        });
//    },
//
//    "test: get repo collaborators" : function(finished) {
//        this.repoApi.getRepoCollaborators("fjakobs", "node", function(err, collaborators) {
//            assert.ok(collaborators.length > 0);
//            assert.ok(!!~collaborators.toString().split(",").indexOf("fjakobs"));
//            finished();
//        });
//    },
//
//    "test: get repo contributors" : function(finished) {
//        this.repoApi.getRepoContributors("fjakobs", "node", function(err, contributors) {
//            assert.ok(contributors.length > 0);
//            assert.ok(contributors[0].login == "ry");
//            finished();
//        });
//    },
//
//    "test: get repo non-github contributors" : function(finished) {
//        this.repoApi.getRepoContributors("fjakobs", "node", true, function(err, contributors) {
//            assert.ok(contributors.length > 0);
//            assert.ok(contributors[0].login == "ry");
//            finished();
//        });
//    },
//
//    "test: get repo watchers" : function(finished) {
//        this.repoApi.getRepoWatchers("fjakobs", "node", function(err, watchers) {
//            assert.ok(watchers.length > 0);
//            assert.ok(!!~watchers.toString().split(",").indexOf("fjakobs"));
//            finished();
//        });
//    }

};

!module.parent && require("asyncjs").test.testcase(module.exports).exec();<commit_msg>Update bitbucket/repo_test.js<commit_after>/**
 * Copyright 2010 Ajax.org B.V.
 *
 * This product includes software developed by
 * Ajax.org B.V. (http://www.ajax.org/).
 *
 * Author: Fabian Jaokbs <fabian@ajax.org>
 */

var assert = require("assert");
var BitBucket = require("./index").BitBucket;

module.exports = {

    setUp: function() {
        this.bitbucket = new BitBucket(true);
        this.repoApi = this.bitbucket.getRepoApi();
    },

//    "test: search repos" : function(finished) {
//        this.repoApi.search("php github api", function(err, repos) {
//            assert.ok(repos.length > 0);
//            assert.ok(repos[0].name !== undefined);
//            finished();
//        });
//    },
//
//    "test: show repository" : function(finished) {
//        this.repoApi.show("fjakobs", "qxoo", function(err, repo) {
//           assert.equal(repo.name, "qxoo");
//           finished();
//        });
//    },

    "test: get user repos" : function(finished) {
        this.repoApi.getUserRepos("c9test01", function(err, repos) {
            assert.equal(err, null);
            assert.ok(repos.length > 0);
            assert.ok(repos[0].name !== undefined);
            finished();
        });
    },
//
//    "test: get repo tags" : function(finished) {
//        this.repoApi.getRepoTags("fjakobs", "node", function(err, tags) {
//            assert.ok(tags["v0.1.0"] == "813b53938b40484f63e7324c030e33711f26a149");
//            finished();
//        });
//    },
//
//    "test: get repo languages" : function(finished) {
//        this.repoApi.getRepoLanguages("fjakobs", "node", function(err, languages) {
//            assert.ok(languages['C++'] != undefined);
//            finished();
//        });
//    },
//
//    "test: get repo branches" : function(finished) {
//        this.repoApi.getRepoBranches("fjakobs", "node", function(err, branches) {
//            assert.ok(branches["master"] !== undefined);
//            finished();
//        });
//    },
//
//    "test: get repo collaborators" : function(finished) {
//        this.repoApi.getRepoCollaborators("fjakobs", "node", function(err, collaborators) {
//            assert.ok(collaborators.length > 0);
//            assert.ok(!!~collaborators.toString().split(",").indexOf("fjakobs"));
//            finished();
//        });
//    },
//
//    "test: get repo contributors" : function(finished) {
//        this.repoApi.getRepoContributors("fjakobs", "node", function(err, contributors) {
//            assert.ok(contributors.length > 0);
//            assert.ok(contributors[0].login == "ry");
//            finished();
//        });
//    },
//
//    "test: get repo non-github contributors" : function(finished) {
//        this.repoApi.getRepoContributors("fjakobs", "node", true, function(err, contributors) {
//            assert.ok(contributors.length > 0);
//            assert.ok(contributors[0].login == "ry");
//            finished();
//        });
//    },
//
//    "test: get repo watchers" : function(finished) {
//        this.repoApi.getRepoWatchers("fjakobs", "node", function(err, watchers) {
//            assert.ok(watchers.length > 0);
//            assert.ok(!!~watchers.toString().split(",").indexOf("fjakobs"));
//            finished();
//        });
//    }

};

!module.parent && require("asyncjs").test.testcase(module.exports).exec();<|endoftext|>


<commit_before>"use strict";
var Promise = require('es6-promise').Promise;
var Dispatcher = require('./dispatcher');
/* Evoflux.createAction({
*    add:function(data){
*      return {
*        action:"action_type",／／必须有action或者actionType
*        data:data
*      }
*    }
*  })
*/
var Action = function(){
  this.__moduleName__ = "";
};
Action.prototype.__create__ = function(actions){
  for (var a in actions) {
    if(actions.hasOwnProperty(a)){
      this[a] = function(){
        Promise.resolve(actions[a].apply(this,arguments))//payload
          .then(function (payload) {
            return new Promise(function(resolve, reject){
              if(!payload){
                return reject();
              }
              if(!payload.actionType && !payload.action){
                setTimeout(function(){throw new Error("action must have a actionType or action")},0);
                return reject();
              }
              var action = payload.actionType || payload.action;
              if(this.__moduleName__){
                payload.action = this.__moduleName__ + '.'+ action;
              }//增加action的namespace，避免一个文件同时访问多个store时的action命名冲突。例如：“todo.add”
              Dispatcher.dispatch(payload);//发布事件
              resolve();
            }.bind(this));

          }.bind(this));
      };

    }
  }//end for
  return this;
}
module.exports = Action;
<commit_msg>add mixins support to action<commit_after>"use strict";
var Promise = require('es6-promise').Promise;
var Dispatcher = require('./dispatcher');
var assign = require('object-assign');
/* Evoflux.createAction({
*    add:function(data){
*      return {
*        action:"action_type",／／必须有action或者actionType
*        data:data
*      }
*    }
*  })
*/
var Action = function(){
  this.__moduleName__ = "";
};
Action.prototype.__create__ = function(actions){
  for (var a in actions) {
    if(a === "mixins"){
      actions["mixins"].forEach(function(obj){
        if(typeof obj === "function"){
          assign(this, obj.prototype);
        }else{
          assign(this,obj);
        }
      }.bind(this))
      continue
    }// add mixins support
    if(actions.hasOwnProperty(a)){
      this[a] = function(){
        Promise.resolve(actions[a].apply(this,arguments))//payload
          .then(function (payload) {
            return new Promise(function(resolve, reject){
              if(!payload){
                return reject();
              }
              if(!payload.actionType && !payload.action){
                setTimeout(function(){throw new Error("action must have a actionType or action")},0);
                return reject();
              }
              var action = payload.actionType || payload.action;
              if(this.__moduleName__){
                payload.action = this.__moduleName__ + '.'+ action;
              }//增加action的namespace，避免一个文件同时访问多个store时的action命名冲突。例如：“todo.add”
              Dispatcher.dispatch(payload);//发布事件
              resolve();
            }.bind(this));

          }.bind(this));
      };

    }
  }//end for
  return this;
}
module.exports = Action;
<|endoftext|>


<commit_before>const hat = require('hat');
const Dispatcher = require('./dispatcher');
const Tree = require('./tree');

const SUBS = ['before', 'error'];

class Action {

  static create(handler, opts = {}) {
    opts = Object.assign({dispatcher: Dispatcher.main, type: Action}, opts);

    const ActionType = opts.type;
    const action = new ActionType(handler, opts.dispatcher);

    return action.wrapper;
  }

  constructor(handler = null, dispatcher = Dispatcher.main, isSubAction = false) {
    this.dispatcher = dispatcher;
    this.actionType = hat();
    this.handler = handler;
    this.wrapper = this.buildWrapper();

    if (!isSubAction) SUBS.forEach(name => this.attachSubAction(name));
  }

  attachSubAction(name) {
    const action = new Action(null, this.dispatcher, true);

    this[name] = action;
    this.wrapper[name] = action.wrapper;
  }

  buildWrapper() {
    const wrapper = (...argv) => this.callHandler(...argv);

    wrapper.action = this;
    wrapper.subscribe = listener => this.dispatcher.subscribe(this, listener);
    wrapper.unsubscribe = listener => this.dispatcher.unsubscribe(this, listener);

    return wrapper;
  }

  trigger(data) {
    this.dispatcher.trigger(this, data);
  }

  callHandler(...argv) {
    if (!!this.before) this.before.trigger(...argv);

    const res = this.handler === null ? null : this.handler.call(this, ...argv);
    const promise = (res instanceof Promise) ? res : new Promise(resolve => resolve(res));

    promise
      .then(data => this.trigger(data))
      .catch(error => this.error.trigger(error));

    return promise;
  }

}

class ActionTree extends Tree {

  _register(name, handler) {
    if (!!handler && !!handler.action && handler.action instanceof Action) {
      this[name] = handler;
    } else {
      this[name] = Action.create(handler);
    }

    this._leafs.add(name);

    return this[name];
  }

}

module.exports = {Action, ActionTree};
<commit_msg>action.before sends handler args<commit_after>const hat = require('hat');
const Dispatcher = require('./dispatcher');
const Tree = require('./tree');

const SUBS = ['before', 'error'];

class Action {

  static create(handler, opts = {}) {
    opts = Object.assign({dispatcher: Dispatcher.main, type: Action}, opts);

    const ActionType = opts.type;
    const action = new ActionType(handler, opts.dispatcher);

    return action.wrapper;
  }

  constructor(handler = null, dispatcher = Dispatcher.main, isSubAction = false) {
    this.dispatcher = dispatcher;
    this.actionType = hat();
    this.handler = handler;
    this.wrapper = this.buildWrapper();

    if (!isSubAction) SUBS.forEach(name => this.attachSubAction(name));
  }

  attachSubAction(name) {
    const action = new Action(null, this.dispatcher, true);

    this[name] = action;
    this.wrapper[name] = action.wrapper;
  }

  buildWrapper() {
    const wrapper = (...args) => this.callHandler(...args);

    wrapper.action = this;
    wrapper.subscribe = listener => this.dispatcher.subscribe(this, listener);
    wrapper.unsubscribe = listener => this.dispatcher.unsubscribe(this, listener);

    return wrapper;
  }

  trigger(data) {
    this.dispatcher.trigger(this, data);
  }

  callHandler(...args) {
    if (!!this.before) this.before.trigger({args});

    const res = this.handler === null ? null : this.handler.call(this, ...args);
    const promise = (res instanceof Promise) ? res : new Promise(resolve => resolve(res));

    promise
      .then(data => this.trigger(data))
      .catch(error => this.error.trigger(error));

    return promise;
  }

}

class ActionTree extends Tree {

  _register(name, handler) {
    if (!!handler && !!handler.action && handler.action instanceof Action) {
      this[name] = handler;
    } else {
      this[name] = Action.create(handler);
    }

    this._leafs.add(name);

    return this[name];
  }

}

module.exports = {Action, ActionTree};
<|endoftext|>


<commit_before>'use strict';
const path = require('path');
const chalk = require('chalk');

/** @type {string[]} */
const blockMany = [
  'chrome',
  'chrome_android',
  'edge',
  'edge_mobile',
  'firefox',
  'firefox_android',
  'ie',
  'opera',
  'opera_android',
  'safari',
  'safari_ios',
  'webview_android'
];

/** @type {Record<string, string[]>} */
const blockList = {
  api: [],
  css: ['ie'],
  html: [],
  http: [],
  svg: [],
  javascript: [],
  mathml: blockMany,
  webdriver: blockMany.concat(['samsunginternet_android']),
  webextensions: [],
  xpath: [],
  xslt: []
};

/**
 * @param {SupportBlock} supportData
 * @param {string[]} blockList
 * @param {string} relPath
 * @param {{error:function(...unknown):void}} logger
 */
function checkRealValues(supportData, blockList, relPath, logger) {
  let hasErrors = false;
  for (const browser of blockList) {
    /** @type {SimpleSupportStatement[]} */
    const supportStatements = [];
    if (Array.isArray(supportData[browser])) {
      Array.prototype.push.apply(supportStatements, supportData[browser]);
    } else {
      supportStatements.push(supportData[browser]);
    }

    for (const statement of supportStatements) {
      if (statement === undefined) {
        logger.error(chalk`{red.bold ${browser}} {red must be defined for} {red.bold ${relPath}}`);
          hasErrors = true;
      } else {
        if ([true, null].includes(statement.version_added)) {
          logger.error(chalk`{red.bold ${relPath}} {red -} {red.bold ${browser}} {red no longer accepts} {red.bold ${statement.version_added}} {red as a value}`);
          hasErrors = true;
        }
        if ([true, null].includes(statement.version_removed)) {
          logger.error(chalk`{red.bold ${relPath}} {red -} {red.bold ${browser}} {red no longer accepts} {red.bold ${statement.version_removed}} {red as a value}`);
          hasErrors = true;
        }
      }
    }
  }

  return hasErrors;
}

/**
 * @param {string} filename
 */
function testRealValues(filename) {
  const relativePath = path.relative(path.resolve(__dirname, '..'), filename);
  const category = relativePath.includes(path.sep) && relativePath.split(path.sep)[0];
  /** @type {Identifier} */
  const data = require(filename);

  /** @type {string[]} */
  const errors = [];
  const logger = {
    /** @param {...unknown} message */
    error: (...message) => {
      errors.push(message.join(' '));
    },
  };

  /**
   * @param {Identifier} data
   * @param {string} relPath
   */
  function findSupport(data, relPath) {
    for (const prop in data) {
      if (prop === '__compat' && data[prop].support) {
        if (blockList[category] && blockList[category].length > 0) checkRealValues(data[prop].support, blockList[category], relPath, logger);
      }
      const sub = data[prop];
      if (typeof sub === 'object') {
        findSupport(sub, relPath ? `${relPath}.${prop}` : `${prop}`);
      }
    }
  }
  findSupport(data);

  if (errors.length) {
    console.error(chalk`{red   Real values – }{red.bold ${errors.length}}{red  ${errors.length === 1 ? 'error' : 'errors'}:}`);
    for (const error of errors) {
      console.error(`    ${error}`);
    }
    return true;
  }
  return false;
}

module.exports = testRealValues;
<commit_msg>Enforce real Firefox values for javascript/ (#4176)<commit_after>'use strict';
const path = require('path');
const chalk = require('chalk');

/** @type {string[]} */
const blockMany = [
  'chrome',
  'chrome_android',
  'edge',
  'edge_mobile',
  'firefox',
  'firefox_android',
  'ie',
  'opera',
  'opera_android',
  'safari',
  'safari_ios',
  'webview_android'
];

/** @type {Record<string, string[]>} */
const blockList = {
  api: [],
  css: ['ie'],
  html: [],
  http: [],
  svg: [],
  javascript: ['firefox', 'firefox_android'],
  mathml: blockMany,
  webdriver: blockMany.concat(['samsunginternet_android']),
  webextensions: [],
  xpath: [],
  xslt: []
};

/**
 * @param {SupportBlock} supportData
 * @param {string[]} blockList
 * @param {string} relPath
 * @param {{error:function(...unknown):void}} logger
 */
function checkRealValues(supportData, blockList, relPath, logger) {
  let hasErrors = false;
  for (const browser of blockList) {
    /** @type {SimpleSupportStatement[]} */
    const supportStatements = [];
    if (Array.isArray(supportData[browser])) {
      Array.prototype.push.apply(supportStatements, supportData[browser]);
    } else {
      supportStatements.push(supportData[browser]);
    }

    for (const statement of supportStatements) {
      if (statement === undefined) {
        logger.error(chalk`{red.bold ${browser}} {red must be defined for} {red.bold ${relPath}}`);
          hasErrors = true;
      } else {
        if ([true, null].includes(statement.version_added)) {
          logger.error(chalk`{red.bold ${relPath}} {red -} {red.bold ${browser}} {red no longer accepts} {red.bold ${statement.version_added}} {red as a value}`);
          hasErrors = true;
        }
        if ([true, null].includes(statement.version_removed)) {
          logger.error(chalk`{red.bold ${relPath}} {red -} {red.bold ${browser}} {red no longer accepts} {red.bold ${statement.version_removed}} {red as a value}`);
          hasErrors = true;
        }
      }
    }
  }

  return hasErrors;
}

/**
 * @param {string} filename
 */
function testRealValues(filename) {
  const relativePath = path.relative(path.resolve(__dirname, '..'), filename);
  const category = relativePath.includes(path.sep) && relativePath.split(path.sep)[0];
  /** @type {Identifier} */
  const data = require(filename);

  /** @type {string[]} */
  const errors = [];
  const logger = {
    /** @param {...unknown} message */
    error: (...message) => {
      errors.push(message.join(' '));
    },
  };

  /**
   * @param {Identifier} data
   * @param {string} relPath
   */
  function findSupport(data, relPath) {
    for (const prop in data) {
      if (prop === '__compat' && data[prop].support) {
        if (blockList[category] && blockList[category].length > 0) checkRealValues(data[prop].support, blockList[category], relPath, logger);
      }
      const sub = data[prop];
      if (typeof sub === 'object') {
        findSupport(sub, relPath ? `${relPath}.${prop}` : `${prop}`);
      }
    }
  }
  findSupport(data);

  if (errors.length) {
    console.error(chalk`{red   Real values – }{red.bold ${errors.length}}{red  ${errors.length === 1 ? 'error' : 'errors'}:}`);
    for (const error of errors) {
      console.error(`    ${error}`);
    }
    return true;
  }
  return false;
}

module.exports = testRealValues;
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version).to.exist;
        expect(npmPackage.version).to.exist;

        if (!expect(ioPackage.common.version).to.be.equal(npmPackage.version)) {
            console.log('ERROR: Version numbers in package.json and io-package.json differ!!');
        }

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
        }

        expect(ioPackage.common.authors).to.exist;
        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length).to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0]).to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors).to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('Testing for set authors field in io-package skipped because template adapter');
        }
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        expect(fileContentReadme.indexOf('## License'), 'The README.md needs to have a section ## License').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## Changelog').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## License').to.be.below(fileContentReadme.indexOf('## License'));
        done();
    });
});
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        expect(fileContentReadme.indexOf('## License'), 'The README.md needs to have a section ## License').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## Changelog').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## License').to.be.below(fileContentReadme.indexOf('## License'));
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should have a section ## License');
            console.log();
        }
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        done();
    });
});
<|endoftext|>


<commit_before>import Dexie, {liveQuery, rangesOverlap, RangeSet} from 'dexie';
import {module, stop, start, asyncTest, equal, ok} from 'QUnit';
import {resetDatabase, supports, promisedTest} from './dexie-unittest-utils';
import { deepEqual } from './tests-table';

function rangeSet(ranges) {
  const set = new RangeSet();
  for (const range of ranges) {
    set.add({from: range[0], to: range[range.length-1]});
  }
  return set;
}

function hasKey(set, key) {
  return rangesOverlap(set, new RangeSet(key))
}

const db = new Dexie("TestLiveQuery");
db.version(2).stores({
    items: "id, name",
    foo: "++id"
});

db.on('populate', ()=> {
  db.items.bulkAdd([
      {id: 1},
      {id: 2},
      {id: 3}
  ]);
});

class Signal {
  promise = new Promise(resolve => this.resolve = resolve);
}

module("live-query", {
  setup: function () {
      stop();
      resetDatabase(db).catch(function (e) {
          ok(false, "Error resetting database: " + e.stack);
      }).finally(start);
  },
  teardown: function () {
  }
});

promisedTest("txcommitted event", async ()=>{
  let signal = new Signal();
  let os = {};
  function txCommitted(observabilitySet) {
    Dexie.extendObservabilitySet(os, observabilitySet);
    signal.resolve(observabilitySet);
  }
  await db.open();
  Dexie.on('txcommitted', txCommitted);
  await db.transaction('rw', db.items, db.foo, async ()=>{
    await db.items.add({id: 4, name: "aiwo1"});
    await db.items.add({id: 7, name: "kjlj"});
    await db.foo.add({name: "jkll"});
    await db.items.update(1, {name: "A"});
  });
  while (!os.TestLiveQuery || !os.TestLiveQuery.items || !hasKey(os.TestLiveQuery.items.keys, 4)) {
    // When Dexie.Observable is active, we might see intermediate transactions taking place
    // before our transaction.
    signal = new Signal();
    await signal.promise;
    console.log("got new os:", os);
  }
  ok(!!os.TestLiveQuery, "Got changes in our table name TestLiveQuery");
  let itemsChanges = os.TestLiveQuery.items;
  ok(itemsChanges, "Got changes for items table");
  deepEqual(itemsChanges.keys, rangeSet([[4], [7], [1]]), "Item changes on concattenated keys");
  deepEqual(itemsChanges.indexes, {name: rangeSet([["aiwo1"],["kjlj"],["A"]])}, "Index changes present");

  // Foo changes (auto-incremented id)
  let fooChanges = os.TestLiveQuery.foo;
  ok(fooChanges, "Got changes for foo table");

  os = {};
  let fooIds = await db.foo.toCollection().primaryKeys();
  await db.transaction('rw', db.items, db.foo, async ()=>{
    await db.items.update(4, {name: "aiwo2"});
    await db.foo.where('id').between(0, 1000).delete();
  });
  while (!os.TestLiveQuery || !os.TestLiveQuery.items || !hasKey(os.TestLiveQuery.items.keys, 4)) {
    // When Dexie.Observable is active, we might see intermediate transactions taking place
    // before our transaction.
    signal = new Signal();
    await signal.promise;
  }
  itemsChanges = os.TestLiveQuery.items;
  deepEqual(itemsChanges.keys, rangeSet([[4]]), "Item 4 was updated");
  deepEqual(itemsChanges.indexes, {name: rangeSet([["aiwo1"], ["aiwo2"]])});

  fooChanges = os.TestLiveQuery.foo;
  ok(!!fooChanges, "Foo table changed");
  if (hasKey(fooChanges.keys, 0) && hasKey(fooChanges.keys, 1000)) {
    // Without addons:
    deepEqual(fooChanges.keys, rangeSet([[0, 1000]]), "Got a range update of foo keys 0..1000");
  } else {
    // With hooks / addons or browser workarounds:
    deepEqual(fooChanges, rangeSet(fooIds.map(id => [id])), "Got individual delete updates of foo keys ", fooIds.join(','));
  }

  Dexie.on('txcommitted').unsubscribe(txCommitted);
});

promisedTest("subscribe to range", async ()=> {
  let signal = new Signal();
  let subscription = liveQuery(()=>db.items.toArray()).subscribe(result => {
    signal.resolve(result);
  });
  let result = await signal.promise;
  deepEqual(result, [{id:1},{id:2},{id:3}], "First callback should give initally populated content");
  signal = new Signal();
  db.items.add({id:-1});
  result = await signal.promise;
  deepEqual(result, [{id:-1},{id:1},{id:2},{id:3}], "2nd callback should give updated content");

  signal = new Signal();
  db.items.delete(2);
  result = await signal.promise;
  deepEqual(result, [{id:-1},{id:1},{id:3}], "3rd callback should wake up when deletion was made");
  subscription.unsubscribe();
});

promisedTest("subscribe to keys", async ()=>{
  let signal1 = new Signal(), signal2 = new Signal();
  let count1 = 0, count2 = 0;
  const debugTxCommitted = set => console.debug("txcommitted", set);
  Dexie.on('txcommitted', debugTxCommitted);
  let sub1 = liveQuery(()=>db.items.get(1)).subscribe(result => {
    ++count1;
    signal1.resolve(result);
  });
  let res1 = await signal1.promise;
  equal(res1.id, 1, "First result for ID 1 ok");
  equal(count1, 1, "Callback called once");
  let sub2 = liveQuery(()=>db.items.get(2)).subscribe(result => {
    ++count2;
    signal2.resolve(result);
  });
  let res2 = await signal2.promise;
  equal(res2.id, 2, "2nd result for ID 2 ok");
  equal(count2, 1, "2nd callback called once");
  equal(count1, 1, "First callback wasn't called again");

  // Now mutate using update - verify listeners don't wake up on other than the keys the subscribe
  signal1 = new Signal();
  signal2 = new Signal();
  await db.items.update(1, {name: "one"});
  ok(true, "Could update item 1");
  res1 = await signal1.promise;
  equal(count1, 2, "First should have been called 2 times now");
  equal(count2, 1, "2nd callback should still only have been called once");
  equal(res1.name, "one", "We got the updated value from the expression");
  await db.items.update(2, {name: "two"});
  res2 = await signal2.promise;
  equal(count1, 2, "First should have been called 2 times now");
  equal(count2, 2, "2nd callback should have been called twice also");
  equal(res2.name, "two", "We got the updated value from the 2nd expression");

  // Now mutate using delete
  signal1 = new Signal();
  signal2 = new Signal();
  await db.items.delete(1);
  res1 = await signal1.promise;
  equal(count1, 3, "First should have been called 3 times now");
  equal(count2, 2, "2nd callback should still only have been called twice");
  ok(res1 === undefined, "The updated result of db.items.get(1) should return undefined after the deletion");

  await db.items.delete(2);
  res2 = await signal2.promise;
  equal(count1, 3, "First should still have been called 3 times");
  equal(count2, 3, "2nd callback should have been called 3 times also now");
  ok(res2 === undefined, "The updated result of db.items.get(2) should return undefined after the deletion");

  // Verify that no more callbacks are called after unsubscribing
  sub1.unsubscribe();
  sub2.unsubscribe();
  await db.items.update(1, {name: "fljkds"});
  equal(count1, 3, "No more calls after having unsubscribed");
  await db.items.update(1, {name: "sfdfs"});
  equal(count1, 3, "Just double-checking - no more calls after having unsubscribed");
});

promisedTest("subscribe and error occur", async ()=> {
  let signal = new Signal();
  let subscription = liveQuery(
    ()=>db.items.get(NaN) // NaN is not a valid key
  ).subscribe({
    next: result => signal.resolve("success"),
    error: result => signal.resolve("error"),
    complete: ()=> signal.resolve("complete")
  });
  ok(!subscription.closed, "Subscription should not yet be closed");
  let result = await signal.promise;
  equal(result, "error", "The observable's error callback should have been called");
  ok(subscription.closed, "Subscription should have been closed after error has occurred");
  subscription.unsubscribe();
});
<commit_msg>Corrected unit test when addons is active<commit_after>import Dexie, {liveQuery, rangesOverlap, RangeSet} from 'dexie';
import {module, stop, start, asyncTest, equal, ok} from 'QUnit';
import {resetDatabase, supports, promisedTest} from './dexie-unittest-utils';
import { deepEqual } from './tests-table';

function rangeSet(ranges) {
  const set = new RangeSet();
  for (const range of ranges) {
    set.add({from: range[0], to: range[range.length-1]});
  }
  return set;
}

function hasKey(set, key) {
  return rangesOverlap(set, new RangeSet(key))
}

const db = new Dexie("TestLiveQuery");
db.version(2).stores({
    items: "id, name",
    foo: "++id"
});

db.on('populate', ()=> {
  db.items.bulkAdd([
      {id: 1},
      {id: 2},
      {id: 3}
  ]);
});

class Signal {
  promise = new Promise(resolve => this.resolve = resolve);
}

module("live-query", {
  setup: function () {
      stop();
      resetDatabase(db).catch(function (e) {
          ok(false, "Error resetting database: " + e.stack);
      }).finally(start);
  },
  teardown: function () {
  }
});

promisedTest("txcommitted event", async ()=>{
  let signal = new Signal();
  let os = {};
  function txCommitted(observabilitySet) {
    Dexie.extendObservabilitySet(os, observabilitySet);
    signal.resolve(observabilitySet);
  }
  await db.open();
  Dexie.on('txcommitted', txCommitted);
  await db.transaction('rw', db.items, db.foo, async ()=>{
    await db.items.add({id: 4, name: "aiwo1"});
    await db.items.add({id: 7, name: "kjlj"});
    await db.foo.add({name: "jkll"});
    await db.items.update(1, {name: "A"});
  });
  while (!os.TestLiveQuery || !os.TestLiveQuery.items || !hasKey(os.TestLiveQuery.items.keys, 4)) {
    // When Dexie.Observable is active, we might see intermediate transactions taking place
    // before our transaction.
    signal = new Signal();
    await signal.promise;
    console.log("got new os:", os);
  }
  ok(!!os.TestLiveQuery, "Got changes in our table name TestLiveQuery");
  let itemsChanges = os.TestLiveQuery.items;
  ok(itemsChanges, "Got changes for items table");
  deepEqual(itemsChanges.keys, rangeSet([[4], [7], [1]]), "Item changes on concattenated keys");
  deepEqual(itemsChanges.indexes, {name: rangeSet([["aiwo1"],["kjlj"],["A"]])}, "Index changes present");

  // Foo changes (auto-incremented id)
  let fooChanges = os.TestLiveQuery.foo;
  ok(fooChanges, "Got changes for foo table");

  os = {};
  let fooIds = await db.foo.toCollection().primaryKeys();
  await db.transaction('rw', db.items, db.foo, async ()=>{
    await db.items.update(4, {name: "aiwo2"});
    await db.foo.where('id').between(0, 1000).delete();
  });
  while (!os.TestLiveQuery || !os.TestLiveQuery.items || !hasKey(os.TestLiveQuery.items.keys, 4)) {
    // When Dexie.Observable is active, we might see intermediate transactions taking place
    // before our transaction.
    signal = new Signal();
    await signal.promise;
  }
  itemsChanges = os.TestLiveQuery.items;
  deepEqual(itemsChanges.keys, rangeSet([[4]]), "Item 4 was updated");
  deepEqual(itemsChanges.indexes, {name: rangeSet([["aiwo1"], ["aiwo2"]])});

  fooChanges = os.TestLiveQuery.foo;
  ok(!!fooChanges, "Foo table changed");
  if (hasKey(fooChanges.keys, 0) && hasKey(fooChanges.keys, 1000)) {
    // Without addons:
    deepEqual(fooChanges.keys, rangeSet([[0, 1000]]), "Got a range update of foo keys 0..1000");
  } else {
    // With hooks / addons or browser workarounds:
    deepEqual(fooChanges.keys, rangeSet(fooIds.map(id => [id])), "Got individual delete updates of foo keys ", fooIds.join(','));
  }

  Dexie.on('txcommitted').unsubscribe(txCommitted);
});

promisedTest("subscribe to range", async ()=> {
  let signal = new Signal();
  let subscription = liveQuery(()=>db.items.toArray()).subscribe(result => {
    signal.resolve(result);
  });
  let result = await signal.promise;
  deepEqual(result, [{id:1},{id:2},{id:3}], "First callback should give initally populated content");
  signal = new Signal();
  db.items.add({id:-1});
  result = await signal.promise;
  deepEqual(result, [{id:-1},{id:1},{id:2},{id:3}], "2nd callback should give updated content");

  signal = new Signal();
  db.items.delete(2);
  result = await signal.promise;
  deepEqual(result, [{id:-1},{id:1},{id:3}], "3rd callback should wake up when deletion was made");
  subscription.unsubscribe();
});

promisedTest("subscribe to keys", async ()=>{
  let signal1 = new Signal(), signal2 = new Signal();
  let count1 = 0, count2 = 0;
  const debugTxCommitted = set => console.debug("txcommitted", set);
  Dexie.on('txcommitted', debugTxCommitted);
  let sub1 = liveQuery(()=>db.items.get(1)).subscribe(result => {
    ++count1;
    signal1.resolve(result);
  });
  let res1 = await signal1.promise;
  equal(res1.id, 1, "First result for ID 1 ok");
  equal(count1, 1, "Callback called once");
  let sub2 = liveQuery(()=>db.items.get(2)).subscribe(result => {
    ++count2;
    signal2.resolve(result);
  });
  let res2 = await signal2.promise;
  equal(res2.id, 2, "2nd result for ID 2 ok");
  equal(count2, 1, "2nd callback called once");
  equal(count1, 1, "First callback wasn't called again");

  // Now mutate using update - verify listeners don't wake up on other than the keys the subscribe
  signal1 = new Signal();
  signal2 = new Signal();
  await db.items.update(1, {name: "one"});
  ok(true, "Could update item 1");
  res1 = await signal1.promise;
  equal(count1, 2, "First should have been called 2 times now");
  equal(count2, 1, "2nd callback should still only have been called once");
  equal(res1.name, "one", "We got the updated value from the expression");
  await db.items.update(2, {name: "two"});
  res2 = await signal2.promise;
  equal(count1, 2, "First should have been called 2 times now");
  equal(count2, 2, "2nd callback should have been called twice also");
  equal(res2.name, "two", "We got the updated value from the 2nd expression");

  // Now mutate using delete
  signal1 = new Signal();
  signal2 = new Signal();
  await db.items.delete(1);
  res1 = await signal1.promise;
  equal(count1, 3, "First should have been called 3 times now");
  equal(count2, 2, "2nd callback should still only have been called twice");
  ok(res1 === undefined, "The updated result of db.items.get(1) should return undefined after the deletion");

  await db.items.delete(2);
  res2 = await signal2.promise;
  equal(count1, 3, "First should still have been called 3 times");
  equal(count2, 3, "2nd callback should have been called 3 times also now");
  ok(res2 === undefined, "The updated result of db.items.get(2) should return undefined after the deletion");

  // Verify that no more callbacks are called after unsubscribing
  sub1.unsubscribe();
  sub2.unsubscribe();
  await db.items.update(1, {name: "fljkds"});
  equal(count1, 3, "No more calls after having unsubscribed");
  await db.items.update(1, {name: "sfdfs"});
  equal(count1, 3, "Just double-checking - no more calls after having unsubscribed");
});

promisedTest("subscribe and error occur", async ()=> {
  let signal = new Signal();
  let subscription = liveQuery(
    ()=>db.items.get(NaN) // NaN is not a valid key
  ).subscribe({
    next: result => signal.resolve("success"),
    error: result => signal.resolve("error"),
    complete: ()=> signal.resolve("complete")
  });
  ok(!subscription.closed, "Subscription should not yet be closed");
  let result = await signal.promise;
  equal(result, "error", "The observable's error callback should have been called");
  ok(subscription.closed, "Subscription should have been closed after error has occurred");
  subscription.unsubscribe();
});
<|endoftext|>


<commit_before>import Vue from 'vue';
import TextEditor from '../src/TextEditor.vue';
import expect from 'expect';

describe("<text-editor>", (done) => {
	beforeEach(() => {
		this.vm = new Vue({
			data: { hi: { text: "hi" } },
			template: '
<text-editor ref="texteditor" v-model="hi"></text-editor>
',
			components: { 'text-editor': TextEditor }
		}).$mount();
	});

	afterEach(() => {
		delete this.vm;
	})

	it("should have the v-model value as input", () => {
		expect(this.vm.$el.querySelector("input").value).toBe(this.vm.hi.text);
	});

	it("should have a save and a cancel button", () => {
		let buttons = this.vm.$el.querySelectorAll("button");

		for (let i = 0; i < buttons.length; i++) {
			expect(buttons[`${i}`].innerText).toMatch(/(Save|Cancel)/);
		}
	});

	it("should save the value upon clicking 'Save'", (done) => {
		const initialValue = this.vm.$data.hi.text;
		const targetValue = "changed value";

		// Set the input to a different value
		this.vm.$refs.texteditor.value.text = targetValue;

		Vue.nextTick(() => {
			// Initial value should be saved in "text"
			expect(this.vm.$refs.texteditor.text).toEqual(initialValue);

			// Bindings should be updated with the new value
			expect(this.vm.$data.hi.text).toNotEqual(initialValue);
			expect(this.vm.$refs.texteditor.value.text).toNotEqual(initialValue);

			// "click" on save
			this.vm.$refs.texteditor.save();

			// Data bindings should be updated
			expect(this.vm.$data.hi.text).toEqual(targetValue);
			expect(this.vm.$refs.texteditor.value.text).toEqual(targetValue);

			done();
		});
	});

	it("should set the initial value back upon clicking 'Cancel'", (done) => {
		const initialValue = this.vm.$data.hi.text;

		// Set the input to a different value
		this.vm.$refs.texteditor.value.text = "changed value";

		Vue.nextTick(() => {
			// Initial value should be saved in "text"
			expect(this.vm.$refs.texteditor.text).toEqual(initialValue);

			// Bindings should be updated with the new value
			expect(this.vm.$data.hi.text).toNotEqual(initialValue);
			expect(this.vm.$refs.texteditor.value.text).toNotEqual(initialValue);

			// "click" on cancel
			this.vm.$refs.texteditor.cancel();

			// Data bindings should be back to normal
			expect(this.vm.$data.hi.text).toEqual(initialValue);
			expect(this.vm.$refs.texteditor.value.text).toEqual(initialValue);

			done();
		});
	});
});
<commit_msg>Complete unit tests for TextEditor<commit_after>import Vue from 'vue';
import TextEditor from '../src/TextEditor.vue';
import expect, {spyOn} from 'expect';

describe("<text-editor>", (done) => {
	beforeEach(() => {
		this.vm = new Vue({
			data: { hi: { text: "hi" }, hidecalled: false },
			template: '
<text-editor ref="texteditor" v-model="hi" @hide="hide"></text-editor>
',
			components: { 'text-editor': TextEditor },
			methods: {
				hide: function() {
					// Spys don't work across nextTick so we have to be a bit
					// creative.
					this.hidecalled = true;
				}
			}
		}).$mount();
	});

	afterEach(() => {
		delete this.vm;
	});

	it("should have an input field", () => {
		expect(this.vm.$el.querySelector("input")).toNotBe(null);
	});

	it("should have the v-model value as input", () => {
		expect(this.vm.$el.querySelector("input").value).toBe(this.vm.hi.text);
	});

	it("should have a save and a cancel button", () => {
		let buttons = this.vm.$el.querySelectorAll("button");

		for (let i = 0; i < buttons.length; i++) {
			expect(buttons[`${i}`].innerText).toMatch(/(Save|Cancel)/);
		}
	});

	it("should save the value upon clicking 'Save'", (done) => {
		const initialValue = this.vm.$data.hi.text;
		const targetValue = "changed value";

		// Set the input to a different value
		this.vm.$refs.texteditor.value.text = targetValue;

		Vue.nextTick(() => {
			// Initial value should be saved in "text"
			expect(this.vm.$refs.texteditor.text).toEqual(initialValue);

			// Bindings should be updated with the new value
			expect(this.vm.$data.hi.text).toNotEqual(initialValue);
			expect(this.vm.$refs.texteditor.value.text).toNotEqual(initialValue);

			// "click" on save
			this.vm.$refs.texteditor.save();

			// Data bindings should be updated
			expect(this.vm.$data.hi.text).toEqual(targetValue);
			expect(this.vm.$refs.texteditor.value.text).toEqual(targetValue);

			done();
		});
	});

	it("should set the initial value back upon clicking 'Cancel'", (done) => {
		const initialValue = this.vm.$data.hi.text;

		// Set the input to a different value
		this.vm.$refs.texteditor.value.text = "changed value";

		Vue.nextTick(() => {
			// Initial value should be saved in "text"
			expect(this.vm.$refs.texteditor.text).toEqual(initialValue);

			// Bindings should be updated with the new value
			expect(this.vm.$data.hi.text).toNotEqual(initialValue);
			expect(this.vm.$refs.texteditor.value.text).toNotEqual(initialValue);

			// "click" on cancel
			this.vm.$refs.texteditor.cancel();

			// Data bindings should be back to normal
			expect(this.vm.$data.hi.text).toEqual(initialValue);
			expect(this.vm.$refs.texteditor.value.text).toEqual(initialValue);

			done();
		});
	});

	it("should call the 'hide' callback when clicking on cancel", (done) => {
		var hideSpy = spyOn(this.vm, 'hide');

		expect(this.vm.hidecalled).toBe(false);

		// "click" on cancel
		this.vm.$refs.texteditor.cancel();

		Vue.nextTick(() => {
			expect(this.vm.hidecalled).toBe(true);
			done();
		});
	});

	it("should call the 'hide' callback when clicking on save", (done) => {
		var hideSpy = spyOn(this.vm, 'hide');

		expect(this.vm.hidecalled).toBe(false);

		// "click" on save
		this.vm.$refs.texteditor.save();

		Vue.nextTick(() => {
			expect(this.vm.hidecalled).toBe(true);
			done();
		});
	});
});
<|endoftext|>


<commit_before>/*global window, Boot, test, ok, equal */
/*jslint windows: true*/
(function () {

    "use strict";

    test("Environment", function () {
        ok(window.Boot);
        ok(window.Boot.cookie);
    });

    test("Set a cookie.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST1", "CREATE"));
    });

    test("Retrieve a cookie.", function () {
        Boot.cookie("BOOTCOOKIETEST2", "CREATE");
        equal(Boot.cookie("BOOTCOOKIETEST2"), "CREATE");
    });

    test("Update a cookie.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST3", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST3"), "CREATE");
        ok(Boot.cookie("BOOTCOOKIETEST3", "UPDATE"));
        equal(Boot.cookie("BOOTCOOKIETEST3"), "UPDATE");
    });

    test("Delete cookies.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST4", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST4"), "CREATE");
        ok(Boot.cookie("BOOTCOOKIETEST4", null));
        equal(Boot.cookie("BOOTCOOKIETEST4"), null);
        ok(Boot.cookie("BOOTCOOKIETEST5", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST5"), "CREATE");
        ok(Boot.cookie("BOOTCOOKIETEST5", ""));
        equal(Boot.cookie("BOOTCOOKIETEST5"), null);
    });

    test("Cookie dump object.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST6", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST6"), "CREATE");
        var dump = Boot.cookie();
        equal(dump.BOOTCOOKIETEST6, "CREATE");
    });
}());
<commit_msg>Added module to Boot.cookie unit test.<commit_after>/*global window, Boot, test, ok, equal */
/*jslint windows: true*/
(function () {

    "use strict";

    module("Boot.cookie");

    test("Environment", function () {
        ok(window.Boot);
        ok(window.Boot.cookie);
    });

    test("Set a cookie.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST1", "CREATE"));
    });

    test("Retrieve a cookie.", function () {
        Boot.cookie("BOOTCOOKIETEST2", "CREATE");
        equal(Boot.cookie("BOOTCOOKIETEST2"), "CREATE");
    });

    test("Update a cookie.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST3", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST3"), "CREATE");
        ok(Boot.cookie("BOOTCOOKIETEST3", "UPDATE"));
        equal(Boot.cookie("BOOTCOOKIETEST3"), "UPDATE");
    });

    test("Delete cookies.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST4", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST4"), "CREATE");
        ok(Boot.cookie("BOOTCOOKIETEST4", null));
        equal(Boot.cookie("BOOTCOOKIETEST4"), null);
        ok(Boot.cookie("BOOTCOOKIETEST5", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST5"), "CREATE");
        ok(Boot.cookie("BOOTCOOKIETEST5", ""));
        equal(Boot.cookie("BOOTCOOKIETEST5"), null);
    });

    test("Cookie dump object.", function () {
        ok(Boot.cookie("BOOTCOOKIETEST6", "CREATE"));
        equal(Boot.cookie("BOOTCOOKIETEST6"), "CREATE");
        var dump = Boot.cookie();
        equal(dump.BOOTCOOKIETEST6, "CREATE");
    });
}());
<|endoftext|>