<commit_before>import React, { Component } from 'react';
import { withAuth, withRouter, styled, Link, withLang } from 'olymp';
import { Menu, Icon, Tooltip, Popover } from 'antd';
import tinycolor from 'tinycolor2';
import CmsButton from './button';

const VerticalMenu = styled(({ deviceWidth, theme }) => ({
  overflow: 'visible',
  display: 'flex',
  flexDirection: 'column',
  boxShadow: 'inset -10px 0 3px -9px hsla(0,0%,0%,.2)!important',
  background: `linear-gradient(0deg, ${theme.colorStart || tinycolor(theme.color).darken(6).spin(-6).toRgbString()}, ${theme.colorEnd || tinycolor(theme.color).lighten(6).spin(12).toRgbString()})`,
  '> li:nth-last-child(4)': {
    marginTop: 'auto',
  },
  '> li.ant-menu-item': {
    paddingX: 14,
    //padding: 5,
    //height: 'initial',
    textAlign: 'center',
    '> a': {
      // backgroundColor: 'white',
      // borderRadius: 500,
      // margin: 2,
    },
    '> a > i.anticon': {
      margin: 0,
      // color: theme.color,
      color: '#FFFFFF',
      padding: 6,
      backgroundColor: 'rgba(0,0,0,0.15)',
      borderRadius: '50%',
    },
    ':hover > a > i.anticon': {
      backgroundColor: 'rgba(0,0,0,0.33)',
    },
  },
  '> li.ant-menu-submenu > .ant-menu-submenu-title': {
    paddingX: 14,
    color: '#FFFFFF',
    textAlign: 'center',
    '> i': {
      margin: 0,
      color: '#FFFFFF',
      padding: 6,
      backgroundColor: 'rgba(0,0,0,0.15)',
      borderRadius: '50%',
    },
    ':hover > i.anticon': {
      backgroundColor: 'rgba(0,0,0,0.33)',
    },
  },
  '> li.ant-menu-item.ant-menu-item-selected': {
    backgroundColor: 'transparent',
  },
  '> li.ant-menu-item-selected > a': {
    color: theme.color,
    '> i': {
      backgroundColor: 'rgba(0,0,0,0.25)!important',
    },
  },
}), Menu, p => p);

export default withLang(withAuth(({ auth, lang, className, deviceWidth, children, query, ...rest }) => (
  <VerticalMenu className={className} deviceWidth={deviceWidth}>
    <Menu.Item key="page">
      <Popover placement="right" content={lang.PAGE_MANAGER}>
        <Link to={{ query: { '@page': null, '@deviceWidth': deviceWidth } }}>
          <Icon type="home" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.Item key="template">
      <Popover placement="right" content="Template-Liste">
        <Link to={{ query: { '@template': null, '@deviceWidth': deviceWidth } }}>
          <Icon type="appstore-o" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.Item key="media">
      <Popover placement="right" content="Mediathek">
        <Link to={{ query: { '@mediathek': null } }}>
          <Icon type="picture" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.Item key="artikel">
      <Popover placement="right" content="Artikel-Liste">
        <Link to={{ query: { '@artikel': null, '@deviceWidth': deviceWidth } }}>
          <Icon type="calculator" />
        </Link>
      </Popover>
    </Menu.Item>

    {auth.user && auth.user.isAdmin ? (
      <Menu.Item key="user">
        <Popover placement="right" content="Benutzer-Management">
          <Link to={{ query: { '@user': null } }}>
            <Icon type="team" />
          </Link>
        </Popover>
      </Menu.Item>
    ) : (
      <Menu.Item key="profile">
        <Popover placement="right" content="Profil">
          <Link to={{ query: { '@profile': null } }}>
            <Icon type="user" />
          </Link>
        </Popover>
      </Menu.Item>
    )}
    <Menu.Item key="settings">
      <Popover placement="right" content="Einstellungen">
        <Link to={{ query: { '@settings': null } }}>
          <Icon type="setting" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.SubMenu key="device" title={<Icon type="laptop" />}>
      <Menu.Item key="device-no">
        <Link to={{ query: { ...query, '@deviceWidth': undefined } }}>
          <Icon type="laptop" /> Normal
        </Link>
      </Menu.Item>
      <Menu.Item key="device-700">
        <Link to={{ query: { ...query, '@deviceWidth': 700 } }}>
          <Icon type="tablet" /> Tablet
        </Link>
      </Menu.Item>
      <Menu.Item key="device-400">
        <Link to={{ query: { ...query, '@deviceWidth': 400 } }}>
          <Icon type="phone" /> Mobil
        </Link>
      </Menu.Item>
    </Menu.SubMenu>
    <Menu.Item key="logoff" title="Abmelden">
      <Popover placement="right" content="Abmelden">

          <Icon type="poweroff" />

      </Popover>
    </Menu.Item>
    {/*<CmsButton {...rest} />*/}
  </VerticalMenu>
)));
<commit_msg>Vertical menu improvements<commit_after>import React, { Component } from 'react';
import { withAuth, withRouter, styled, Link, withLang } from 'olymp';
import { Menu, Icon, Tooltip, Popover } from 'antd';
import tinycolor from 'tinycolor2';
import CmsButton from './button';

const Separator = styled(({ theme }) => ({
  // borderTop: '1px solid rgba(0, 0, 0, 0.05)',
}), 'li');
const Filler = styled(({ theme }) => ({
  flex: 1,
}), 'li');
const VerticalMenu = styled(({ deviceWidth, theme }) => ({
  overflow: 'visible',
  display: 'flex',
  flexDirection: 'column',
  boxShadow: 'inset -10px 0 3px -9px hsla(0,0%,0%,.2)!important',
  background: `linear-gradient(0deg, ${theme.colorStart || tinycolor(theme.color).darken(6).spin(-6).toRgbString()}, ${theme.colorEnd || tinycolor(theme.color).lighten(6).spin(12).toRgbString()})`,
  '> li.ant-menu-item': {
    paddingX: 14,
    //padding: 5,
    //height: 'initial',
    textAlign: 'center',
    '> a': {
      // backgroundColor: 'white',
      // borderRadius: 500,
      // margin: 2,
    },
    '> a > i.anticon': {
      margin: 0,
      // color: theme.color,
      color: '#FFFFFF',
      padding: 6,
      backgroundColor: 'rgba(0,0,0,0.15)',
      borderRadius: '50%',
    },
    ':hover > a > i.anticon': {
      backgroundColor: 'rgba(0,0,0,0.33)',
    },
  },
  '> li.ant-menu-submenu > .ant-menu-submenu-title': {
    paddingX: 14,
    color: '#FFFFFF',
    textAlign: 'center',
    '> i': {
      margin: 0,
      color: '#FFFFFF',
      padding: 6,
      backgroundColor: 'rgba(0,0,0,0.15)',
      borderRadius: '50%',
    },
    ':hover > i.anticon': {
      backgroundColor: 'rgba(0,0,0,0.33)',
    },
  },
  '> li.ant-menu-item.ant-menu-item-selected': {
    backgroundColor: 'transparent',
  },
  '> li.ant-menu-item-selected > a': {
    color: theme.color,
    '> i': {
      backgroundColor: 'rgba(0,0,0,0.25)!important',
    },
  },
}), Menu, p => p);

export default withLang(withAuth(({ auth, lang, className, deviceWidth, children, query, ...rest }) => (
  <VerticalMenu className={className} deviceWidth={deviceWidth}>
    <Menu.Item key="page">
      <Popover placement="right" content={lang.PAGE_MANAGER}>
        <Link to={{ query: { '@page': null, '@deviceWidth': deviceWidth } }}>
          <Icon type="home" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.Item key="template">
      <Popover placement="right" content="Template-Liste">
        <Link to={{ query: { '@template': null, '@deviceWidth': deviceWidth } }}>
          <Icon type="appstore-o" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.Item key="media">
      <Popover placement="right" content="Mediathek">
        <Link to={{ query: { '@mediathek': null } }}>
          <Icon type="picture" />
        </Link>
      </Popover>
    </Menu.Item>
    <Separator />
    <Menu.Item key="artikel">
      <Popover placement="right" content="Artikel-Liste">
        <Link to={{ query: { '@artikel': null, '@deviceWidth': deviceWidth } }}>
          <Icon type="calculator" />
        </Link>
      </Popover>
    </Menu.Item>
    <Filler />
    {auth.user && auth.user.isAdmin ? (
      <Menu.Item key="user">
        <Popover placement="right" content="Benutzer-Management">
          <Link to={{ query: { '@user': null } }}>
            <Icon type="team" />
          </Link>
        </Popover>
      </Menu.Item>
    ) : (
      <Menu.Item key="profile">
        <Popover placement="right" content="Profil">
          <Link to={{ query: { '@profile': null } }}>
            <Icon type="user" />
          </Link>
        </Popover>
      </Menu.Item>
    )}
    <Menu.Item key="settings">
      <Popover placement="right" content="Einstellungen">
        <Link to={{ query: { '@settings': null } }}>
          <Icon type="setting" />
        </Link>
      </Popover>
    </Menu.Item>
    <Menu.SubMenu key="device" title={<Icon type="laptop" />}>
      <Menu.Item key="device-no">
        <Link to={{ query: { ...query, '@deviceWidth': undefined } }}>
          <Icon type="laptop" /> Normal
        </Link>
      </Menu.Item>
      <Menu.Item key="device-700">
        <Link to={{ query: { ...query, '@deviceWidth': 700 } }}>
          <Icon type="tablet" /> Tablet
        </Link>
      </Menu.Item>
      <Menu.Item key="device-400">
        <Link to={{ query: { ...query, '@deviceWidth': 400 } }}>
          <Icon type="phone" /> Mobil
        </Link>
      </Menu.Item>
    </Menu.SubMenu>
    <Separator />
    <Menu.Item key="logoff" title="Abmelden">
      <Popover placement="right" content="Abmelden">

          <Icon type="poweroff" />

      </Popover>
    </Menu.Item>
    {/*<CmsButton {...rest} />*/}
  </VerticalMenu>
)));
<|endoftext|>


<commit_before>import Promise from 'bluebird';
import config from 'config';
import jwt from 'jsonwebtoken';
import moment from 'moment';

import * as errors from '../graphql/errors';
import models, { Op } from '../models';

// Helper
const daysToSeconds = days => moment.duration({ days }).asSeconds();
const minutesToSeconds = minutes => moment.duration({ minutes }).asSeconds();

/* Constants that determin token expiration */
export const TOKEN_EXPIRATION_LOGIN = minutesToSeconds(75);
export const TOKEN_EXPIRATION_CONNECTED_ACCOUNT = daysToSeconds(1);
export const TOKEN_EXPIRATION_SESSION = daysToSeconds(90);
export const TOKEN_EXPIRATION_PDF = minutesToSeconds(75);

const ALGORITHM = 'HS256';
const KID = 'HS256-2019-09-02';

/** Generate a JWToken with the received parameters */
export function createJwt(subject, payload, expiresIn) {
  return jwt.sign(payload || {}, config.keys.opencollective.jwtSecret, {
    expiresIn,
    subject: String(subject),
    algorithm: ALGORITHM,
    header: {
      kid: KID,
    },
  });
}

/** Verify JWToken */
export function verifyJwt(token) {
  return jwt.verify(token, config.keys.opencollective.jwtSecret, {
    algorithms: [ALGORITHM],
  });
}

/**
 * Returns the subset of [User|Organization]CollectiveIds that the remoteUser has access to
 */
export function getListOfAccessibleMembers(remoteUser, CollectiveIds) {
  if (!remoteUser) {
    return Promise.resolve([]);
  }
  if (!remoteUser.rolesByCollectiveId) {
    return Promise.resolve([]);
  }
  // all the CollectiveIds that the remoteUser is admin of.
  const adminOfCollectives = Object.keys(remoteUser.rolesByCollectiveId).filter(CollectiveId =>
    remoteUser.isAdmin(CollectiveId),
  );
  return models.Member.findAll({
    attributes: ['MemberCollectiveId'],
    where: {
      MemberCollectiveId: { [Op.in]: CollectiveIds },
      CollectiveId: { [Op.in]: adminOfCollectives },
    },
    group: ['MemberCollectiveId'],
  }).then(results => results.map(r => r.MemberCollectiveId));
}

export function mustBeLoggedInTo(remoteUser, action = 'do this') {
  if (!remoteUser) {
    throw new errors.Unauthorized(`You must be logged in to ${action}`);
  }
}

export function mustHaveRole(remoteUser, roles, CollectiveId, action = 'perform this action') {
  mustBeLoggedInTo(remoteUser, action);
  if (!CollectiveId || !remoteUser.hasRole(roles, CollectiveId)) {
    throw new errors.Unauthorized(`You don't have sufficient permissions to ${action}`);
  }
}
<commit_msg>chore(auth.js): Fix typo (#5651)<commit_after>import Promise from 'bluebird';
import config from 'config';
import jwt from 'jsonwebtoken';
import moment from 'moment';

import * as errors from '../graphql/errors';
import models, { Op } from '../models';

// Helper
const daysToSeconds = days => moment.duration({ days }).asSeconds();
const minutesToSeconds = minutes => moment.duration({ minutes }).asSeconds();

/* Constants that determine token expiration */
export const TOKEN_EXPIRATION_LOGIN = minutesToSeconds(75);
export const TOKEN_EXPIRATION_CONNECTED_ACCOUNT = daysToSeconds(1);
export const TOKEN_EXPIRATION_SESSION = daysToSeconds(90);
export const TOKEN_EXPIRATION_PDF = minutesToSeconds(75);

const ALGORITHM = 'HS256';
const KID = 'HS256-2019-09-02';

/** Generate a JWToken with the received parameters */
export function createJwt(subject, payload, expiresIn) {
  return jwt.sign(payload || {}, config.keys.opencollective.jwtSecret, {
    expiresIn,
    subject: String(subject),
    algorithm: ALGORITHM,
    header: {
      kid: KID,
    },
  });
}

/** Verify JWToken */
export function verifyJwt(token) {
  return jwt.verify(token, config.keys.opencollective.jwtSecret, {
    algorithms: [ALGORITHM],
  });
}

/**
 * Returns the subset of [User|Organization]CollectiveIds that the remoteUser has access to
 */
export function getListOfAccessibleMembers(remoteUser, CollectiveIds) {
  if (!remoteUser) {
    return Promise.resolve([]);
  }
  if (!remoteUser.rolesByCollectiveId) {
    return Promise.resolve([]);
  }
  // all the CollectiveIds that the remoteUser is admin of.
  const adminOfCollectives = Object.keys(remoteUser.rolesByCollectiveId).filter(CollectiveId =>
    remoteUser.isAdmin(CollectiveId),
  );
  return models.Member.findAll({
    attributes: ['MemberCollectiveId'],
    where: {
      MemberCollectiveId: { [Op.in]: CollectiveIds },
      CollectiveId: { [Op.in]: adminOfCollectives },
    },
    group: ['MemberCollectiveId'],
  }).then(results => results.map(r => r.MemberCollectiveId));
}

export function mustBeLoggedInTo(remoteUser, action = 'do this') {
  if (!remoteUser) {
    throw new errors.Unauthorized(`You must be logged in to ${action}`);
  }
}

export function mustHaveRole(remoteUser, roles, CollectiveId, action = 'perform this action') {
  mustBeLoggedInTo(remoteUser, action);
  if (!CollectiveId || !remoteUser.hasRole(roles, CollectiveId)) {
    throw new errors.Unauthorized(`You don't have sufficient permissions to ${action}`);
  }
}
<|endoftext|>


<commit_before>'use strict'

var test = require('tap').test
var os = require('os')
var proxyquire = require('proxyquire')
var pino = require('../')
var sink = require('./helper').sink
var check = require('./helper').check

var pid = process.pid
var hostname = os.hostname()

test('pino version is exposed', function (t) {
  t.plan(2)
  var instance = pino()
  t.ok(instance.pino)
  t.is(instance.pino, require('../package.json').version)
})

test('child exposes pino version', function (t) {
  t.plan(1)
  var child = pino().child({foo: 'bar'})
  t.ok(child.pino)
})

function levelTest (name, level) {
  test(name + ' logs as ' + level, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello world')
    }))

    instance.level = name
    instance[name]('hello world')
  })

  test('passing objects at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' })
  })

  test('passing an object and a string at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'a string',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' }, 'a string')
  })

  test('formatting logs as ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello 42')
    }))

    instance.level = name
    instance[name]('hello %d', 42)
  })

  test('passing error with a serializer at level ' + name, function (t) {
    t.plan(2)
    var err = new Error('myerror')
    var instance = pino({
      serializers: {
        err: pino.stdSerializers.err
      }
    }, sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        err: {
          type: 'Error',
          message: err.message,
          stack: err.stack
        },
        v: 1
      })
      cb()
    }))

    instance.level = name
    instance[name]({ err: err })
  })

  test('child logger for level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'hello world',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    var child = instance.child({
      hello: 'world'
    })
    child[name]('hello world')
  })
}

levelTest('fatal', 60)
levelTest('error', 50)
levelTest('warn', 40)
levelTest('info', 30)
levelTest('debug', 20)
levelTest('trace', 10)

test('serializers can return undefined to strip field', function (t) {
  t.plan(1)
  var instance = pino({
    serializers: {
      test: function (o) { return undefined }
    }
  }, sink(function (obj, enc, cb) {
    t.notOk('test' in obj)
    cb()
  }))

  instance.info({ test: 'sensitive info' })
})

test('does not explode with a circular ref', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  instance.info(a)
  t.end()
})

test('explode with a circular ref with safe = false', function (t) {
  var instance = pino({ safe: false }, sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  t.throws(function () {
    instance.info(a)
  })
  t.end()
})

test('set the name', function (t) {
  t.plan(2)

  var instance = pino({
    name: 'hello'
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 60,
      name: 'hello',
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('set the messageKey', function (t) {
  t.plan(2)

  var message = 'hello world'
  var messageKey = 'fooMessage'
  var instance = pino({
    messageKey: messageKey
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      fooMessage: message,
      v: 1
    })
    cb()
  }))

  instance.info(message)
})

test('set undefined properties', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  instance.info({ hello: 'world', property: undefined })
})

test('set properties defined in the prototype chain', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  function MyObject () {
    this.hello = 'world'
  }

  MyObject.prototype.some = function () {}

  instance.info(new MyObject())
})

test('set the base', function (t) {
  t.plan(2)

  var instance = pino({
    base: {
      a: 'b'
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      a: 'b',
      level: 60,
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('set the base to null', function (t) {
  t.plan(2)

  var instance = pino({
    base: null
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      level: 60,
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('throw if creating child without bindings', function (t) {
  t.plan(1)

  var instance = pino(
    sink(function (chunk, enc, cb) {
      t.ok(Date.parse(chunk.time) <= new Date(), 'time is greater than Date.now()')
      t.end()
    }))

  t.throws(function () {
    instance.child()
  })
})

test('correctly escape msg strings', function (t) {
  t.plan(1)

  var instance = pino({
    name: 'hello'
  }, sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 60,
      name: 'hello',
      msg: 'this contains "',
      v: 1
    })
    cb()
  }))

  instance.fatal('this contains "')
})

// https://github.com/pinojs/pino/issues/139
test('object and format string', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'foo bar',
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info({}, 'foo %s', 'bar')
})

test('object and format string property', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'foo bar',
      answer: 42,
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info({ answer: 42 }, 'foo %s', 'bar')
})

test('correctly strip undefined when returned from toJSON', function (t) {
  t.plan(1)

  var instance = pino({
    test: 'this'
  }, sink(function (obj, enc, cb) {
    t.notOk('test' in obj)
    cb()
  }))

  instance.fatal({test: {toJSON: function () { return undefined }}})
})

test('correctly support node v4+ stderr', function (t) {
  t.plan(1)

  // stderr inherits from Stream, rather than Writable
  var dest = {
    writable: true,
    write: function (chunk) {
      chunk = JSON.parse(chunk)
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: 60,
        msg: 'a message',
        v: 1
      })
    }
  }

  var instance = pino(dest)

  instance.fatal('a message')
})

test('normalize number to string', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: '1',
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info(1)
})

test('normalize number to string with an object', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: '1',
      answer: 42,
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info({ answer: 42 }, 1)
})

test('handles objects with null prototype', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      test: 'test',
      v: 1
    })
    t.end()
    cb()
  }))
  var o = Object.create(null)
  o.test = 'test'
  instance.info(o)
})

// https://github.com/pinojs/pino/issues/222
test('children with same names render in correct order', function (t) {
  t.plan(1)
  var root = pino(sink(function (chunk, enc, cb) {
    t.is(chunk.a, 3, 'last logged object takes precedence')
    cb()
  }))

  root.child({a: 1}).child({a: 2}).info({a: 3})
})

// https://github.com/pinojs/pino/pull/251 - use this.stringify
test('when safe is true it should ONLY use `fast-safe-stringify`', function (t) {
  t.plan(2)
  var safeStates = [true, false]
  var isFastSafeStringifyCalled = null
  var mockedPino = proxyquire('../', {
    'fast-safe-stringify': function () {
      isFastSafeStringifyCalled = true
      return '{ "hello": "world" }'
    }
  })
  safeStates.forEach(function (safeState) {
    isFastSafeStringifyCalled = false
    var instance = mockedPino({ safe: safeState }, sink(function (chunk, enc, cb) {
      cb()
    }))
    instance.info({ hello: 'world' })
    t.equal(isFastSafeStringifyCalled, safeState)
  })
  t.end()
})

test('when safe is true, fast-safe-stringify must be used when interpolating', function (t) {
  var instance = pino({safe: true}, sink(function (chunk, enc, cb) {
    const { msg } = chunk
    t.is(msg, 'test {"a":{"b":{"c":"[Circular]"}}}')
    t.end()
  }))
  var o = { a: { b: {} } }
  o.a.b.c = o.a.b
  instance.info('test', o)
})

test('when safe is false, interpolation output circulars at the root', function (t) {
  var instance = pino({safe: false}, sink(function (chunk, enc, cb) {
    const { msg } = chunk
    t.is(msg, 'test "[Circular]"')
    t.end()
  }))
  var o = { a: { b: {} } }
  o.a.b.c = o.a.b
  instance.info('test', o)
})
<commit_msg>hot fix: node v4 syntax<commit_after>'use strict'

var test = require('tap').test
var os = require('os')
var proxyquire = require('proxyquire')
var pino = require('../')
var sink = require('./helper').sink
var check = require('./helper').check

var pid = process.pid
var hostname = os.hostname()

test('pino version is exposed', function (t) {
  t.plan(2)
  var instance = pino()
  t.ok(instance.pino)
  t.is(instance.pino, require('../package.json').version)
})

test('child exposes pino version', function (t) {
  t.plan(1)
  var child = pino().child({foo: 'bar'})
  t.ok(child.pino)
})

function levelTest (name, level) {
  test(name + ' logs as ' + level, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello world')
    }))

    instance.level = name
    instance[name]('hello world')
  })

  test('passing objects at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' })
  })

  test('passing an object and a string at level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'a string',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    instance[name]({ hello: 'world' }, 'a string')
  })

  test('formatting logs as ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      check(t, chunk, level, 'hello 42')
    }))

    instance.level = name
    instance[name]('hello %d', 42)
  })

  test('passing error with a serializer at level ' + name, function (t) {
    t.plan(2)
    var err = new Error('myerror')
    var instance = pino({
      serializers: {
        err: pino.stdSerializers.err
      }
    }, sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        err: {
          type: 'Error',
          message: err.message,
          stack: err.stack
        },
        v: 1
      })
      cb()
    }))

    instance.level = name
    instance[name]({ err: err })
  })

  test('child logger for level ' + name, function (t) {
    t.plan(2)
    var instance = pino(sink(function (chunk, enc, cb) {
      t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: level,
        msg: 'hello world',
        hello: 'world',
        v: 1
      })
    }))

    instance.level = name
    var child = instance.child({
      hello: 'world'
    })
    child[name]('hello world')
  })
}

levelTest('fatal', 60)
levelTest('error', 50)
levelTest('warn', 40)
levelTest('info', 30)
levelTest('debug', 20)
levelTest('trace', 10)

test('serializers can return undefined to strip field', function (t) {
  t.plan(1)
  var instance = pino({
    serializers: {
      test: function (o) { return undefined }
    }
  }, sink(function (obj, enc, cb) {
    t.notOk('test' in obj)
    cb()
  }))

  instance.info({ test: 'sensitive info' })
})

test('does not explode with a circular ref', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  instance.info(a)
  t.end()
})

test('explode with a circular ref with safe = false', function (t) {
  var instance = pino({ safe: false }, sink(function (chunk, enc, cb) {
    // nothing to check
    cb()
  }))
  var b = {}
  var a = {
    hello: b
  }
  b.a = a // circular ref
  t.throws(function () {
    instance.info(a)
  })
  t.end()
})

test('set the name', function (t) {
  t.plan(2)

  var instance = pino({
    name: 'hello'
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 60,
      name: 'hello',
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('set the messageKey', function (t) {
  t.plan(2)

  var message = 'hello world'
  var messageKey = 'fooMessage'
  var instance = pino({
    messageKey: messageKey
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      fooMessage: message,
      v: 1
    })
    cb()
  }))

  instance.info(message)
})

test('set undefined properties', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  instance.info({ hello: 'world', property: undefined })
})

test('set properties defined in the prototype chain', function (t) {
  t.plan(2)

  var instance = pino(sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      hello: 'world',
      v: 1
    })
    cb()
  }))

  function MyObject () {
    this.hello = 'world'
  }

  MyObject.prototype.some = function () {}

  instance.info(new MyObject())
})

test('set the base', function (t) {
  t.plan(2)

  var instance = pino({
    base: {
      a: 'b'
    }
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      a: 'b',
      level: 60,
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('set the base to null', function (t) {
  t.plan(2)

  var instance = pino({
    base: null
  }, sink(function (chunk, enc, cb) {
    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
    delete chunk.time
    t.deepEqual(chunk, {
      level: 60,
      msg: 'this is fatal',
      v: 1
    })
    cb()
  }))

  instance.fatal('this is fatal')
})

test('throw if creating child without bindings', function (t) {
  t.plan(1)

  var instance = pino(
    sink(function (chunk, enc, cb) {
      t.ok(Date.parse(chunk.time) <= new Date(), 'time is greater than Date.now()')
      t.end()
    }))

  t.throws(function () {
    instance.child()
  })
})

test('correctly escape msg strings', function (t) {
  t.plan(1)

  var instance = pino({
    name: 'hello'
  }, sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 60,
      name: 'hello',
      msg: 'this contains "',
      v: 1
    })
    cb()
  }))

  instance.fatal('this contains "')
})

// https://github.com/pinojs/pino/issues/139
test('object and format string', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'foo bar',
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info({}, 'foo %s', 'bar')
})

test('object and format string property', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: 'foo bar',
      answer: 42,
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info({ answer: 42 }, 'foo %s', 'bar')
})

test('correctly strip undefined when returned from toJSON', function (t) {
  t.plan(1)

  var instance = pino({
    test: 'this'
  }, sink(function (obj, enc, cb) {
    t.notOk('test' in obj)
    cb()
  }))

  instance.fatal({test: {toJSON: function () { return undefined }}})
})

test('correctly support node v4+ stderr', function (t) {
  t.plan(1)

  // stderr inherits from Stream, rather than Writable
  var dest = {
    writable: true,
    write: function (chunk) {
      chunk = JSON.parse(chunk)
      delete chunk.time
      t.deepEqual(chunk, {
        pid: pid,
        hostname: hostname,
        level: 60,
        msg: 'a message',
        v: 1
      })
    }
  }

  var instance = pino(dest)

  instance.fatal('a message')
})

test('normalize number to string', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: '1',
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info(1)
})

test('normalize number to string with an object', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      msg: '1',
      answer: 42,
      v: 1
    })
    t.end()
    cb()
  }))

  instance.info({ answer: 42 }, 1)
})

test('handles objects with null prototype', function (t) {
  var instance = pino(sink(function (chunk, enc, cb) {
    delete chunk.time
    t.deepEqual(chunk, {
      pid: pid,
      hostname: hostname,
      level: 30,
      test: 'test',
      v: 1
    })
    t.end()
    cb()
  }))
  var o = Object.create(null)
  o.test = 'test'
  instance.info(o)
})

// https://github.com/pinojs/pino/issues/222
test('children with same names render in correct order', function (t) {
  t.plan(1)
  var root = pino(sink(function (chunk, enc, cb) {
    t.is(chunk.a, 3, 'last logged object takes precedence')
    cb()
  }))

  root.child({a: 1}).child({a: 2}).info({a: 3})
})

// https://github.com/pinojs/pino/pull/251 - use this.stringify
test('when safe is true it should ONLY use `fast-safe-stringify`', function (t) {
  t.plan(2)
  var safeStates = [true, false]
  var isFastSafeStringifyCalled = null
  var mockedPino = proxyquire('../', {
    'fast-safe-stringify': function () {
      isFastSafeStringifyCalled = true
      return '{ "hello": "world" }'
    }
  })
  safeStates.forEach(function (safeState) {
    isFastSafeStringifyCalled = false
    var instance = mockedPino({ safe: safeState }, sink(function (chunk, enc, cb) {
      cb()
    }))
    instance.info({ hello: 'world' })
    t.equal(isFastSafeStringifyCalled, safeState)
  })
  t.end()
})

test('when safe is true, fast-safe-stringify must be used when interpolating', function (t) {
  var instance = pino({safe: true}, sink(function (chunk, enc, cb) {
    var msg = chunk.msg
    t.is(msg, 'test {"a":{"b":{"c":"[Circular]"}}}')
    t.end()
  }))
  var o = { a: { b: {} } }
  o.a.b.c = o.a.b
  instance.info('test', o)
})

test('when safe is false, interpolation output circulars at the root', function (t) {
  var instance = pino({safe: false}, sink(function (chunk, enc, cb) {
    var msg = chunk.msg
    t.is(msg, 'test "[Circular]"')
    t.end()
  }))
  var o = { a: { b: {} } }
  o.a.b.c = o.a.b
  instance.info('test', o)
})
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var WidgetCacheGroupsController = function(cacheGroupHealth, $scope) {

	// pagination
	$scope.currentLocationPage = 1;
	$scope.cacheGroupsPerPage = 10;

	$scope.onlinePercent = function(location) {
		return (location.online / (location.online + location.offline)) * 100;
	};

	var init = function() {
		if (cacheGroupHealth) {
			// only set this if it's passed in
			$scope.cacheGroupHealth = cacheGroupHealth;
		}
	};
	init();

};

WidgetCacheGroupsController.$inject = ['cacheGroupHealth', '$scope'];
module.exports = WidgetCacheGroupsController;
<commit_msg>fixes bug with cachegroup sorting<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var WidgetCacheGroupsController = function(cacheGroupHealth, $scope) {

	// pagination
	$scope.currentCacheGroupsPage = 1;
	$scope.cacheGroupsPerPage = 10;

	$scope.onlinePercent = function(location) {
		return (location.online / (location.online + location.offline)) * 100;
	};

	var init = function() {
		if (cacheGroupHealth) {
			// only set this if it's passed in
			$scope.cacheGroupHealth = cacheGroupHealth;
		}
	};
	init();

};

WidgetCacheGroupsController.$inject = ['cacheGroupHealth', '$scope'];
module.exports = WidgetCacheGroupsController;
<|endoftext|>


<commit_before>import { generateUUID } from 'react-native-database';
import { batch } from 'react-redux';
import { NavigationActions } from '@react-navigation/core';

import { UIDatabase, createRecord } from '../../database';
import {
  selectEditingVaccinePrescriptionId,
  selectSelectedBatches,
} from '../../selectors/Entities/vaccinePrescription';
import { selectEditingNameId } from '../../selectors/Entities/name';
import { NameActions } from './NameActions';
import { NameNoteActions } from './NameNoteActions';

export const VACCINE_PRESCRIPTION_ACTIONS = {
  CREATE: 'VACCINE_PRESCRIPTION/create',
  UPDATE: 'VACCINE_PRESCRIPTION/update',
  SAVE_NEW: 'VACCINE_PRESCRIPTION/saveNew',
  SAVE_EDITING: 'VACCINE_PRESCRIPTION/saveEditing',
  REFUSE_VACCINATION: 'VACCINE_PRESCRIPTION/refuse',
  RESET: 'VACCINE_PRESCRIPTION/reset',
  SELECT_VACCINE: 'VACCINE_PRESCRIPTION/selectVaccine',
  SELECT_BATCH: 'VACCINE_PRESCRIPTION/selectBatch',
};

const createDefaultVaccinePrescription = () => ({
  id: generateUUID(),
  name: '',
  code: '',
  type: 'patient',
  isCustomer: false,
  isSupplier: false,
  isManufacturer: false,
  isVisible: true,
});

const create = () => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.CREATE,
  payload: { prescription: createDefaultVaccinePrescription() },
});

const reset = () => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.RESET,
});

const update = (id, field, value) => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.UPDATE,
  payload: { id, field, value },
});

const saveNew = prescription => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SAVE_NEW,
  payload: { prescription },
});

const saveEditing = prescription => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SAVE_EDITING,
  payload: { prescription },
});

const selectVaccine = vaccine => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SELECT_VACCINE,
  payload: { vaccine },
});
const selectBatch = itemBatch => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SELECT_BATCH,
  payload: { itemBatch },
});

const updateEditing = (value, field) => (dispatch, getState) => {
  const newVaccinePrescriptionId = selectEditingVaccinePrescriptionId(getState());
  dispatch(update(newVaccinePrescriptionId, field, value));
};

const refuse = value => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.REFUSE_VACCINATION,
  payload: { value },
});

const confirm = () => (dispatch, getState) => {
  const { user } = getState();
  const { currentUser } = user;
  const patientID = selectEditingNameId(getState());
  const patient = UIDatabase.get('Name', patientID);
  const selectedBatches = selectSelectedBatches(getState());

  UIDatabase.write(() => {
    const prescription = createRecord(
      UIDatabase,
      'CustomerInvoice',
      patient,
      currentUser,
      'dispensary'
    );

    selectedBatches.forEach(itemBatch => {
      const { item } = itemBatch;
      const transactionItem = createRecord(UIDatabase, 'TransactionItem', prescription, item);
      createRecord(UIDatabase, 'TransactionBatch', transactionItem, itemBatch);
      transactionItem.setDoses(UIDatabase, 1);
    });
    prescription.finalise(UIDatabase);
  });

  batch(() => {
    dispatch(NameNoteActions.saveEditing());
    dispatch(NameActions.saveEditing());
    dispatch(reset());
  });
};

const cancel = () => dispatch => {
  batch(() => {
    dispatch(NavigationActions.back());
    dispatch(NameActions.reset());
    dispatch(NameNoteActions.reset());
    dispatch(reset());
  });
};

export const VaccinePrescriptionActions = {
  cancel,
  confirm,
  create,
  refuse,
  reset,
  saveEditing,
  saveNew,
  selectBatch,
  selectVaccine,
  update,
  updateEditing,
};
<commit_msg>wire up prescription and name note<commit_after>import { generateUUID } from 'react-native-database';
import { batch } from 'react-redux';
import { NavigationActions } from '@react-navigation/core';

import { UIDatabase, createRecord } from '../../database';
import {
  selectEditingVaccinePrescriptionId,
  selectHasRefused,
  selectSelectedBatches,
} from '../../selectors/Entities/vaccinePrescription';
import { selectEditingNameId } from '../../selectors/Entities/name';
import { NameActions } from './NameActions';
import { NameNoteActions } from './NameNoteActions';

export const VACCINE_PRESCRIPTION_ACTIONS = {
  CREATE: 'VACCINE_PRESCRIPTION/create',
  UPDATE: 'VACCINE_PRESCRIPTION/update',
  SAVE_NEW: 'VACCINE_PRESCRIPTION/saveNew',
  SAVE_EDITING: 'VACCINE_PRESCRIPTION/saveEditing',
  REFUSE_VACCINATION: 'VACCINE_PRESCRIPTION/refuse',
  RESET: 'VACCINE_PRESCRIPTION/reset',
  SELECT_VACCINE: 'VACCINE_PRESCRIPTION/selectVaccine',
  SELECT_BATCH: 'VACCINE_PRESCRIPTION/selectBatch',
};

const createDefaultVaccinePrescription = () => ({
  id: generateUUID(),
  name: '',
  code: '',
  type: 'patient',
  isCustomer: false,
  isSupplier: false,
  isManufacturer: false,
  isVisible: true,
});

const create = () => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.CREATE,
  payload: { prescription: createDefaultVaccinePrescription() },
});

const reset = () => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.RESET,
});

const update = (id, field, value) => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.UPDATE,
  payload: { id, field, value },
});

const saveNew = prescription => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SAVE_NEW,
  payload: { prescription },
});

const saveEditing = prescription => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SAVE_EDITING,
  payload: { prescription },
});

const selectVaccine = vaccine => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SELECT_VACCINE,
  payload: { vaccine },
});
const selectBatch = itemBatch => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.SELECT_BATCH,
  payload: { itemBatch },
});

const updateEditing = (value, field) => (dispatch, getState) => {
  const newVaccinePrescriptionId = selectEditingVaccinePrescriptionId(getState());
  dispatch(update(newVaccinePrescriptionId, field, value));
};

const refuse = value => ({
  type: VACCINE_PRESCRIPTION_ACTIONS.REFUSE_VACCINATION,
  payload: { value },
});

const createPrescription = (patient, currentUser, selectedBatches) => {
  UIDatabase.write(() => {
    const prescription = createRecord(
      UIDatabase,
      'CustomerInvoice',
      patient,
      currentUser,
      'dispensary'
    );

    selectedBatches.forEach(itemBatch => {
      const { item } = itemBatch;
      const transactionItem = createRecord(UIDatabase, 'TransactionItem', prescription, item);
      createRecord(UIDatabase, 'TransactionBatch', transactionItem, itemBatch);
      transactionItem.setDoses(UIDatabase, 1);
    });
    prescription.finalise(UIDatabase);
  });
};

const createRefusalNameNote = name => {
  const [patientEvent] = UIDatabase.objects('PatientEvent').filtered('code == "RV"');
  const id = generateUUID();
  const data = { refused: true, date: new Date() };
  const newNameNote = { id, name, patientEvent, data, entryDate: new Date() };

  UIDatabase.write(() => UIDatabase.create('NameNote', newNameNote));
};

const confirm = () => (dispatch, getState) => {
  const { user } = getState();
  const { currentUser } = user;
  const hasRefused = selectHasRefused(getState());
  const patientID = selectEditingNameId(getState());
  const patient = UIDatabase.get('Name', patientID);
  const selectedBatches = selectSelectedBatches(getState());

  if (hasRefused) {
    createRefusalNameNote(patient);
  } else {
    createPrescription(patient, currentUser, selectedBatches);
  }

  batch(() => {
    dispatch(NameNoteActions.saveEditing());
    dispatch(NameActions.saveEditing());
    dispatch(reset());
  });
};

const cancel = () => dispatch => {
  batch(() => {
    dispatch(NavigationActions.back());
    dispatch(NameActions.reset());
    dispatch(NameNoteActions.reset());
    dispatch(reset());
  });
};

export const VaccinePrescriptionActions = {
  cancel,
  confirm,
  create,
  refuse,
  reset,
  saveEditing,
  saveNew,
  selectBatch,
  selectVaccine,
  update,
  updateEditing,
};
<|endoftext|>


<commit_before>/*
 * Jakefile for Rimu Markup (http://github.com/srackham/rimu).
 */
'use strict'

if (parseInt(process.versions.node) < 6) {
  fail('nodejs must be version 6 or greater')
}

let pkg = require('./package.json')
let shelljs = require('shelljs')
let child_process = require('child_process')

/* Inputs and outputs */

let RIMU_LIB = 'lib/rimu.js'
let RIMU_LIB_MIN = 'lib/rimu.min.js'
let RIMU_SRC = shelljs.ls('src/rimu/*.ts')
let RIMU_TSD = 'typings/rimu.d.ts'
let TESTS = shelljs.ls('test/*.js')
let DOCS_DIR = 'docs/'
let RIMUC_JS = 'bin/rimuc.js'
let RIMUC_TS = 'src/rimuc/rimuc.ts'
let RIMUC_EXE = 'node ' + RIMUC_JS

let DOCS = [
  {
    src: 'README.md',
    dst: DOCS_DIR + 'index.html',
    title: 'Rimu Markup',
    rimucOptions: '--highlightjs'
  },
  {
    src: DOCS_DIR + 'changelog.rmu',
    dst: DOCS_DIR + 'changelog.html',
    title: 'Rimu Change Log',
    rimucOptions: ''
  },
  {
    src: DOCS_DIR + 'reference.rmu',
    dst: DOCS_DIR + 'reference.html',
    title: 'Rimu Reference',
    rimucOptions: '--highlightjs --prepend "{generate-examples}=\'yes\'"'
  },
  {
    src: DOCS_DIR + 'tips.rmu',
    dst: DOCS_DIR + 'tips.html',
    title: 'Rimu Tips',
    rimucOptions: '--highlightjs --mathjax --prepend "{generate-examples}=\'yes\'"'
  },
  {
    src: DOCS_DIR + 'rimuplayground.rmu',
    dst: DOCS_DIR + 'rimuplayground.html',
    title: 'Rimu Playground',
    rimucOptions: '--prepend "{generate-examples}=\'yes\'"'
  },
  {
    src: DOCS_DIR + 'gallery.rmu',
    dst: DOCS_DIR + 'gallery.html',
    title: 'Rimu layout and themes gallery',
    rimucOptions: ''
  }
]
let HTML = DOCS.map(doc => doc.dst)

/* Utility functions. */

/*
 Execute shell commands in parallel then run the `callback` when they have all finished.
 Abort immediately an error occurs unless options.executeAll is true (in which case run all commands
 commands and abort if one or more failed).
 Write command output to the inherited stdout (unless the Jake --quiet option is set).
 Print a status message when each command starts and finishes (unless the Jake --quiet option is set).

 NOTE: This function is similar to the built-in jake.exec function but is twice as fast.
 */
function exec(commands, callback, options = {}) {
  if (typeof commands === 'string') {
    commands = [commands]
  }
  let remaining = commands.length
  if (remaining === 0) {
    callback()
  }
  else {
    let error_count = 0
    commands.forEach(command => {
      jake.logger.log('STARTING: ' + command)
      child_process.exec(command, function (error, stdout, stderr) {
        jake.logger.log((error === null ? 'FINISHED: ' : 'FAILED: ') + command)
        if (!jake.program.opts.quiet) {
          jake.logger.log(stdout)
        }
        if (error !== null) {
          if (options.executeAll) {
            error_count++
          }
          else {
            fail(error, error.code)
          }
        }
        remaining--
        if (remaining === 0) {
          if (error_count > 0) {
            fail(error_count + ' errors(s)')
          }
          else {
            callback()
          }
        }
      })
    })
  }
}

/*
 Tasks

 All tasks are synchronous (another task will not run until the current task has completed).
 Consequently all task dependencies are executed asynchronously in declaration order.
 The `exec` function ensures shell commands within each task run in parallel.
 */

desc(`Run tests.`)
task('default', ['test'])

desc(`build, lint and test rimu and tools, build documentation, validate HTML. Use vers=x.y.z argument to set a new version number.`)
task('build', ['test', 'lint', 'version', 'build-docs', 'validate-html'])

desc(`Update version number, tag and push to Github and npm. Use vers=x.y.z argument to set a new version number. Finally, rebuild and publish docs website.`)
task('release', ['build', 'tag', 'publish'])

desc(`Lint TypeScript, Javascript and JSON files.`)
task('lint', {async: true}, function () {
  let commands = []
    .concat(RIMU_SRC.concat([RIMUC_TS, RIMU_TSD]).map(file => 'tslint ' + file))
    .concat(TESTS.map(file => 'jshint ' + file))
// TODO: Disable jsonlint until the nomnom bug is fixed (see https://github.com/zaach/jsonlint/issues/103).
//    .concat(['jsonlint --quiet package.json'])
  exec(commands, complete)
})

desc(`Run tests (rebuild if necessary).`)
task('test', ['build-rimu', 'build-rimuc'], {async: true}, function () {
  let commands = TESTS.map(file => 'tape ' + file + ' | faucet')
  exec(commands, complete)
})

desc(`Compile and bundle rimu.js and rimu.min.js libraries and generate .map files.`)
task('build-rimu', [RIMU_LIB])

file(RIMU_LIB, RIMU_SRC, {async: true}, function () {
  exec('webpack --mode production --config ./src/rimu/webpack.config.js', complete)
})

desc(`Compile rimuc to JavaScript executable and generate .map file.`)
task('build-rimuc', {async: true}, function () {
  exec('webpack --mode production --config ./src/rimuc/webpack.config.js', function () {
    shelljs.chmod('+x', RIMUC_JS)
    complete()
  })
})

desc(`Generate documentation`)
task('build-docs', ['build-rimu', 'build-gallery'], {async: true}, function () {
  let commands = DOCS.map(doc =>
    RIMUC_EXE +
    ' --no-rimurc --theme legend --custom-toc --header-links' +
    ' --layout sequel' +
    ' --output "' + doc.dst + '"' +
    ' --lang en' +
    ' --title "' + doc.title + '"' +
    ' ' + doc.rimucOptions + ' ' +
    ' ./src/examples/example-rimurc.rmu ' + DOCS_DIR + 'doc-header.rmu ' + doc.src
  )
  shelljs.cp('-f', RIMU_LIB_MIN, DOCS_DIR)
  exec(commands, complete)
})

function forEachGalleryDocument(documentCallback, layoutCallback, themeCallback) {
  ['sequel', 'classic', 'flex', 'plain'].forEach(function (layout) {
    if (layoutCallback) layoutCallback(layout);
    if (layout === 'plain') {
      documentCallback('--layout plain --no-toc', 'plain-example.html')
      return
    }
    ['legend', 'vintage', 'graystone'].forEach(function (theme) {
      if (themeCallback) themeCallback(layout, theme);
      ['', 'dropdown-toc', 'no-toc'].forEach(function (variant) {
        let option = variant;
        switch (variant) {
          case 'dropdown-toc':
            if (layout !== 'classic') return
            else option = '--prepend "{--dropdown-toc}=\'yes\'"';
            break;
          case 'no-toc':
            option = '--no-toc';
            break;
        }
        let options = '--layout ' + layout + ' --theme ' + theme + ' ' + option
        options = options.trim()
        let outfile = layout + '-' + theme + '-' + variant + '-example.html'
        outfile = outfile.replace('--', '-')
        documentCallback(options, outfile, layout, theme)
      })
    })
  })
}

desc(`Generate gallery documentation examples`)
task('build-gallery', ['build-rimu'], {async: true}, function () {
  let commands = [];
  forEachGalleryDocument(function (options, outfile, layout, theme) {
    let command =
      RIMUC_EXE +
      ' --custom-toc' +
      ' --no-rimurc' +
      ' ' + options +
      ' --output ' + DOCS_DIR + outfile +
      ' --prepend "{gallery-options}=\'' + options.replace(/(["{])/g, '\\$1') + '\'"' +
      ' ./src/examples/example-rimurc.rmu' +
      ' ' + DOCS_DIR + 'doc-header.rmu' +
      ' ' + DOCS_DIR + 'gallery-example-template.rmu'
    commands.push(command)
  })
  exec(commands, complete)
})

desc('Generate gallery index Rimu markup for ' + DOCS_DIR + 'gallery.rmu')
task('gallery-markup', function () {
  forEachGalleryDocument(function (options, outfile, layout, theme) {
      let link = '[`' + options.replace(/{/g, '\\{') + '`](' + outfile + ')'
      console.log('- ' + link)
    },
    function (layout) {
      console.log('\n\n## ' + layout + ' layout');
    },
    function (layout, theme) {
      console.log('\n### ' + theme + ' theme');
    })
})

desc(`Validate HTML documents.`)
task('validate-html', {async: true}, function () {
  let commands = HTML.map(file => 'html-validator --verbose --format=text --file=' + file)
  // 2018-11-09: Disable validation. The Nu W3C validator is once again treating style tags in the body as an error.
  // exec(commands, complete, {executeAll: true})
})

desc(`Display or update the project version number. Use vers=x.y.z argument to set a new version number.`)
task('version', {async: true}, function () {
  let version = process.env.vers
  if (!version) {
    console.log(`version: ${pkg.version}`)
    complete()
  }
  else {
    if (!version.match(/^\d+\.\d+\.\d+$/)) {
      fail('Invalid version number: ' + version + '\n')
    }
    shelljs.sed('-i', /(\s*"version"\s*:\s*)"\d+\.\d+\.\d+"/, `$1"${version}"`, 'package.json')
    pkg.version = version
    exec('git commit -m "Bump version number." package.json', complete)
  }
})

desc(`Create tag ${pkg.version}`)
task('tag', ['test'], {async: true}, function () {
  exec('git tag -a -m "Tag ' + pkg.version + '" ' + pkg.version, complete)
})

desc(`Commit changes to local Git repo.`)
task('commit', ['test'], {async: true}, function () {
  jake.exec('git commit -a', {interactive: true}, complete)
})

desc(`Push to Github and publish to npm.`)
task('publish', ['push', 'publish-npm'])

desc(`Push local commits to Github.`)
task('push', ['test'], {async: true}, function () {
  exec('git push -u --tags origin master', complete)
})

desc(`Publish to npm.`)
task('publish-npm', {async: true}, ['test', 'build-rimu'], function () {
  exec('npm publish', complete)
})<commit_msg>build: Exclude files with style elements in body from HTML validation.<commit_after>/*
 * Jakefile for Rimu Markup (http://github.com/srackham/rimu).
 */
'use strict'

if (parseInt(process.versions.node) < 6) {
  fail('nodejs must be version 6 or greater')
}

let pkg = require('./package.json')
let shelljs = require('shelljs')
let child_process = require('child_process')

/* Inputs and outputs */

let RIMU_LIB = 'lib/rimu.js'
let RIMU_LIB_MIN = 'lib/rimu.min.js'
let RIMU_SRC = shelljs.ls('src/rimu/*.ts')
let RIMU_TSD = 'typings/rimu.d.ts'
let TESTS = shelljs.ls('test/*.js')
let DOCS_DIR = 'docs/'
let RIMUC_JS = 'bin/rimuc.js'
let RIMUC_TS = 'src/rimuc/rimuc.ts'
let RIMUC_EXE = 'node ' + RIMUC_JS

let DOCS = [
  {
    src: 'README.md',
    dst: DOCS_DIR + 'index.html',
    title: 'Rimu Markup',
    rimucOptions: '--highlightjs'
  },
  {
    src: DOCS_DIR + 'changelog.rmu',
    dst: DOCS_DIR + 'changelog.html',
    title: 'Rimu Change Log',
    rimucOptions: ''
  },
  {
    src: DOCS_DIR + 'reference.rmu',
    dst: DOCS_DIR + 'reference.html',
    title: 'Rimu Reference',
    rimucOptions: '--highlightjs --prepend "{generate-examples}=\'yes\'"'
  },
  {
    src: DOCS_DIR + 'tips.rmu',
    dst: DOCS_DIR + 'tips.html',
    title: 'Rimu Tips',
    rimucOptions: '--highlightjs --mathjax --prepend "{generate-examples}=\'yes\'"'
  },
  {
    src: DOCS_DIR + 'rimuplayground.rmu',
    dst: DOCS_DIR + 'rimuplayground.html',
    title: 'Rimu Playground',
    rimucOptions: '--prepend "{generate-examples}=\'yes\'"'
  },
  {
    src: DOCS_DIR + 'gallery.rmu',
    dst: DOCS_DIR + 'gallery.html',
    title: 'Rimu layout and themes gallery',
    rimucOptions: ''
  }
]
let HTML = DOCS.map(doc => doc.dst)

/* Utility functions. */

/*
 Execute shell commands in parallel then run the `callback` when they have all finished.
 Abort immediately an error occurs unless options.executeAll is true (in which case run all commands
 commands and abort if one or more failed).
 Write command output to the inherited stdout (unless the Jake --quiet option is set).
 Print a status message when each command starts and finishes (unless the Jake --quiet option is set).

 NOTE: This function is similar to the built-in jake.exec function but is twice as fast.
 */
function exec(commands, callback, options = {}) {
  if (typeof commands === 'string') {
    commands = [commands]
  }
  let remaining = commands.length
  if (remaining === 0) {
    callback()
  }
  else {
    let error_count = 0
    commands.forEach(command => {
      jake.logger.log('STARTING: ' + command)
      child_process.exec(command, function (error, stdout, stderr) {
        jake.logger.log((error === null ? 'FINISHED: ' : 'FAILED: ') + command)
        if (!jake.program.opts.quiet) {
          jake.logger.log(stdout)
        }
        if (error !== null) {
          if (options.executeAll) {
            error_count++
          }
          else {
            fail(error, error.code)
          }
        }
        remaining--
        if (remaining === 0) {
          if (error_count > 0) {
            fail(error_count + ' errors(s)')
          }
          else {
            callback()
          }
        }
      })
    })
  }
}

/*
 Tasks

 All tasks are synchronous (another task will not run until the current task has completed).
 Consequently all task dependencies are executed asynchronously in declaration order.
 The `exec` function ensures shell commands within each task run in parallel.
 */

desc(`Run tests.`)
task('default', ['test'])

desc(`build, lint and test rimu and tools, build documentation, validate HTML. Use vers=x.y.z argument to set a new version number.`)
task('build', ['test', 'lint', 'version', 'build-docs', 'validate-html'])

desc(`Update version number, tag and push to Github and npm. Use vers=x.y.z argument to set a new version number. Finally, rebuild and publish docs website.`)
task('release', ['build', 'tag', 'publish'])

desc(`Lint TypeScript, Javascript and JSON files.`)
task('lint', {async: true}, function () {
  let commands = []
    .concat(RIMU_SRC.concat([RIMUC_TS, RIMU_TSD]).map(file => 'tslint ' + file))
    .concat(TESTS.map(file => 'jshint ' + file))
// TODO: Disable jsonlint until the nomnom bug is fixed (see https://github.com/zaach/jsonlint/issues/103).
//    .concat(['jsonlint --quiet package.json'])
  exec(commands, complete)
})

desc(`Run tests (rebuild if necessary).`)
task('test', ['build-rimu', 'build-rimuc'], {async: true}, function () {
  let commands = TESTS.map(file => 'tape ' + file + ' | faucet')
  exec(commands, complete)
})

desc(`Compile and bundle rimu.js and rimu.min.js libraries and generate .map files.`)
task('build-rimu', [RIMU_LIB])

file(RIMU_LIB, RIMU_SRC, {async: true}, function () {
  exec('webpack --mode production --config ./src/rimu/webpack.config.js', complete)
})

desc(`Compile rimuc to JavaScript executable and generate .map file.`)
task('build-rimuc', {async: true}, function () {
  exec('webpack --mode production --config ./src/rimuc/webpack.config.js', function () {
    shelljs.chmod('+x', RIMUC_JS)
    complete()
  })
})

desc(`Generate documentation`)
task('build-docs', ['build-rimu', 'build-gallery'], {async: true}, function () {
  let commands = DOCS.map(doc =>
    RIMUC_EXE +
    ' --no-rimurc --theme legend --custom-toc --header-links' +
    ' --layout sequel' +
    ' --output "' + doc.dst + '"' +
    ' --lang en' +
    ' --title "' + doc.title + '"' +
    ' ' + doc.rimucOptions + ' ' +
    ' ./src/examples/example-rimurc.rmu ' + DOCS_DIR + 'doc-header.rmu ' + doc.src
  )
  exec(commands, function () {
    shelljs.cp('-f', RIMU_LIB_MIN, DOCS_DIR)
    complete()
  })
})

function forEachGalleryDocument(documentCallback, layoutCallback, themeCallback) {
  ['sequel', 'classic', 'flex', 'plain'].forEach(function (layout) {
    if (layoutCallback) layoutCallback(layout);
    if (layout === 'plain') {
      documentCallback('--layout plain --no-toc', 'plain-example.html')
      return
    }
    ['legend', 'vintage', 'graystone'].forEach(function (theme) {
      if (themeCallback) themeCallback(layout, theme);
      ['', 'dropdown-toc', 'no-toc'].forEach(function (variant) {
        let option = variant;
        switch (variant) {
          case 'dropdown-toc':
            if (layout !== 'classic') return
            else option = '--prepend "{--dropdown-toc}=\'yes\'"';
            break;
          case 'no-toc':
            option = '--no-toc';
            break;
        }
        let options = '--layout ' + layout + ' --theme ' + theme + ' ' + option
        options = options.trim()
        let outfile = layout + '-' + theme + '-' + variant + '-example.html'
        outfile = outfile.replace('--', '-')
        documentCallback(options, outfile, layout, theme)
      })
    })
  })
}

desc(`Generate gallery documentation examples`)
task('build-gallery', ['build-rimu'], {async: true}, function () {
  let commands = [];
  forEachGalleryDocument(function (options, outfile, layout, theme) {
    let command =
      RIMUC_EXE +
      ' --custom-toc' +
      ' --no-rimurc' +
      ' ' + options +
      ' --output ' + DOCS_DIR + outfile +
      ' --prepend "{gallery-options}=\'' + options.replace(/(["{])/g, '\\$1') + '\'"' +
      ' ./src/examples/example-rimurc.rmu' +
      ' ' + DOCS_DIR + 'doc-header.rmu' +
      ' ' + DOCS_DIR + 'gallery-example-template.rmu'
    commands.push(command)
  })
  exec(commands, complete)
})

desc('Generate gallery index Rimu markup for ' + DOCS_DIR + 'gallery.rmu')
task('gallery-markup', function () {
  forEachGalleryDocument(function (options, outfile, layout, theme) {
      let link = '[`' + options.replace(/{/g, '\\{') + '`](' + outfile + ')'
      console.log('- ' + link)
    },
    function (layout) {
      console.log('\n\n## ' + layout + ' layout');
    },
    function (layout, theme) {
      console.log('\n### ' + theme + ' theme');
    })
})

desc(`Validate HTML documents.`)
task('validate-html', {async: true}, function () {
  let commands = HTML
    // 2018-11-09: Skip files with style tags in the body as Nu W3C validator treats style tags in the body as an error.
    .filter(file => ! ['reference','tips','rimuplayground'].map(file => DOCS_DIR+file+'.html').includes(file))
    .map(file => 'html-validator --verbose --format=text --file=' + file)
  exec(commands, complete, {executeAll: true})
})

desc(`Display or update the project version number. Use vers=x.y.z argument to set a new version number.`)
task('version', {async: true}, function () {
  let version = process.env.vers
  if (!version) {
    console.log(`version: ${pkg.version}`)
    complete()
  }
  else {
    if (!version.match(/^\d+\.\d+\.\d+$/)) {
      fail('Invalid version number: ' + version + '\n')
    }
    shelljs.sed('-i', /(\s*"version"\s*:\s*)"\d+\.\d+\.\d+"/, `$1"${version}"`, 'package.json')
    pkg.version = version
    exec('git commit -m "Bump version number." package.json', complete)
  }
})

desc(`Create tag ${pkg.version}`)
task('tag', ['test'], {async: true}, function () {
  exec('git tag -a -m "Tag ' + pkg.version + '" ' + pkg.version, complete)
})

desc(`Commit changes to local Git repo.`)
task('commit', ['test'], {async: true}, function () {
  jake.exec('git commit -a', {interactive: true}, complete)
})

desc(`Push to Github and publish to npm.`)
task('publish', ['push', 'publish-npm'])

desc(`Push local commits to Github.`)
task('push', ['test'], {async: true}, function () {
  exec('git push -u --tags origin master', complete)
})

desc(`Publish to npm.`)
task('publish-npm', {async: true}, ['test', 'build-rimu'], function () {
  exec('npm publish', complete)
})<|endoftext|>


<commit_before>var sys = require('sys'),
    vows = require('vows'),
    assert = require('assert');
var books = require('../books');
var redis = require("redis"),
    client = redis.createClient();

client.select(99,function(err,result) {
    // Clear out this test database
    client.flushdb();
});

vows.describe('Books').addBatch({
    'Create Book': {
        topic: function() {
            books.save_book(client,"9780060733353",this.callback);
        },
        'has ASIN': function(err,book) {
            assert.equal(book.ASIN, "0060733357");
        },
        'has Title': function(err, book) {
            assert.equal(book.ItemAttributes.Title, "The Confusion (The Baroque Cycle, Vol. 2)");
        },
        'has ISBN': function(err, book) {
            assert.equal(book.ItemAttributes.ISBN, "0060733357");
        },
        'has Author': function(err, book) {
            assert.equal(book.ItemAttributes.Author, "Neal Stephenson");
        },
        'has NumberOfPages': function(err, book) {
            assert.equal(book.ItemAttributes.NumberOfPages, "848");
        }
    }
}).addBatch({
    'Retrieve Book': {
        topic: function() {
            var context = this;
            client.flushdb(function() {
                books.save_book(client,"9780060733353",function() {
                    books.query_book(client,"9780060733353",context.callback);
                });
            });
        },
        'has ASIN': function(book) {
            assert.equal(book.ASIN, "0060733357");
        },
        'has Title': function(err, book) {
            assert.equal(book.ItemAttributes.Title, "The Confusion (The Baroque Cycle, Vol. 2)");
        },
        'has ISBN': function(err, book) {
            assert.equal(book.ItemAttributes.ISBN, "0060733357");
        },
        'has Author': function(err, book) {
            assert.equal(book.ItemAttributes.Author, "Neal Stephenson");
        },
        'has NumberOfPages': function(err, book) {
            assert.equal(book.ItemAttributes.NumberOfPages, "848");
        },
    }
}).addBatch({
    'Book Listing': {
        topic: function() {
            var context = this;
            // flush db, add two books, and get a full list.
            client.flushdb(function() {
                books.save_book(client,"9780060733353",function() {
                    books.save_book(client,"9780471292524",function() {
                        books.list_books(client,0,99,context.callback);
                    });
                });
            });
        },
        'has correct count': function(err, booklist) {
            assert.equal(booklist.length, 2);
        },
        teardown: function() { client.quit();}
    }
}).export(module);
<commit_msg>Added test for contents of book listing.<commit_after>var sys = require('sys'),
    vows = require('vows'),
    assert = require('assert');
var books = require('../books');
var redis = require("redis"),
    client = redis.createClient();

client.select(99,function(err,result) {
    // Clear out this test database
    client.flushdb();
});

vows.describe('Books').addBatch({
    'Create Book': {
        topic: function() {
            books.save_book(client,"9780060733353",this.callback);
        },
        'has ASIN': function(err,book) {
            assert.equal(book.ASIN, "0060733357");
        },
        'has Title': function(err, book) {
            assert.equal(book.ItemAttributes.Title, "The Confusion (The Baroque Cycle, Vol. 2)");
        },
        'has ISBN': function(err, book) {
            assert.equal(book.ItemAttributes.ISBN, "0060733357");
        },
        'has Author': function(err, book) {
            assert.equal(book.ItemAttributes.Author, "Neal Stephenson");
        },
        'has NumberOfPages': function(err, book) {
            assert.equal(book.ItemAttributes.NumberOfPages, "848");
        }
    }
}).addBatch({
    'Retrieve Book': {
        topic: function() {
            var context = this;
            client.flushdb(function() {
                books.save_book(client,"9780060733353",function() {
                    books.query_book(client,"9780060733353",context.callback);
                });
            });
        },
        'has ASIN': function(book) {
            assert.equal(book.ASIN, "0060733357");
        },
        'has Title': function(err, book) {
            assert.equal(book.ItemAttributes.Title, "The Confusion (The Baroque Cycle, Vol. 2)");
        },
        'has ISBN': function(err, book) {
            assert.equal(book.ItemAttributes.ISBN, "0060733357");
        },
        'has Author': function(err, book) {
            assert.equal(book.ItemAttributes.Author, "Neal Stephenson");
        },
        'has NumberOfPages': function(err, book) {
            assert.equal(book.ItemAttributes.NumberOfPages, "848");
        },
    }
}).addBatch({
    'Book Listing': {
        topic: function() {
            var context = this;
            // flush db, add two books, and get a full list.
            client.flushdb(function() {
                books.save_book(client,"9780060733353",function() {
                    books.save_book(client,"9780471292524",function() {
                        books.list_books(client,0,99,context.callback);
                    });
                });
            });
        },
        'has correct count': function(err, booklist) {
            assert.equal(booklist.length, 2);
        },
        'contains correct books': function(err,booklist) {
            assert.equal(booklist[0].ItemAttributes.Title, "The Confusion (The Baroque Cycle, Vol. 2)");
            assert.equal(booklist[1].ItemAttributes.Title,"Developing Products in Half the Time: New Rules, New Tools, 2nd Edition");
        },
        teardown: function() { client.quit();}
    }
}).export(module);
<|endoftext|>


<commit_before>/*jshint nomen:false */
/*globals require, console, complete, __dirname, process */

(function () {
    'use strict';

    var exec = require('child_process').exec,

    commands = {
        minify: './node_modules/.bin/uglifyjs --no-copyright --lift-vars --output ./src/vagueTime.min.js ./src/vagueTime.js',
        test: './node_modules/.bin/mocha --ui tdd --reporter spec --colors ./test/vagueTime.js',
        lint: './node_modules/.bin/jshint ./src/vagueTime.js --config config/jshint.json',
        prepare: 'npm install'
    };

    desc('Minify the source code for deployment.');
    task('minify', [ 'prepare', 'lint', 'test' ], function () {
        runTask(minify, 'Minifying...');
    }, {
        async: true
    });

    desc('Run the unit tests.');
    task('test', [ 'prepare' ], function () {
        runTask(test, 'Testing...');
    }, {
        async: true
    });

    desc('Lint the source code.');
    task('lint', [ 'prepare' ], function () {
        runTask(lint, 'Linting...');
    }, {
        async: true
    });

    desc('Install dependencies.');
    task('prepare', function () {
        runTask(prepare, 'Preparing the build environment...');
    }, {
        async: true
    });

    function runTask (operation, message) {
        console.log(message);
        operation();
    }

    function minify () {
        runCommand(commands.minify);
    }

    function test () {
        runCommand(commands.test);
    }

    function lint () {
        runCommand(commands.lint);
    }

    function prepare () {
        runCommand(commands.prepare);
    }

    function runCommand (command) {
        exec(command, { cwd: __dirname }, function (error, stdout, stderr) {
            console.log(stdout);
            console.log(stderr);
            if (typeof error === 'object' && error !== null) {
                console.log(error.message);
                process.exit(1);
            }
            complete();
        });
    }
}());

<commit_msg>Update uglify command for new version.<commit_after>/*jshint nomen:false */
/*globals require, console, complete, __dirname, process */

(function () {
    'use strict';

    var exec = require('child_process').exec,

    commands = {
        minify: './node_modules/.bin/uglifyjs ./src/vagueTime.js --compress --mangle --output ./src/vagueTime.min.js',
        test: './node_modules/.bin/mocha --ui tdd --reporter spec --colors ./test/vagueTime.js',
        lint: './node_modules/.bin/jshint ./src/vagueTime.js --config config/jshint.json',
        prepare: 'npm install'
    };

    desc('Minify the source code for deployment.');
    task('minify', [ 'prepare', 'lint', 'test' ], function () {
        runTask(minify, 'Minifying...');
    }, {
        async: true
    });

    desc('Run the unit tests.');
    task('test', [ 'prepare' ], function () {
        runTask(test, 'Testing...');
    }, {
        async: true
    });

    desc('Lint the source code.');
    task('lint', [ 'prepare' ], function () {
        runTask(lint, 'Linting...');
    }, {
        async: true
    });

    desc('Install dependencies.');
    task('prepare', function () {
        runTask(prepare, 'Preparing the build environment...');
    }, {
        async: true
    });

    function runTask (operation, message) {
        console.log(message);
        operation();
    }

    function minify () {
        runCommand(commands.minify);
    }

    function test () {
        runCommand(commands.test);
    }

    function lint () {
        runCommand(commands.lint);
    }

    function prepare () {
        runCommand(commands.prepare);
    }

    function runCommand (command) {
        exec(command, { cwd: __dirname }, function (error, stdout, stderr) {
            console.log(stdout);
            console.log(stderr);
            if (typeof error === 'object' && error !== null) {
                console.log(error.message);
                process.exit(1);
            }
            complete();
        });
    }
}());

<|endoftext|>


<commit_before>var assert = require('assert');
var cp = require('child_process')
var path = require('path');
var existsSync = require('fs').existsSync || require('path').existsSync;

var cmd_path = path.join(__dirname,'../bin/');
var sep = ':';
if (process.platform === 'win32') {
    sep = ';'
}
process.env.PATH = cmd_path + sep + process.env.PATH;
process.env.NODE_PATH = path.join(__dirname,'../lib/');

function run(command,app,opts,cb) {
    if (!opts.cwd) {
        command += ' -C ' + path.join(__dirname,app.name);
    }
    command += ' ' + app.args;
    cp.exec(command,opts, cb);
}

var apps = [
    {
        'name': 'app1',
        'args': ''
    }
    ,{
        'name': 'app2',
        'args': '--custom_include_path=../include'
    }
    ,{
        'name': 'app2',
        'args': '--custom_include_path=../include --debug'
    }
    ,{
        'name': 'app3',
        'args': ''
    }
    ,{
        'name': 'app4',
        'args': ''
    }
]

describe('build', function() {
    apps.forEach(function(app) {

        it(app.name + ' builds ' + app.args, function(done) {
            run('node-pre-gyp rebuild --fallback-to-build --loglevel=silent', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.ok(stdout.search(app.name+'.node') > -1);
                assert.equal(stderr,'');
                done();
            })
        });

        it(app.name + ' builds with custom --target ' + app.args, function(done) {
            run('node-pre-gyp rebuild --fallback-to-build --target='+process.versions.node, app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.ok(stdout.search(app.name+'.node') > -1);
                assert.equal(stderr,'');
                done();
            })
        });

        it(app.name + ' is found ' + app.args, function(done) {
            run('node-pre-gyp reveal module_path --silent', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                var module_path = stdout.trim();
                assert.ok(module_path.search(app.name) > -1);
                assert.ok(existsSync(module_path));
                var module_binary = path.join(module_path,app.name+'.node');
                assert.ok(existsSync(module_binary));
                done();
            });
        });

        it(app.name + ' passes tests ' + app.args, function(done) {
            run('npm test', app, {cwd: path.join(__dirname,app.name)}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                assert.notEqual(stdout,'');
                done();
            });
        });

        it(app.name + ' packages ' + app.args, function(done) {
            run('node-pre-gyp package', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                done();
            });
        });

        it(app.name + ' package is valid ' + app.args, function(done) {
            run('node-pre-gyp testpackage', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                done();
            });
        });

        if (process.env.AWS_ACCESS_KEY_ID || process.env.node_pre_gyp_accessKeyId) {

            it(app.name + ' publishes ' + app.args, function(done) {
                run('node-pre-gyp unpublish publish', app, {}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

            it(app.name + ' info shows it ' + app.args, function(done) {
                run('node-pre-gyp reveal package_name --silent', app, {}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    var package_name = stdout.trim();
                    run('node-pre-gyp info', app, {}, function(err,stdout,stderr) {
                        if (err) throw err;
                        assert.equal(stderr,'');
                        assert.ok(stdout.indexOf(package_name) > -1);
                        done();
                    });
                });
            });

            it(app.name + ' can be uninstalled ' + app.args, function(done) {
                run('node-pre-gyp clean', app, {}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

            it(app.name + ' can be installed via remote ' + app.args, function(done) {
                run('npm install --fallback-to-build=false --silent', app, {cwd: path.join(__dirname,app.name)}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

            it(app.name + ' via remote passes tests ' + app.args, function(done) {
                run('npm test', app, {cwd: path.join(__dirname,app.name)}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

        } else {
            it.skip(app.name + ' publishes ' + app.args, function() {});
        }

    });
});
<commit_msg>debug x64 windows failings<commit_after>var assert = require('assert');
var cp = require('child_process')
var path = require('path');
var existsSync = require('fs').existsSync || require('path').existsSync;

var cmd_path = path.join(__dirname,'../bin/');
var sep = ':';
if (process.platform === 'win32') {
    sep = ';'
}
process.env.PATH = cmd_path + sep + process.env.PATH;
process.env.NODE_PATH = path.join(__dirname,'../lib/');

function run(command,app,opts,cb) {
    if (!opts.cwd) {
        command += ' -C ' + path.join(__dirname,app.name);
    }
    command += ' ' + app.args;
    cp.exec(command,opts, cb);
}

var apps = [
    {
        'name': 'app1',
        'args': ''
    }
    ,{
        'name': 'app2',
        'args': '--custom_include_path=../include'
    }
    ,{
        'name': 'app2',
        'args': '--custom_include_path=../include --debug'
    }
    ,{
        'name': 'app3',
        'args': ''
    }
    ,{
        'name': 'app4',
        'args': ''
    }
]

describe('build', function() {
    apps.forEach(function(app) {

        it(app.name + ' builds ' + app.args, function(done) {
            run('node-pre-gyp rebuild --fallback-to-build --loglevel=silent', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                console.log(stdout);
                assert.ok(stdout.search(app.name+'.node') > -1);
                assert.equal(stderr,'');
                done();
            })
        });

        it(app.name + ' builds with custom --target ' + app.args, function(done) {
            run('node-pre-gyp rebuild --fallback-to-build --target='+process.versions.node, app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                console.log(stdout);
                assert.ok(stdout.search(app.name+'.node') > -1);
                assert.equal(stderr,'');
                done();
            })
        });

        it(app.name + ' is found ' + app.args, function(done) {
            run('node-pre-gyp reveal module_path --silent', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                console.log(stdout);
                assert.equal(stderr,'');
                var module_path = stdout.trim();
                assert.ok(module_path.search(app.name) > -1);
                assert.ok(existsSync(module_path));
                var module_binary = path.join(module_path,app.name+'.node');
                assert.ok(existsSync(module_binary));
                done();
            });
        });

        it(app.name + ' passes tests ' + app.args, function(done) {
            run('npm test', app, {cwd: path.join(__dirname,app.name)}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                assert.notEqual(stdout,'');
                done();
            });
        });

        it(app.name + ' packages ' + app.args, function(done) {
            run('node-pre-gyp package', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                done();
            });
        });

        it(app.name + ' package is valid ' + app.args, function(done) {
            run('node-pre-gyp testpackage', app, {}, function(err,stdout,stderr) {
                if (err) throw err;
                assert.equal(stderr,'');
                done();
            });
        });

        if (process.env.AWS_ACCESS_KEY_ID || process.env.node_pre_gyp_accessKeyId) {

            it(app.name + ' publishes ' + app.args, function(done) {
                run('node-pre-gyp unpublish publish', app, {}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

            it(app.name + ' info shows it ' + app.args, function(done) {
                run('node-pre-gyp reveal package_name --silent', app, {}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    var package_name = stdout.trim();
                    run('node-pre-gyp info', app, {}, function(err,stdout,stderr) {
                        if (err) throw err;
                        assert.equal(stderr,'');
                        assert.ok(stdout.indexOf(package_name) > -1);
                        done();
                    });
                });
            });

            it(app.name + ' can be uninstalled ' + app.args, function(done) {
                run('node-pre-gyp clean', app, {}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

            it(app.name + ' can be installed via remote ' + app.args, function(done) {
                run('npm install --fallback-to-build=false --silent', app, {cwd: path.join(__dirname,app.name)}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

            it(app.name + ' via remote passes tests ' + app.args, function(done) {
                run('npm test', app, {cwd: path.join(__dirname,app.name)}, function(err,stdout,stderr) {
                    if (err) throw err;
                    assert.equal(stderr,'');
                    assert.notEqual(stdout,'');
                    done();
                });
            });

        } else {
            it.skip(app.name + ' publishes ' + app.args, function() {});
        }

    });
});
<|endoftext|>


<commit_before>import { gsap } from '../src/utils'
import Group, { groupDefaults } from '../src/group/group'
import Timelines from '../src/group/timelines'

describe('group', () => {

  let sandbox

  beforeEach(() => sandbox = sinon.sandbox.create())
  afterEach(() => sandbox.restore())

  it('should create an empty group', () => {
    const group = new Group()

    expect(group.fps).equal(groupDefaults.fps)
    expect(group.name).equal(groupDefaults.name)
    expect(group.timelines).equal(groupDefaults.timelines)
  })

  it('should create custom group', () => {
    const group = new Group({ name: 'ghost' })
    expect(group.name).equal('ghost')
  })

  it('should have empty timelines', () => {
    const group = new Group()
    expect(group.timelines).to.be.an.instanceOf(Timelines)
    expect(group.timelines).to.have.lengthOf(0)
  })

  it('should ensure gsap before construct animation', async () => {
    const group = new Group()
    const spy = sandbox.spy(gsap, 'ensure')

    const result = await resolvePromise(group.construct())

    expect(spy.called).to.be.true
    expect(result).not.to.be.an('error')
  })

})
<commit_msg>Skip group test gsap ensure for now<commit_after>import { gsap } from '../src/utils'
import Group, { groupDefaults } from '../src/group/group'
import Timelines from '../src/group/timelines'

describe('group', () => {

  let sandbox

  beforeEach(() => sandbox = sinon.sandbox.create())
  afterEach(() => sandbox.restore())

  it('should create an empty group', () => {
    const group = new Group()

    expect(group.fps).equal(groupDefaults.fps)
    expect(group.name).equal(groupDefaults.name)
    expect(group.timelines).equal(groupDefaults.timelines)
  })

  it('should create custom group', () => {
    const group = new Group({ name: 'ghost' })
    expect(group.name).equal('ghost')
  })

  it('should have empty timelines', () => {
    const group = new Group()
    expect(group.timelines).to.be.an.instanceOf(Timelines)
    expect(group.timelines).to.have.lengthOf(0)
  })

  it.skip('should ensure gsap before construct animation', async () => {
    const group = new Group()
    const spy = sandbox.spy(gsap, 'ensure')

    const result = await resolvePromise(group.construct())

    expect(spy.called).to.be.true
    expect(result).not.to.be.an('error')
  })

})
<|endoftext|>