<commit_before>import assert from "assert"
import tmp from "tmp"
import path from "path"
import fs from "fs"
import concat from "concat-stream"
import sinon from "sinon"

import LogFileGenerator from "../mock/LogFileGenerator.js"
import LiveIndex from "../lib/LiveIndex.js"

tmp.setGracefulCleanup()

const fooFixturePath = path.resolve(__dirname, "..", "fixtures", "foo.txt")
const fooFixtureData = fs.readFileSync(fooFixturePath)
const barFixturePath = path.resolve(__dirname, "..", "fixtures", "bar.txt")
const barFixtureData = fs.readFileSync(barFixturePath)

describe("LiveIndex", () => {
  let index, logGenerator, dir, logPath

  const simpleIndexer = (data, addIndex) => {
    let pos = 0
    data.toString().split(/\n+/).forEach(s => {
      const m = s.match(/[^:]+/);
      if (m) { addIndex(m[0], pos) }
      pos += s.length + 1
    })
  }

  beforeEach(done => {
    logGenerator = new LogFileGenerator()
    dir = tmp.dirSync({ unsafeCleanup: true }).name
    logPath = path.join(dir, "foo.log")
    logGenerator.createLog(logPath)
    logGenerator.on("created", () => {
      index = new LiveIndex({ pathToWatch: logPath })
      return done()
    })
  })

  describe("fileAndPositionForIdentifier()", () => {
    beforeEach(() => {
      index.setIndexer(simpleIndexer)
      index.watch()
    })

    it("should return the correct file and position for the id", done => {
      logGenerator.writeLog()
      index.once("insert", id => {
        assert.strictEqual(id, logGenerator.ids[0])
        index.fileAndPositionForIdentifier(id).then(result => {
          assert.strictEqual(result.file, logPath)
          assert.strictEqual(result.position, 0)
          return done()
        })
      })
    })

    it("should update the file name when the underlying file is renamed", done => {
      logGenerator.on("flushed", () => {
        const newPath = path.join(dir, "renamed.txt")
        logGenerator.renameFile(newPath, () => {
          setTimeout(() => {
            index.fileAndPositionForIdentifier(logGenerator.ids[0]).then(result => {
              assert.strictEqual(result.file, newPath)
              return done()
            })
          }, 40)
        })
      })
      logGenerator.writeLog()
    })

    it("should resolve link entries", done => {
      index.addStaticDataFile(fooFixturePath)
      Promise.all([
        index.insert("foo", fooFixturePath, 9),
        index.insertLink("bar", "foo")
      ]).then(() => {
        return index.fileAndPositionForIdentifier("bar")
      }).then(result => {
        assert.deepEqual(result, {file: fooFixturePath, position: 9})
        return done()
      })
    })

    it("should reject when traversing a self referential link", done => {
      index.addStaticDataFile(fooFixturePath)
      index.insertLink("foo", "foo")
        .then(() => index.fileAndPositionForIdentifier("foo"))
        .then(() => assert.fail(), err => {
          assert(err)
          return done()
        })
    })

    it("should reject when traversing a circular link", done => {
      index.addStaticDataFile(fooFixturePath)
      Promise.all([
        index.insertLink("foo", "bar"),
        index.insertLink("bar", "foo"),
      ]).then(() => index.fileAndPositionForIdentifier("foo"))
        .then(() => assert.fail(), err => {
          assert(err)
          return done()
        })
    })
  })

  describe("indexer", () => {
    describe("processedTo callback", () => {
      it("should cause unprocessed buffer to be appended in next chunk", done => {
        let callCount = 0
        index.setIndexer((data, addIndex, processedTo) => {
          callCount += 1
          if (callCount === 1) {
            assert(processedTo)
            processedTo(7)
          }
          else if (callCount === 2) {
            const expected = logGenerator.lines[0].slice(7) + logGenerator.lines[1]
            assert.strictEqual(data.toString(), expected)
            return done()
          }
        })
        index.watch()
        logGenerator.writeLog()
      })
    })

    describe("addIndex callback", () => {
      it("should call .insert() to add indexes", done => {
        const insertSpy = sinon.spy(index, "insert")
        index.setIndexer(simpleIndexer)
        index.watch()
        logGenerator.writeLog()
        logGenerator.on("flushed", () => {
          assert.strictEqual(insertSpy.callCount, 5)
          logGenerator.ids.forEach((id, i) => {
            assert(insertSpy.calledWithExactly(id, logPath, i*20))
          })
          return done()
        })
      })

      it("should call .insertLink() to add links", done => {
        const insertLinkSpy = sinon.spy(index, "insertLink")
        index.setIndexer((chunk, addIndex, processedTo) => {
          simpleIndexer(chunk, addIndex, processedTo)
          const lastId = logGenerator.ids.pop()
          addIndex(`link-${lastId}`, lastId)
        })
        index.watch()
        logGenerator.writeLog()
        logGenerator.on("flushed", () => {
          assert.strictEqual(insertLinkSpy.callCount, 5)
          logGenerator.ids.forEach((id, i) => {
            assert(insertLinkSpy.calledWithExactly(`link-${id}`, id))
          })
          return done()
        })
      })
    })
  })

  describe("setIndexStorageObject()", () => {
    let mockStore

    beforeEach(() => {
      mockStore = new MockIndexStorage()
      index = new LiveIndex()
      index.setIndexStorageObject(mockStore)
    })

    it("should update the object that is used when calling .insert()", () => {
      index.insert("foo", "file", 5)
      mockStore.assertSetCalledWith("foo", {file: undefined, position: 5})
    })

    it("should update the object that is used when calling fileAndPositionForIdentifier()", () => {
      index.fileAndPositionForIdentifier("foo")
      mockStore.assertGetCalledWith("foo")
    })
  })

  describe("addStaticDataFile()", () => {
    it("should add a file to the index", done => {
      index.setIndexer(simpleIndexer)
      index.watch()
      logGenerator.writeLog()

      logGenerator.once("flushed", () => {
        index.addStaticDataFile(barFixturePath, err => {
          assert.ifError(err)
          const expected = {file: barFixturePath, position: 20}
          index.fileAndPositionForIdentifier("EtBQPcgqTHA").then(result => {
            assert.deepEqual(result, expected)
            return done()
          })
        })
      })
    })
  })

  describe("readStreamBetweenIndexes()", () => {
    beforeEach(done => {
      index.setIndexer(simpleIndexer)
      index.addStaticDataFile(barFixturePath, err => added(err, barFixturePath))
      index.addStaticDataFile(fooFixturePath, err => added(err, fooFixturePath))

      const seen = []
      function added (err, path) {
        assert.ifError(err)

        seen.push(path)
        if (seen.length !== 2) {
          return done()
        }
      }
    })

    it("should return undefined if index does not exist", () => {
      return Promise.all([
        index.readStreamBetweenIndexes("nonexistent", "6fVmv625zfs"),
        index.readStreamBetweenIndexes("6fVmv625zfs", "nonexistent"),
        index.readStreamBetweenIndexes("nonexistent", "nonexistent")
      ]).then(([firstNonExistent, secondNonExistent, bothNonExistent]) => {
        assert.strictEqual(firstNonExistent, undefined)
        assert.strictEqual(secondNonExistent, undefined)
        assert.strictEqual(bothNonExistent, undefined)
      })
    })

    it("should return a Readable stream beginning at the offset specified by the index", done => {
      index.readStreamBetweenIndexes("6fVmv625zfs", "cLlQfumYGlQ").then(stream => {
        stream.pipe(concat(result => {
          assert.strictEqual(result.toString(), fooFixtureData.slice(40, 80).toString())
          return done()
        }))
      })
    })

    it("should return a Readable stream that spans across files", done => {
      index.readStreamBetweenIndexes("EtBQPcgqTHA", "6fVmv625zfs").then(stream => {
        stream.pipe(concat(result => {
          const barThenFoo = Buffer.concat([barFixtureData, fooFixtureData])
          assert.strictEqual(result.toString(), barThenFoo.slice(20, 140).toString())
          return done()
        }))
      })
    })

    it("should emit an error when startId comes after endId in different files", done => {
      index.readStreamBetweenIndexes("6fVmv625zfs", "EtBQPcgqTHA").catch(err => {
        assert(err)
        return done()
      })
    })

    it("should emit an error when startId comes after endId in same file", () => {
      index.readStreamBetweenIndexes("cLlQfumYGlQ", "6fVmv625zfs").catch(err => {
        assert(err)
        return done()
      })
    })
  })

  describe("insert()", () => {
    it("should emit an error when insertion fails", done => {
      index.setIndexStorageObject(new ExplodingStorage())
      index.insert("foo", "foo.log", 0)
      index.once("error", err => {
        assert(err)
        return done()
      })
    })
  })

  describe("insertLink()", () => {
    it("should emit an error when link insertion fails", done => {
      index.setIndexStorageObject(new ExplodingStorage())
      index.insertLink("foo", "bar")
      index.once("error", err => {
        assert(err)
        return done()
      })
    })
  })
})

class MockIndexStorage {
  constructor () {
    this._map = Object.create(null)
    this._getCalledWith = null
    this._setCalledWith = null
  }

  get (id) {
    this._getCalledWith = Array.from(arguments)
    return new Promise(resolve => {
      process.nextTick(() => resolve(this._map[id]))
    })
  }

  set (id, val) {
    this._setCalledWith = Array.from(arguments)
    return new Promise(resolve => {
      process.nextTick(() => resolve(this._map[id] = val))
    })
  }

  assertGetCalledWith () {
    assert.deepEqual(this._getCalledWith, Array.from(arguments))
  }

  assertSetCalledWith () {
    assert.deepEqual(this._setCalledWith, Array.from(arguments))
  }
}

class ExplodingStorage {
  get (id) {
    return Promise.reject(new Error("Failed to read A:\\MYDB.DAT"))
  }

  set (id, val) {
    return Promise.reject(new Error("Can't open A:\\MYDB.DAT"))
  }
}
<commit_msg>Test that fileAndPositionForIdentifier() returns error when storage fails<commit_after>import assert from "assert"
import tmp from "tmp"
import path from "path"
import fs from "fs"
import concat from "concat-stream"
import sinon from "sinon"

import LogFileGenerator from "../mock/LogFileGenerator.js"
import LiveIndex from "../lib/LiveIndex.js"

tmp.setGracefulCleanup()

const fooFixturePath = path.resolve(__dirname, "..", "fixtures", "foo.txt")
const fooFixtureData = fs.readFileSync(fooFixturePath)
const barFixturePath = path.resolve(__dirname, "..", "fixtures", "bar.txt")
const barFixtureData = fs.readFileSync(barFixturePath)

describe("LiveIndex", () => {
  let index, logGenerator, dir, logPath

  const simpleIndexer = (data, addIndex) => {
    let pos = 0
    data.toString().split(/\n+/).forEach(s => {
      const m = s.match(/[^:]+/);
      if (m) { addIndex(m[0], pos) }
      pos += s.length + 1
    })
  }

  beforeEach(done => {
    logGenerator = new LogFileGenerator()
    dir = tmp.dirSync({ unsafeCleanup: true }).name
    logPath = path.join(dir, "foo.log")
    logGenerator.createLog(logPath)
    logGenerator.on("created", () => {
      index = new LiveIndex({ pathToWatch: logPath })
      return done()
    })
  })

  describe("fileAndPositionForIdentifier()", () => {
    beforeEach(() => {
      index.setIndexer(simpleIndexer)
      index.watch()
    })

    it("should return the correct file and position for the id", done => {
      logGenerator.writeLog()
      index.once("insert", id => {
        assert.strictEqual(id, logGenerator.ids[0])
        index.fileAndPositionForIdentifier(id).then(result => {
          assert.strictEqual(result.file, logPath)
          assert.strictEqual(result.position, 0)
          return done()
        })
      })
    })

    it("should update the file name when the underlying file is renamed", done => {
      logGenerator.on("flushed", () => {
        const newPath = path.join(dir, "renamed.txt")
        logGenerator.renameFile(newPath, () => {
          setTimeout(() => {
            index.fileAndPositionForIdentifier(logGenerator.ids[0]).then(result => {
              assert.strictEqual(result.file, newPath)
              return done()
            })
          }, 40)
        })
      })
      logGenerator.writeLog()
    })

    it("should resolve link entries", done => {
      index.addStaticDataFile(fooFixturePath)
      Promise.all([
        index.insert("foo", fooFixturePath, 9),
        index.insertLink("bar", "foo")
      ]).then(() => {
        return index.fileAndPositionForIdentifier("bar")
      }).then(result => {
        assert.deepEqual(result, {file: fooFixturePath, position: 9})
        return done()
      })
    })

    it("should reject when traversing a self referential link", done => {
      index.addStaticDataFile(fooFixturePath)
      index.insertLink("foo", "foo")
        .then(() => index.fileAndPositionForIdentifier("foo"))
        .then(() => assert.fail(), err => {
          assert(err)
          return done()
        })
    })

    it("should reject when traversing a circular link", done => {
      index.addStaticDataFile(fooFixturePath)
      Promise.all([
        index.insertLink("foo", "bar"),
        index.insertLink("bar", "foo"),
      ]).then(() => index.fileAndPositionForIdentifier("foo"))
        .then(() => assert.fail(), err => {
          assert(err)
          return done()
        })
    })

    it("should reject when storage fails with an error", done => {
      index.setIndexStorageObject(new ExplodingStorage())
      index.fileAndPositionForIdentifier("foo").catch(err => {
        assert(err)
        return done()
      })
    })
  })

  describe("indexer", () => {
    describe("processedTo callback", () => {
      it("should cause unprocessed buffer to be appended in next chunk", done => {
        let callCount = 0
        index.setIndexer((data, addIndex, processedTo) => {
          callCount += 1
          if (callCount === 1) {
            assert(processedTo)
            processedTo(7)
          }
          else if (callCount === 2) {
            const expected = logGenerator.lines[0].slice(7) + logGenerator.lines[1]
            assert.strictEqual(data.toString(), expected)
            return done()
          }
        })
        index.watch()
        logGenerator.writeLog()
      })
    })

    describe("addIndex callback", () => {
      it("should call .insert() to add indexes", done => {
        const insertSpy = sinon.spy(index, "insert")
        index.setIndexer(simpleIndexer)
        index.watch()
        logGenerator.writeLog()
        logGenerator.on("flushed", () => {
          assert.strictEqual(insertSpy.callCount, 5)
          logGenerator.ids.forEach((id, i) => {
            assert(insertSpy.calledWithExactly(id, logPath, i*20))
          })
          return done()
        })
      })

      it("should call .insertLink() to add links", done => {
        const insertLinkSpy = sinon.spy(index, "insertLink")
        index.setIndexer((chunk, addIndex, processedTo) => {
          simpleIndexer(chunk, addIndex, processedTo)
          const lastId = logGenerator.ids.pop()
          addIndex(`link-${lastId}`, lastId)
        })
        index.watch()
        logGenerator.writeLog()
        logGenerator.on("flushed", () => {
          assert.strictEqual(insertLinkSpy.callCount, 5)
          logGenerator.ids.forEach((id, i) => {
            assert(insertLinkSpy.calledWithExactly(`link-${id}`, id))
          })
          return done()
        })
      })
    })
  })

  describe("setIndexStorageObject()", () => {
    let mockStore

    beforeEach(() => {
      mockStore = new MockIndexStorage()
      index = new LiveIndex()
      index.setIndexStorageObject(mockStore)
    })

    it("should update the object that is used when calling .insert()", () => {
      index.insert("foo", "file", 5)
      mockStore.assertSetCalledWith("foo", {file: undefined, position: 5})
    })

    it("should update the object that is used when calling fileAndPositionForIdentifier()", () => {
      index.fileAndPositionForIdentifier("foo")
      mockStore.assertGetCalledWith("foo")
    })
  })

  describe("addStaticDataFile()", () => {
    it("should add a file to the index", done => {
      index.setIndexer(simpleIndexer)
      index.watch()
      logGenerator.writeLog()

      logGenerator.once("flushed", () => {
        index.addStaticDataFile(barFixturePath, err => {
          assert.ifError(err)
          const expected = {file: barFixturePath, position: 20}
          index.fileAndPositionForIdentifier("EtBQPcgqTHA").then(result => {
            assert.deepEqual(result, expected)
            return done()
          })
        })
      })
    })
  })

  describe("readStreamBetweenIndexes()", () => {
    beforeEach(done => {
      index.setIndexer(simpleIndexer)
      index.addStaticDataFile(barFixturePath, err => added(err, barFixturePath))
      index.addStaticDataFile(fooFixturePath, err => added(err, fooFixturePath))

      const seen = []
      function added (err, path) {
        assert.ifError(err)

        seen.push(path)
        if (seen.length !== 2) {
          return done()
        }
      }
    })

    it("should return undefined if index does not exist", () => {
      return Promise.all([
        index.readStreamBetweenIndexes("nonexistent", "6fVmv625zfs"),
        index.readStreamBetweenIndexes("6fVmv625zfs", "nonexistent"),
        index.readStreamBetweenIndexes("nonexistent", "nonexistent")
      ]).then(([firstNonExistent, secondNonExistent, bothNonExistent]) => {
        assert.strictEqual(firstNonExistent, undefined)
        assert.strictEqual(secondNonExistent, undefined)
        assert.strictEqual(bothNonExistent, undefined)
      })
    })

    it("should return a Readable stream beginning at the offset specified by the index", done => {
      index.readStreamBetweenIndexes("6fVmv625zfs", "cLlQfumYGlQ").then(stream => {
        stream.pipe(concat(result => {
          assert.strictEqual(result.toString(), fooFixtureData.slice(40, 80).toString())
          return done()
        }))
      })
    })

    it("should return a Readable stream that spans across files", done => {
      index.readStreamBetweenIndexes("EtBQPcgqTHA", "6fVmv625zfs").then(stream => {
        stream.pipe(concat(result => {
          const barThenFoo = Buffer.concat([barFixtureData, fooFixtureData])
          assert.strictEqual(result.toString(), barThenFoo.slice(20, 140).toString())
          return done()
        }))
      })
    })

    it("should emit an error when startId comes after endId in different files", done => {
      index.readStreamBetweenIndexes("6fVmv625zfs", "EtBQPcgqTHA").catch(err => {
        assert(err)
        return done()
      })
    })

    it("should emit an error when startId comes after endId in same file", () => {
      index.readStreamBetweenIndexes("cLlQfumYGlQ", "6fVmv625zfs").catch(err => {
        assert(err)
        return done()
      })
    })
  })

  describe("insert()", () => {
    it("should emit an error when insertion fails", done => {
      index.setIndexStorageObject(new ExplodingStorage())
      index.insert("foo", "foo.log", 0)
      index.once("error", err => {
        assert(err)
        return done()
      })
    })
  })

  describe("insertLink()", () => {
    it("should emit an error when link insertion fails", done => {
      index.setIndexStorageObject(new ExplodingStorage())
      index.insertLink("foo", "bar")
      index.once("error", err => {
        assert(err)
        return done()
      })
    })
  })
})

class MockIndexStorage {
  constructor () {
    this._map = Object.create(null)
    this._getCalledWith = null
    this._setCalledWith = null
  }

  get (id) {
    this._getCalledWith = Array.from(arguments)
    return new Promise(resolve => {
      process.nextTick(() => resolve(this._map[id]))
    })
  }

  set (id, val) {
    this._setCalledWith = Array.from(arguments)
    return new Promise(resolve => {
      process.nextTick(() => resolve(this._map[id] = val))
    })
  }

  assertGetCalledWith () {
    assert.deepEqual(this._getCalledWith, Array.from(arguments))
  }

  assertSetCalledWith () {
    assert.deepEqual(this._setCalledWith, Array.from(arguments))
  }
}

class ExplodingStorage {
  get (id) {
    return Promise.reject(new Error("Failed to read A:\\MYDB.DAT"))
  }

  set (id, val) {
    return Promise.reject(new Error("Can't open A:\\MYDB.DAT"))
  }
}
<|endoftext|>


<commit_before>/*global describe, beforeEach, it*/
'use strict';

var path = require('path');
var helpers = require('yeoman-generator').test;

describe('node-webkit generator', function () {
  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.app = helpers.createGenerator('node-webkit:app', [
        '../../app'
      ]);

      helpers.mockPrompt(this.app, {
        'appName': 'Test App',
        'appDescription': 'Test App Description',
        'githubUser': 'someUser',
        'platforms': []
      });
      this.app.options['skip-install'] = true;

      done();
    }.bind(this));
  });

  it('Creates dot files', function (done) {
    var expected = [
      '.jshintrc',
      '.editorconfig'
    ];

    this.app.run({}, function () {
      helpers.assertFile(expected);
      done();
    });
  });

  it('Creates main package files', function (done) {
    var expected = [
      // add files you expect to exist here.
      'Gruntfile.js',
      'package.json',
      'bower.json'
    ];

    this.app.run({}, function () {
      helpers.assertFile(expected);
      done();
    });
  });
});
<commit_msg>* this is related to #24 * adjust test setup * tests show finally correct results<commit_after>/*global describe, beforeEach, it*/
'use strict';

var path = require('path');
var temp = require('temp');
var helpers = require('yeoman-generator').test;
var assert = require('yeoman-generator').assert;

describe('Test prompt validations', function () {

  var app;

  after(function () {
    temp.cleanup();
  });

  it('App name has invalid character and should fail', function(done){
    var workspace = temp.mkdirSync();
    helpers.testDirectory(workspace, function (err) {
      if (err) {
        return done(err);
      }

      app = helpers.createGenerator('node-webkit:app', [
        path.resolve(__dirname, '../app')
      ]);

      helpers.mockPrompt(app, {
        'appName': 'Test App',
        'appDescription': 'Test App Description',
        'githubUser': 'someuser',
        downloadNodeWebkit: false,
        'platforms': ['Linux64']
      });
      app.options['skip-install'] = true;

      app.run({}, function () {
        assert.ok(typeof app.errors !== 'undefined', 'This should fail if the app name contains a space.');
        assert.ok(app.errors.length === 1, 'There should be only 1 error.');
        assert.ok(app.errors[0].name === 'appName', 'The appName property should be wrong.');
        assert.ok(app.errors[0].message === 'The application name should only consist of the following characters a-z, A-Z and 0-9.', 'The appName property should be wrong.');
        done();
      });
    });
  });
});

describe('node-webkit generator', function () {
  var app;

  after(function () {
    temp.cleanup();
  });

  beforeEach(function (done) {
    var workspace = temp.mkdirSync();
    helpers.testDirectory(workspace, function (err) {
      if (err) {
        return done(err);
      }

      app = helpers.createGenerator('node-webkit:app', [
        path.resolve(__dirname, '../app')
      ]);

      helpers.mockPrompt(app, {
        'appName': 'TestApp',
        'appDescription': 'Test App Description',
        'githubUser': 'someuser',
        downloadNodeWebkit: false,
        'platforms': ['Linux64']
      });
      app.options['skip-install'] = true;
      done();
    });
  });

  it('Creates dot files', function (done) {
    var expected = [
      '.jshintrc',
      '.editorconfig'
    ];

    app.run({}, function () {
      assert.ok(typeof app.errors === 'undefined', 'Validation errors in prompt values');
      helpers.assertFile(expected);
      done();
    });
  });

  it('Creates main package files', function (done) {
    var expected = [
      // add files you expect to exist here.
      'Gruntfile.js',
      'package.json',
      'bower.json'
    ];

    app.run({}, function () {
      assert.ok(typeof app.errors === 'undefined', 'Validation errors in prompt values');
      helpers.assertFile(expected);
      done();
    });
  });
});
<|endoftext|>


<commit_before>var util           = require("util")
  , EventEmitter   = require("events").EventEmitter
  , Promise        = require("promise")
  , proxyEventKeys = ['success', 'error', 'sql']

var bindToProcess = function(fct) {
  if (fct) {
    if (process.domain) {
      return process.domain.bind(fct);
    }
  }

  return fct;
};

module.exports = (function() {
  var CustomEventEmitter = function(fct) {
    this.fct = bindToProcess(fct);
  }
  util.inherits(CustomEventEmitter, EventEmitter)

  CustomEventEmitter.prototype.run = function() {
    var tick = (typeof setImmediate !== "undefined" ? setImmediate : process.nextTick)
    tick(function() {
      if (this.fct) {
        this.fct.call(this, this)
      }
    }.bind(this))

    return this
  }

  CustomEventEmitter.prototype.success =
  CustomEventEmitter.prototype.ok =
  function(fct) {
    this.on('success', bindToProcess(fct))
    return this
  }

  CustomEventEmitter.prototype.failure =
  CustomEventEmitter.prototype.fail =
  CustomEventEmitter.prototype.error =
  function(fct) {
    this.on('error', bindToProcess(fct))
    return this;
  }

  CustomEventEmitter.prototype.done =
  CustomEventEmitter.prototype.complete =
  function(fct) {
    fct = bindToProcess(fct);
    this.on('error', function(err) { fct(err, null) })
        .on('success', function(result) { fct(null, result) })
    return this
  }

  CustomEventEmitter.prototype.sql =
  function(fct) {
    this.on('sql', bindToProcess(fct))
    return this;
  }

  CustomEventEmitter.prototype.proxy = function(emitter) {
    proxyEventKeys.forEach(function (eventKey) {
      this.on(eventKey, function (result) {
        emitter.emit(eventKey, result)
      })
    }.bind(this))
  }

  CustomEventEmitter.prototype.then =
  function (onFulfilled, onRejected) {
    var self = this
    onFulfilled = bindToProcess(onFulfilled)
    onRejected = bindToProcess(onRejected)
    return new Promise(function (resolve, reject) {
      self.on('error', reject)
          .on('success', resolve);
    }).then(onFulfilled, onRejected)
  }

  return CustomEventEmitter;
})()

<commit_msg>Forgot to move the tick variable to the top of the file in custom event emitters.<commit_after>var util           = require("util")
  , EventEmitter   = require("events").EventEmitter
  , Promise        = require("promise")
  , proxyEventKeys = ['success', 'error', 'sql']
  , tick           = (typeof setImmediate !== "undefined" ? setImmediate : process.nextTick)

var bindToProcess = function(fct) {
  if (fct) {
    if (process.domain) {
      return process.domain.bind(fct);
    }
  }

  return fct;
};

module.exports = (function() {
  var CustomEventEmitter = function(fct) {
    this.fct = bindToProcess(fct);
  }
  util.inherits(CustomEventEmitter, EventEmitter)

  CustomEventEmitter.prototype.run = function() {
    tick(function() {
      if (this.fct) {
        this.fct.call(this, this)
      }
    }.bind(this))

    return this
  }

  CustomEventEmitter.prototype.success =
  CustomEventEmitter.prototype.ok =
  function(fct) {
    this.on('success', bindToProcess(fct))
    return this
  }

  CustomEventEmitter.prototype.failure =
  CustomEventEmitter.prototype.fail =
  CustomEventEmitter.prototype.error =
  function(fct) {
    this.on('error', bindToProcess(fct))
    return this;
  }

  CustomEventEmitter.prototype.done =
  CustomEventEmitter.prototype.complete =
  function(fct) {
    fct = bindToProcess(fct);
    this.on('error', function(err) { fct(err, null) })
        .on('success', function(result) { fct(null, result) })
    return this
  }

  CustomEventEmitter.prototype.sql =
  function(fct) {
    this.on('sql', bindToProcess(fct))
    return this;
  }

  CustomEventEmitter.prototype.proxy = function(emitter) {
    proxyEventKeys.forEach(function (eventKey) {
      this.on(eventKey, function (result) {
        emitter.emit(eventKey, result)
      })
    }.bind(this))
  }

  CustomEventEmitter.prototype.then =
  function (onFulfilled, onRejected) {
    var self = this
    onFulfilled = bindToProcess(onFulfilled)
    onRejected = bindToProcess(onRejected)
    return new Promise(function (resolve, reject) {
      self.on('error', reject)
          .on('success', resolve);
    }).then(onFulfilled, onRejected)
  }

  return CustomEventEmitter;
})()

<|endoftext|>


<commit_before>var CronJob = require('cron').CronJob;
var time = require('time');
var fs = require('fs');

var twitter = require('../twitter');

var alertTimes = 0;

var frequency = 10;

function repeat(string, times) {
	var ret = '';
	for (var i = 0; i < times; i++) ret += string;
	return ret;
}

module.exports = new CronJob('00 * * * * *', function () {
	var now = new Date();

	fs.readFile(__dirname + '/lastalert.txt', function (error, data) {
		if (error) return console.error(error);

		var lastAlert = data.toString();

		twitter.get('hakatashi', 'statuses/user_timeline', {
			screen_name: 'hideo54',
			since_id: lastAlert,
			count: frequency,
			include_rts: false
		}, function (error, responce, data) {
			if (error) return console.error(error);
			if (data.length < frequency) return;

			var lastTweet = data[0];
			var borderTweet = data[frequency - 1];
			var borderTime = new Date(borderTweet.created_at);
			var lastTime = new Date(lastTweet.created_at);

			if (lastTime - borderTime < 10 * 60 * 1000) {
				twitter.post('hakatashi', 'statuses/update', {
					status: '@hideo54 勉強しろ' + repeat('!', alertTimes),
					in_reply_to_status_id: lastTweet.id_str
				});

				lastAlert = lastTweet.id_str;
				alertTimes++;
			}

			fs.writeFile(__dirname + '/lastalert.txt', lastAlert);
		});
	});
}, null, true, 'Asia/Tokyo');
<commit_msg>Change alert frequency to 5<commit_after>var CronJob = require('cron').CronJob;
var time = require('time');
var fs = require('fs');

var twitter = require('../twitter');

var alertTimes = 0;

var frequency = 5;

function repeat(string, times) {
	var ret = '';
	for (var i = 0; i < times; i++) ret += string;
	return ret;
}

module.exports = new CronJob('00 * * * * *', function () {
	var now = new Date();

	fs.readFile(__dirname + '/lastalert.txt', function (error, data) {
		if (error) return console.error(error);

		var lastAlert = data.toString();

		twitter.get('hakatashi', 'statuses/user_timeline', {
			screen_name: 'hideo54',
			since_id: lastAlert,
			count: frequency,
			include_rts: false
		}, function (error, responce, data) {
			if (error) return console.error(error);
			if (data.length < frequency) return;

			var lastTweet = data[0];
			var borderTweet = data[frequency - 1];
			var borderTime = new Date(borderTweet.created_at);
			var lastTime = new Date(lastTweet.created_at);

			if (lastTime - borderTime < 10 * 60 * 1000) {
				twitter.post('hakatashi', 'statuses/update', {
					status: '@hideo54 勉強しろ' + repeat('!', alertTimes),
					in_reply_to_status_id: lastTweet.id_str
				});

				lastAlert = lastTweet.id_str;
				alertTimes++;
			}

			fs.writeFile(__dirname + '/lastalert.txt', lastAlert);
		});
	});
}, null, true, 'Asia/Tokyo');
<|endoftext|>


<commit_before>/* This is a bit of hacky code to pop up a debug window */
var _debug_window;
function debug_window() {
  if( _debug_window ) { return; }
  _debug_window=window.open('','__debug','height=400,width=600');
  D = _debug_window.document;
  h_3 = D.createElement( 'h3' );
  h_3.appendChild( D.createTextNode('HI!') );
  D.documentElement.appendChild(h_3);
  D.documentElement.style.fontSize = '0.7em';
  h_3.style.marginWidth = '0px';
  u_l = D.createElement( 'ul' );
  u_l.style.marginWidth = '0px';
  u_l.setAttribute('id','debug_list');
  D.documentElement.appendChild(u_l);
}

function debug( string ) {
  if( _debug_window ) {
    D = _debug_window.document;
    l_i = D.createElement( 'li' );
    l_i.documentElement.style.margin = '0px';
    l_i.appendChild(D.createTextNode( string ) );
    D.getElementById( 'debug_list' ).appendChild(l_i);
    _debug_window.focus();
  } else {
    alert( string );
  }
}

function debug_clear( ) {
  if( _debug_window ) {
    D = _debug_window.document;
    u_l = D.getElementById( 'debug_list' );
    while(u_l.hasChildNodes()) {
      u_l.removeChild(u_l.firstChild);
    }
  }
}

function toggle_settings_drawer() {
  if ($('settings').style.display == 'none') {
    $('settings_link').innerHTML = 'Hide account';
    new Effect.BlindDown('settings');
  } else {
    $('settings_link').innerHTML = 'Show account';
    new Effect.BlindUp('settings');
  }
}

function settings_drawer_change() {
  var display_id = $('group_select').value;
  set_style_for_class('all', 'none');
  set_style_for_class(display_id, '');
  save_drawer_change(display_id);
}

function getElementsByClass(searchClass,node,tag) {
  var classElements = new Array();
  if ( node == null )
    node = document;
  if ( tag == null )
    tag = '*';
  var els = node.getElementsByTagName(tag);
  var elsLen = els.length;
  var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
  for (i = 0, j = 0; i < elsLen; i++) {
    if ( pattern.test(els[i].className) ) {
      classElements[j] = els[i];
      j++;
    }
  }
  return classElements;
}

function save_drawer_change(ident) {
  var url = "/common/drawer";
  var data = "group=" + ident;
  var ajax_info = new Ajax.Request(url, {
                           method: 'get',
                           parameters: data,
                           onComplete: drawer_change_saved
                         });
}

function drawer_change_saved(response) {
}

function set_style_for_class(new_class,style) {
  var elements = getElementsByClass(new_class);
  for (var i = 0; i < elements.length; i++) {
    elements[i].style.display = style;
  }
}

// Return a link based on the current URL to the archive...

function addLoadEvent(func) {
  var oldonload = window.onload;
  if( typeof window.onload != 'function' ) {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

function cytoview_link() {
  URL = document.location.href;
  document.location = URL.replace(/(\w+view)/,'cytoview');
  return true;
}

function archive( release ) {
  URL = document.location.href;
  document.location = URL.replace(/^https?:\/\/[^\/]+/,'http://'+release+'.archive.ensembl.org');
  return true;
}

function login_link() {
  URL = escape(document.location.href);
  document.location = '/common/user/login?url=' + URL;
  return true;
}

function logout_link() {
  URL = escape(document.location.href);
  document.location = '/common/user/logout?url=' + URL;
  return true;
}

function das_link() {
  URL = escape(document.location.href);
  document.location = '/common/user/save_das?url=' + URL;
  return true;
}

function add_config(ident) {
  URL = escape(document.location.href);
  var location = '/common/user/configuration?url=' + URL;
  if (ident) {
    location = location + ';id=' + ident;
  }
  document.location = location;
  return true;
}

function change_config(ident) {
  URL = escape(document.location.href);
  var location = '/common/user/configuration?dataview=edit;url=' + URL;
  if (ident) {
    location = location + ';id=' + ident;
  }
  document.location = location;
  return true;
}

function load_config(config_id) {
  URL = escape(document.location.href);
  document.location = '/common/user/load_config?id=' + config_id + ';url=' + URL;
  return true;
}

function go_to_config(config_id) {
  document.location = '/common/user/load_config?id=' + config_id;
  return true;
}

function bookmark_link() {
  URL = escape(document.location.href);

  var page_title;
  titles = document.getElementsByTagName("title");
  // assume first title tag is actual page title
  children = titles[0].childNodes;
  for (i=0; i<children.length; i++) {
    child = children[i];
    // look for text node
    if (child.nodeType == 3) {
      page_title = child.nodeValue;
    }
  }

  document.location = '/common/user/bookmark?name=' + page_title + ';url=' + URL;
  return true;
}

function account_return() {
  var cookieKey = 'ENSEMBL_USER_REFERER';
  if (!readCookie(cookieKey)) {
    document.location = '/index.html';
  } else {
    document.location = unescape(readCookie(cookieKey));
  }
}

function ajaxCapability() {

//  window.onerror = errorSuppression;

  var cookieKey = 'ENSEMBL_AJAX';

  if (!readCookie(cookieKey)) {

  var useActiveX = false;
  var javaIsAvailable = false;
  var httpobj;
  var browserVersion = parseInt(window.navigator.appVersion);
  var browserName = window.navigator.appName;
  var ajaxCapability = "none";

  if (!(browserName.indexOf("Microsoft Internet Explorer"))) {
    if (typeof ScriptEngine != "undefined") {
      if (ScriptEngineMajorVersion() > 2) {
        httpobj = new ActiveXObject('Msxml2.XMLHTTP');
        if ((!httpobj) ||  (typeof httpobj == 'undefined')) httpobj = new ActiveXObject('Microsoft.XMLHTTP');
        if ((httpobj) ||  (typeof httpobj != 'undefined')) useActiveX = true;
      }
    }
  } else {
    useActiveX = false;
    if (window.navigator.javaEnabled() == true) javaIsAvailable = true;
    httpobj = new XMLHttpRequest();
  }

  if ((!httpobj) || (typeof httpobj == 'undefined')) {
    if (javaIsAvailable == true) {
      ajaxCapability = "java";
    } else {
      if ((browserVersion >= 3)  && (browserName.indexOf("Netscape"))) {
        ajaxCapability = "iframe";
      } else {
        ajaxCapability = "ilayer";
      }
      if (browserVersion < 3) {
        ajaxCapability = "none";
      }
    }
  } else {
    if (useActiveX == true) {
      ajaxCapability = "activex";
    } else {
      ajaxCapability = "builtin";
    }
  }

  createCookie(cookieKey, ajaxCapability, 30);
  }
}

function createCookie(name,value,days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  } else {
    var expires = "";
  }
  document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

ajaxCapability();
<commit_msg>helper functions for sequencealignview<commit_after>/* functions for sequencealignview : select / deselect all options in the group */
function deselectAll( group) {
  var clist = document.getElementsByName(group);
  for (i = 0; i < clist.length; i++) {
    clist[i].checked = false;
  }
}
function selectAll( group) {
  var clist = document.getElementsByName(group);
  for (i = 0; i < clist.length; i++) {
    clist[i].checked = true;
  }
}

/* This is a bit of hacky code to pop up a debug window */

var _debug_window;
function debug_window() {
  if( _debug_window ) { return; }
  _debug_window=window.open('','__debug','height=400,width=600');
  D = _debug_window.document;
  h_3 = D.createElement( 'h3' );
  h_3.appendChild( D.createTextNode('HI!') );
  D.documentElement.appendChild(h_3);
  D.documentElement.style.fontSize = '0.7em';
  h_3.style.marginWidth = '0px';
  u_l = D.createElement( 'ul' );
  u_l.style.marginWidth = '0px';
  u_l.setAttribute('id','debug_list');
  D.documentElement.appendChild(u_l);
}

function debug( string ) {
  if( _debug_window ) {
    D = _debug_window.document;
    l_i = D.createElement( 'li' );
    l_i.documentElement.style.margin = '0px';
    l_i.appendChild(D.createTextNode( string ) );
    D.getElementById( 'debug_list' ).appendChild(l_i);
    _debug_window.focus();
  } else {
    alert( string );
  }
}

function debug_clear( ) {
  if( _debug_window ) {
    D = _debug_window.document;
    u_l = D.getElementById( 'debug_list' );
    while(u_l.hasChildNodes()) {
      u_l.removeChild(u_l.firstChild);
    }
  }
}

function toggle_settings_drawer() {
  if ($('settings').style.display == 'none') {
    $('settings_link').innerHTML = 'Hide account';
    new Effect.BlindDown('settings');
  } else {
    $('settings_link').innerHTML = 'Show account';
    new Effect.BlindUp('settings');
  }
}

function settings_drawer_change() {
  var display_id = $('group_select').value;
  set_style_for_class('all', 'none');
  set_style_for_class(display_id, '');
  save_drawer_change(display_id);
}

function getElementsByClass(searchClass,node,tag) {
  var classElements = new Array();
  if ( node == null )
    node = document;
  if ( tag == null )
    tag = '*';
  var els = node.getElementsByTagName(tag);
  var elsLen = els.length;
  var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
  for (i = 0, j = 0; i < elsLen; i++) {
    if ( pattern.test(els[i].className) ) {
      classElements[j] = els[i];
      j++;
    }
  }
  return classElements;
}

function save_drawer_change(ident) {
  var url = "/common/drawer";
  var data = "group=" + ident;
  var ajax_info = new Ajax.Request(url, {
                           method: 'get',
                           parameters: data,
                           onComplete: drawer_change_saved
                         });
}

function drawer_change_saved(response) {
}

function set_style_for_class(new_class,style) {
  var elements = getElementsByClass(new_class);
  for (var i = 0; i < elements.length; i++) {
    elements[i].style.display = style;
  }
}

// Return a link based on the current URL to the archive...

function addLoadEvent(func) {
  var oldonload = window.onload;
  if( typeof window.onload != 'function' ) {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

function cytoview_link() {
  URL = document.location.href;
  document.location = URL.replace(/(\w+view)/,'cytoview');
  return true;
}

function archive( release ) {
  URL = document.location.href;
  document.location = URL.replace(/^https?:\/\/[^\/]+/,'http://'+release+'.archive.ensembl.org');
  return true;
}

function login_link() {
  URL = escape(document.location.href);
  document.location = '/common/user/login?url=' + URL;
  return true;
}

function logout_link() {
  URL = escape(document.location.href);
  document.location = '/common/user/logout?url=' + URL;
  return true;
}

function das_link() {
  URL = escape(document.location.href);
  document.location = '/common/user/save_das?url=' + URL;
  return true;
}

function add_config(ident) {
  URL = escape(document.location.href);
  var location = '/common/user/configuration?url=' + URL;
  if (ident) {
    location = location + ';id=' + ident;
  }
  document.location = location;
  return true;
}

function change_config(ident) {
  URL = escape(document.location.href);
  var location = '/common/user/configuration?dataview=edit;url=' + URL;
  if (ident) {
    location = location + ';id=' + ident;
  }
  document.location = location;
  return true;
}

function load_config(config_id) {
  URL = escape(document.location.href);
  document.location = '/common/user/load_config?id=' + config_id + ';url=' + URL;
  return true;
}

function go_to_config(config_id) {
  document.location = '/common/user/load_config?id=' + config_id;
  return true;
}

function bookmark_link() {
  URL = escape(document.location.href);

  var page_title;
  titles = document.getElementsByTagName("title");
  // assume first title tag is actual page title
  children = titles[0].childNodes;
  for (i=0; i<children.length; i++) {
    child = children[i];
    // look for text node
    if (child.nodeType == 3) {
      page_title = child.nodeValue;
    }
  }

  document.location = '/common/user/bookmark?name=' + page_title + ';url=' + URL;
  return true;
}

function account_return() {
  var cookieKey = 'ENSEMBL_USER_REFERER';
  if (!readCookie(cookieKey)) {
    document.location = '/index.html';
  } else {
    document.location = unescape(readCookie(cookieKey));
  }
}

function ajaxCapability() {

//  window.onerror = errorSuppression;

  var cookieKey = 'ENSEMBL_AJAX';

  if (!readCookie(cookieKey)) {

  var useActiveX = false;
  var javaIsAvailable = false;
  var httpobj;
  var browserVersion = parseInt(window.navigator.appVersion);
  var browserName = window.navigator.appName;
  var ajaxCapability = "none";

  if (!(browserName.indexOf("Microsoft Internet Explorer"))) {
    if (typeof ScriptEngine != "undefined") {
      if (ScriptEngineMajorVersion() > 2) {
        httpobj = new ActiveXObject('Msxml2.XMLHTTP');
        if ((!httpobj) ||  (typeof httpobj == 'undefined')) httpobj = new ActiveXObject('Microsoft.XMLHTTP');
        if ((httpobj) ||  (typeof httpobj != 'undefined')) useActiveX = true;
      }
    }
  } else {
    useActiveX = false;
    if (window.navigator.javaEnabled() == true) javaIsAvailable = true;
    httpobj = new XMLHttpRequest();
  }

  if ((!httpobj) || (typeof httpobj == 'undefined')) {
    if (javaIsAvailable == true) {
      ajaxCapability = "java";
    } else {
      if ((browserVersion >= 3)  && (browserName.indexOf("Netscape"))) {
        ajaxCapability = "iframe";
      } else {
        ajaxCapability = "ilayer";
      }
      if (browserVersion < 3) {
        ajaxCapability = "none";
      }
    }
  } else {
    if (useActiveX == true) {
      ajaxCapability = "activex";
    } else {
      ajaxCapability = "builtin";
    }
  }

  createCookie(cookieKey, ajaxCapability, 30);
  }
}

function createCookie(name,value,days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  } else {
    var expires = "";
  }
  document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

ajaxCapability();
<|endoftext|>


<commit_before>(function(root){
function websocket(dop, node, options) {

    var url = 'ws://localhost:4444/'+dop.name,
        args = arguments;

    if (typeof options.url == 'string')
        url = options.url.replace('http','ws');
    else if (typeof window!='undefined' && /http/.test(window.location.href)) {
        var domain_prefix = /(ss|ps)?:\/\/([^\/]+)\/?(.+)?/.exec(window.location.href),
            protocol = domain_prefix[1] ? 'wss' : 'ws';
        url = protocol+'://'+domain_prefix[2].toLocaleLowerCase()+'/'+dop.name;
    }

    var api = options.transport.getApi(),
        socket = new api(url),
        send_queue = [];

    // We use this function as alias to store messages when connection is not OPEN
    function send(message) {
        (socket.readyState === socket.constructor.OPEN) ? socket.send(message) : send_queue.push(message);
    }
    function sendQueue(message) {
        while (send_queue.length>0)
            send(send_queue.shift());
    }

    node.readyState = dop.CONS.CLOSE;
    node.reconnect = function() {
        oldSocket = node.socket;
        node.socket = node.options.transport.apply(node, args);
        node.readyState = dop.CONS.RECONNECT;
    };
    node.once(dop.CONS.CONNECT, function() {
        node.readyState = dop.CONS.CONNECT;
        dop.core.emitConnect(node);
        sendQueue();
    });
    node.on(dop.CONS.SEND, function(message) {
        send(message);
    });
    node.on(dop.CONS.DISCONNECT, function() {
        node.readyState = dop.CONS.CLOSE;
        socket.close();
    });

    socket.addEventListener('open', function() {
        // Reconnect
        if (node.readyState === dop.CONS.RECONNECT) {
            send(node.tokenServer);
            sendQueue();
        }
        // Connect
        else {
            send(); // Empty means we want to get connected
            node.readyState = dop.CONS.OPEN;
        }
        dop.core.emitOpen(node, socket, options.transport);
    });
    socket.addEventListener('message', function(message) {
        // Reconnecting
        if (message.data===node.tokenServer && node.readyState===dop.CONS.RECONNECT) {
            node.readyState = dop.CONS.CONNECT;
            dop.core.emitReconnectClient(node, oldSocket);
        }
        else
            dop.core.emitMessage(node, socket, message.data, message);
    });
    socket.addEventListener('close', function() {
        dop.core.emitClose(node, socket);
    });

    return socket;
};

if (typeof dop=='undefined' && typeof module == 'object' && module.exports)
    module.exports = websocket;
else {
    websocket.getApi = function() { return window.WebSocket };
    (typeof dop != 'undefined') ?
        dop.transports.connect.websocket = websocket
    :
        root.dopTransportsConnectWebsocket = websocket;
}

})(this);<commit_msg>Test protocol_reconnect passed<commit_after>(function(root){
function websocket(dop, node, options) {

    var url = 'ws://localhost:4444/'+dop.name,
        args = arguments;

    if (typeof options.url == 'string')
        url = options.url.replace('http','ws');
    else if (typeof window!='undefined' && /http/.test(window.location.href)) {
        var domain_prefix = /(ss|ps)?:\/\/([^\/]+)\/?(.+)?/.exec(window.location.href),
            protocol = domain_prefix[1] ? 'wss' : 'ws';
        url = protocol+'://'+domain_prefix[2].toLocaleLowerCase()+'/'+dop.name;
    }

    var api = options.transport.getApi(),
        socket = new api(url),
        send_queue = [];

    // We use this function as alias to store messages when connection is not OPEN
    function send(message) {
        (socket.readyState === socket.constructor.OPEN && node.readyState === dop.CONS.CONNECT) ?
            socket.send(message)
        :
            console.log( 'save', message );
    }

    // This function emit all the queue messages
    function sendQueue(message) {
        while (send_queue.length>0)
            socket.send(send_queue.shift());
    }

    function onopen() {
        // Reconnect
        if (node.readyState === dop.CONS.RECONNECT) {
            socket.send(node.tokenServer);
        }
        // Connect
        else {
            socket.send(''); // Empty means we want to get connected
            node.readyState = dop.CONS.OPEN;
        }
        dop.core.emitOpen(node, socket, options.transport);
    }
    function onmessage(message) {
        // // Reconnecting
        // if (message.data===node.tokenServer && node.readyState===dop.CONS.RECONNECT) {
        //     node.readyState = dop.CONS.CONNECT;
        //     dop.core.emitReconnectClient(node, oldSocket);
        //     sendQueue();
        // }
        // else
            dop.core.emitMessage(node, socket, message.data, message);
    }
    function onclose() {
        dop.core.emitClose(node, socket);
    }

    node.readyState = dop.CONS.CLOSE;
    // node.reconnect = function() {
    //     oldSocket = socket;
    //     node.socket = socket = new api(url);
    //     addListeners(socket, onopen, onmessage, onclose);
    //     removeListeners(oldSocket, onopen, onmessage, onclose);
    //     node.readyState = dop.CONS.RECONNECT;
    // };
    node.on(dop.CONS.CONNECT, function() {
        node.readyState = dop.CONS.CONNECT;
        dop.core.emitConnect(node);
    });
    node.on(dop.CONS.SEND, function(message) {
        send(message);
    });
    node.on(dop.CONS.DISCONNECT, function() {
        node.readyState = dop.CONS.CLOSE;
        socket.close();
    });

    addListeners(socket, onopen, onmessage, onclose);

    return socket;
};

function addListeners(socket, onopen, onmessage, onclose) {
    socket.addEventListener('open', onopen);
    socket.addEventListener('message', onmessage);
    socket.addEventListener('close', onclose);
}
function removeListeners(socket, onopen, onmessage, onclose) {
    socket.removeEventListener('open', onopen);
    socket.removeEventListener('message', onmessage);
    socket.removeEventListener('close', onclose);
}

// UMD
if (typeof dop=='undefined' && typeof module == 'object' && module.exports)
    module.exports = websocket;
else {
    websocket.getApi = function() { return window.WebSocket };
    (typeof dop != 'undefined') ?
        dop.transports.connect.websocket = websocket
    :
        root.dopTransportsConnectWebsocket = websocket;
}

})(this);<|endoftext|>


<commit_before>var VersionInfo = require('./lib/versionInfo')
var execute = require('./lib/execute')

const isWindows = process.platform === 'win32'
const isDarwin = process.platform === 'darwin'
const arch = 'x64'
const buildDir = 'Brave-' + process.platform + '-' + arch

var appIcon
if (isWindows) {
  appIcon = 'res/app.ico'
} else if (isDarwin) {
  appIcon = 'res/app.icns'
} else {
  appIcon = 'res/app.png'
}

var env = {
  NODE_ENV: 'production'
}

console.log('Building version ' + VersionInfo.braveVersion + ' in ' + buildDir + ' with Electron ' + VersionInfo.electronVersion)

var cmds = [
  'rm -rf ' + buildDir,
  'rm -f dist/*.dmg dist/*.nupkg dist/*.exe dist/*.msi dist/RELEASES dist/*.zip',
  '"./node_modules/.bin/webpack"',
  'npm run checks',
  'node ./node_modules/electron-packager/cli.js . Brave' +
    ' --overwrite' +
    ' --ignore="electron-download|electron-rebuild|electron-packager|electron-builder|electron-prebuilt|electron-rebuild|babel$|babel-(?!polyfill|regenerator-runtime)"' +
    ' --platform=' + process.platform +
    ' --arch=' + arch +
    ' --version=' + VersionInfo.electronVersion +
    ' --icon=' + appIcon +
    ' --asar=true' +
    ' --app-version=' + VersionInfo.braveVersion +
    ' --build-version=' + VersionInfo.electronVersion +
    ' --protocol="http" --protocol-name="HTTP Handler"' +
    ' --protocol="https" --protocol-name="HTTPS Handler"' +
    ' --version-string.CompanyName=\"Brave Inc.\"' +
    ' --version-string.ProductName=\"Brave\"' +
    ' --version-string.Copyright=\"Copyright 2016, Brave Inc.\"' +
    ' --version-string.FileDescription=\"Brave\"'
]

execute(cmds, env, console.log.bind(null, 'done'))
<commit_msg>Remove dependency on gnu rm for Windows builds<commit_after>var VersionInfo = require('./lib/versionInfo')
var execute = require('./lib/execute')

const isWindows = process.platform === 'win32'
const isDarwin = process.platform === 'darwin'
const arch = 'x64'
const buildDir = 'Brave-' + process.platform + '-' + arch

var appIcon
if (isWindows) {
  appIcon = 'res/app.ico'
} else if (isDarwin) {
  appIcon = 'res/app.icns'
} else {
  appIcon = 'res/app.png'
}

var env = {
  NODE_ENV: 'production'
}

console.log('Cleaning build target')

if (isWindows) {
  var cmds = [
    'if exist ' + buildDir + ' rmdir /s /q ' + buildDir,
  ]
  execute(cmds, env, console.log.bind(null, 'done'))
} else {
  var cmds = [
    'rm -rf ' + buildDir,
    'rm -f dist/*.dmg dist/*.nupkg dist/*.exe dist/*.msi dist/RELEASES dist/*.zip',
  ]
  execute(cmds, env, console.log.bind(null, 'done'))
}

console.log('Building version ' + VersionInfo.braveVersion + ' in ' + buildDir + ' with Electron ' + VersionInfo.electronVersion)

var cmds = [
  '"./node_modules/.bin/webpack"',
  'npm run checks',
  'node ./node_modules/electron-packager/cli.js . Brave' +
    ' --overwrite' +
    ' --ignore="electron-download|electron-rebuild|electron-packager|electron-builder|electron-prebuilt|electron-rebuild|babel$|babel-(?!polyfill|regenerator-runtime)"' +
    ' --platform=' + process.platform +
    ' --arch=' + arch +
    ' --version=' + VersionInfo.electronVersion +
    ' --icon=' + appIcon +
    ' --asar=true' +
    ' --app-version=' + VersionInfo.braveVersion +
    ' --build-version=' + VersionInfo.electronVersion +
    ' --protocol="http" --protocol-name="HTTP Handler"' +
    ' --protocol="https" --protocol-name="HTTPS Handler"' +
    ' --version-string.CompanyName=\"Brave Inc.\"' +
    ' --version-string.ProductName=\"Brave\"' +
    ' --version-string.Copyright=\"Copyright 2016, Brave Inc.\"' +
    ' --version-string.FileDescription=\"Brave\"'
]

execute(cmds, env, console.log.bind(null, 'done'))
<|endoftext|>


<commit_before>`/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.INTERFACE({
  package: 'foam.dao',
  name: 'DAODecorator',
  methods: [
    {
      name: 'write',
      returns: 'Promise',
      javaReturns: 'foam.core.FObject',
      args: [
        {
          name: 'context'
        },
        {
          name: 'dao'
        },
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        },
        {
          name: 'existing',
          javaType: 'foam.core.FObject'
        }
      ]
    },
    {
      name: 'read',
      returns: 'Promise',
      javaReturns: 'foam.core.FObject',
      args: [
        {
          name: 'context'
        },
        {
          name: 'dao'
        },
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        }
      ]
    },
    {
      name: 'remove',
      returns: 'Promise',
      javaReturns: 'foam.core.FObject',
      args: [
        {
          name: 'context'
        },
        {
          name: 'dao'
        },
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        }
      ]
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'CascadingRemoveDecorator',
  implements: [ 'foam.dao.DAODecorator' ],
  mehtods: [
    function read(X, dao, obj) {
    },
    function write(X, dao, obj, existing) {
    },
    function remove(X, dao, obj) {
      obj.
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'DecoratedDAO',
  extends: 'foam.dao.ProxyDAO',
  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.dao.DAODecorator',
      name: 'decorator'
    }
  ],
  methods: [
    {
      name: 'put',
      code: function(obj) {
        var self = this;
        return this.delegate.find(obj.id).then(function(existing) {
          return self.decorator.write(obj, existing);
        }, function() {
          return self.decorator.write(obj, null);
        }).then(function(newObj) {
          return self.delegate.put(newObj);
        });
      }
    },
    {
      name: 'remove',
      code: function(obj) {
      }
    },
    {
      name: 'find',
      code: function(id) {
        var self = this;
        return this.SUPER(id).then(function(o) {
          return self.decorator.read(o);
        });
      }
    }
    // TODO: Select/removeAll support.  How do we do select
    // without breaking MDAO optimizations?
    // {
    //   name: 'select',
    //   code: function() {
    //   }
    // },
    // {
    //   name: 'removeAll',
    //   code: function() {
    //   }
    // }
  ]
});<commit_msg>Fixed invalid chars in DAODecorator.js breaking coverage<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.INTERFACE({
  package: 'foam.dao',
  name: 'DAODecorator',
  methods: [
    {
      name: 'write',
      returns: 'Promise',
      javaReturns: 'foam.core.FObject',
      args: [
        {
          name: 'context'
        },
        {
          name: 'dao'
        },
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        },
        {
          name: 'existing',
          javaType: 'foam.core.FObject'
        }
      ]
    },
    {
      name: 'read',
      returns: 'Promise',
      javaReturns: 'foam.core.FObject',
      args: [
        {
          name: 'context'
        },
        {
          name: 'dao'
        },
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        }
      ]
    },
    {
      name: 'remove',
      returns: 'Promise',
      javaReturns: 'foam.core.FObject',
      args: [
        {
          name: 'context'
        },
        {
          name: 'dao'
        },
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        }
      ]
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'CascadingRemoveDecorator',
  implements: [ 'foam.dao.DAODecorator' ],
  mehtods: [
    function read(X, dao, obj) {
    },
    function write(X, dao, obj, existing) {
    },
    function remove(X, dao, obj) {
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'DecoratedDAO',
  extends: 'foam.dao.ProxyDAO',
  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.dao.DAODecorator',
      name: 'decorator'
    }
  ],
  methods: [
    {
      name: 'put',
      code: function(obj) {
        var self = this;
        return this.delegate.find(obj.id).then(function(existing) {
          return self.decorator.write(obj, existing);
        }, function() {
          return self.decorator.write(obj, null);
        }).then(function(newObj) {
          return self.delegate.put(newObj);
        });
      }
    },
    {
      name: 'remove',
      code: function(obj) {
      }
    },
    {
      name: 'find',
      code: function(id) {
        var self = this;
        return this.SUPER(id).then(function(o) {
          return self.decorator.read(o);
        });
      }
    }
    // TODO: Select/removeAll support.  How do we do select
    // without breaking MDAO optimizations?
    // {
    //   name: 'select',
    //   code: function() {
    //   }
    // },
    // {
    //   name: 'removeAll',
    //   code: function() {
    //   }
    // }
  ]
});<|endoftext|>


<commit_before>for ( var key in foam.UNUSED ) { foam.lookup(key); }

foam.CLASS({
  package: 'foam.doc',
  name: 'AxiomInfo',

  properties: [
    {
      name: 'axiom',
      hidden: true
    },
    {
      name: 'cls',
      label: 'Source Class',
      tableCellView: function(o, e) {
        return foam.doc.LinkView.create({data: o.cls}, e.__subSubContext__);
      }
    },
    {
      name: 'type',
      tableCellView: function(o, e) {
        return o.type ?
          foam.doc.LinkView.create({data: foam.doc.Link.create({path: o.type.id, label: o.type.name})}, e.__subSubContext__) :
          'anonymous';
      }
    },
    {
      name: 'name'
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassList',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.ClassLink'
  ],

  methods: [
    function initE() {
      this.SUPER();

      var self = this;

      this.data.forEach(function(cls) {
        self.start(self.ClassLink, {data: cls, showPackage: true}).end().br();
      });
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassDocView',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.Link',
    'foam.doc.ClassLink',
    'foam.doc.AxiomInfo',
    'foam.u2.TableView',
    'foam.dao.ArrayDAO'
  ],

  methods: [
    function initE() {
      this.SUPER();

      var data = this.data;

      this.add('CLASS: ', data.name, ' (', data.count_, ')').br();
      this.add('extends: ');
      var cls = data;
      for ( var i = 0 ; cls ; i++ ) {
        cls = this.lookup(cls.model_.extends, true);
        if ( i ) this.add(' : ');
        this.start(this.ClassLink, {data: cls}).end();
        if ( cls === foam.core.FObject ) break;
      }
      this.br();
      this.add(data.documentation);

      var axs = [];
      for ( var key in data.axiomMap_ ) {
        var a = data.axiomMap_[key];
        var ai = foam.doc.AxiomInfo.create({
          axiom: a,
          type: a.cls_,
          cls: this.Link.create({
            path: a.sourceCls_.id,
            label: a.sourceCls_.name
          }),
          name: a.name
        });
        axs.push(ai);
      }

      this.add(this.TableView.create({
        of: this.AxiomInfo,
        data: this.ArrayDAO.create({array: axs})
      }));
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'Link',

  properties: [
    'path',
    'label'
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'LinkView',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.path}).
        add(this.data.label);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.path);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassLink',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  properties: [
    {
      class: 'Class',
      name: 'data'
    },
    {
      class: 'Boolean',
      name: 'showPackage'
    }
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.id}).
        add(this.showPackage ? this.data.id : this.data.name);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.id);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'DocBrowser',
  extends: 'foam.u2.Element',

  requires: [
    'foam.doc.ClassList',
    'foam.doc.ClassDocView'
  ],

  exports: [
    'as data',
    'path as browserPath'
  ],

  properties: [
    'path',
    {
      class: 'FObjectProperty',
      name: 'axiom'
    }
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.add('Path: ', this.PATH).br().br();

      this.
        start('table').
          start('tr').
            start('td').
              style({'vertical-align': 'top', background: '#eee' }).
              start(this.ClassList, {data: Object.values(foam.USED).sort()}).
            end().
            start('td').
              add(this.slot(function(path) {
                var o = foam.lookup(path, true);
                if ( ! o ) return '';
                return this.ClassDocView.create({data: o});
              })).
            end().
            start('td').
              add(this.AXIOM).
            end().
          end().
        end();
    }
  ]
});

// foam.doc.ClassDocView.create({data: foam.core.Property}).write();

foam.doc.DocBrowser.create({path: 'foam.core.Property'}).write();
<commit_msg>DocBrowser.<commit_after>for ( var key in foam.UNUSED ) { foam.lookup(key); }

foam.CLASS({
  package: 'foam.doc',
  name: 'AxiomInfo',

  properties: [
    {
      name: 'axiom',
      hidden: true
    },
    {
      name: 'cls',
      label: 'Source Class',
      tableCellView: function(o, e) {
        return foam.doc.LinkView.create({data: o.cls}, e.__subSubContext__);
      }
    },
    {
      name: 'type',
      tableCellView: function(o, e) {
        return o.type ?
          foam.doc.LinkView.create({data: foam.doc.Link.create({path: o.type.id, label: o.type.name})}, e.__subSubContext__) :
          'anonymous';
      }
    },
    {
      name: 'name'
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassList',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.ClassLink'
  ],

  methods: [
    function initE() {
      this.SUPER();

      var self = this;

      this.add('(', this.data.length, ')').br();

      this.data.forEach(function(cls) {
        self.start(self.ClassLink, {data: cls, showPackage: true}).end().br();
      });
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassDocView',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.Link',
    'foam.doc.ClassLink',
    'foam.doc.AxiomInfo',
    'foam.u2.TableView',
    'foam.dao.ArrayDAO'
  ],

  methods: [
    function initE() {
      this.SUPER();

      var data = this.data;

      this.add('CLASS: ', data.name, ' (', data.count_, ')').br();
      this.add('extends: ');
      var cls = data;
      for ( var i = 0 ; cls ; i++ ) {
        cls = this.lookup(cls.model_.extends, true);
        if ( i ) this.add(' : ');
        this.start(this.ClassLink, {data: cls}).end();
        if ( cls === foam.core.FObject ) break;
      }
      this.br();
      this.add(data.documentation);

      var axs = [];
      for ( var key in data.axiomMap_ ) {
        var a = data.axiomMap_[key];
        var ai = foam.doc.AxiomInfo.create({
          axiom: a,
          type: a.cls_,
          cls: this.Link.create({
            path: a.sourceCls_.id,
            label: a.sourceCls_.name
          }),
          name: a.name
        });
        axs.push(ai);
      }

      this.add(this.TableView.create({
        of: this.AxiomInfo,
        data: this.ArrayDAO.create({array: axs})
      }));
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'Link',

  properties: [
    'path',
    'label'
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'LinkView',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.path}).
        add(this.data.label);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.path);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassLink',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  properties: [
    {
      class: 'Class',
      name: 'data'
    },
    {
      class: 'Boolean',
      name: 'showPackage'
    }
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.id}).
        add(this.showPackage ? this.data.id : this.data.name);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.id);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'DocBrowser',
  extends: 'foam.u2.Element',

  requires: [
    'foam.doc.ClassList',
    'foam.doc.ClassDocView'
  ],

  exports: [
    'as data',
    'path as browserPath'
  ],

  properties: [
    'path',
    {
      class: 'FObjectProperty',
      name: 'axiom'
    }
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.add('Path: ', this.PATH).br().br();

      this.
        start('table').
          start('tr').
            start('td').
              style({'vertical-align': 'top', background: '#f5f5ea' }).
              start(this.ClassList, {data: Object.values(foam.USED).sort(foam.core.Model.ID.compare)}).
            end().
            start('td').
              style({'vertical-align': 'top', background: '#f5f5ea' }).
              add(this.slot(function(path) {
                var o = foam.lookup(path, true);
                if ( ! o ) return '';
                return this.ClassDocView.create({data: o});
              })).
            end().
            start('td').
              style({'vertical-align': 'top', background: '#f5f5ea' }).
              add(this.AXIOM).
            end().
          end().
        end();
    }
  ]
});

// foam.doc.ClassDocView.create({data: foam.core.Property}).write();

foam.doc.DocBrowser.create({path: 'foam.core.Property'}).write();
<|endoftext|>


<commit_before>// REACT COMPONENTS
import React from 'react';
import {
  Form,
  Radio,
  Checkbox,
  Header
} from 'semantic-ui-react';

// PROJECT COMPONENTS
import {
  FormPartsContainer,
  // MassiveToggle,
  FormHeading,
  IntervalColumnHeadings,
  CashFlowRow
} from './formHelpers';
import {
  ContractRentField,
  RentShareField,
  PlainRentRow
} from './rentFields';
import CashFlowRowWithPrompt from './CashFlowRowWithPrompt';

// COMPONENT HELPER FUNCTIONS
import { getTimeSetter } from '../utils/getTimeSetter';

// LOGIC
import {
  getEveryMember,
  isHeadOrSpouse,
  getDependentMembers,
  isDisabled,
  isUnder13,
} from '../utils/getMembers';

// ========================================
// COMPONENTS
// ========================================

const Utilities = function ({ current, type, time, setClientProperty }) {

  let climate     = current.climateControl,
      electricity = current.nonHeatElectricity,
      phone       = current.phone,
      fuelAssist  = current.fuelAssistance;

  let setChecked = function ( evnt, inputProps ) {
    var obj = { ...inputProps, value: inputProps.checked };
    setClientProperty( evnt, obj );
  };  // End setChecked()

  return (

      Which of these utilities do you pay for?

      <Checkbox
        name={'climateControl'}
        label={'Heating or cooling (e.g. A/C during summer)'}
        checked={climate}
        onChange={setChecked}
      />

      <Checkbox
        name={'nonHeatElectricity'}
        label={'Electricity for non-heating purposes'}
        checked={electricity}
        onChange={setChecked}
      />

      <Checkbox
        name={'phone'}
        label={'Telephone service'}
        checked={phone}
        onChange={setChecked}
      />

      Do you get Fuel Assistance?
      <Form.Field style={{display: 'inline-block', paddingRight: '1em'}}>
        <Radio
          name={'fuelAssistance'}
          label={'Yes'} value={'Yes'}
          checked={fuelAssist}
          onChange={setClientProperty}
        />
      </Form.Field>
      <Form.Field style={{display: 'inline-block', paddingRight: '1em'}}>
        <Radio
          name={'fuelAssistance'}
          label={'No'} value={'No'}
          checked={!fuelAssist}
          onChange={setClientProperty}
        />
      </Form.Field>

  );
};  // End Utilities(<>)

const HousingDetails = function ({ current, type, time, setClientProperty }) {

  let shelter = current.shelter,
      sharedProps = {
        timeState: current, current: current, type: type, time: time,
        setClientProperty: setClientProperty
      };

  if ( current.shelter === 'voucher' ) {
    return (

        <ContractRentField {...sharedProps} />
        <RentShareField {...sharedProps} />
        <Utilities {...sharedProps}/>

    );

  } else if ( shelter === 'homeless' ) {
    return null;

  } else if ( shelter === 'renter' ) {
    return (

        <PlainRentRow {...sharedProps} />
        <Utilities {...sharedProps}/>

    );

  } else if ( shelter === 'homeowner' ) {
    return (

        <IntervalColumnHeadings type={ type }/>
        <CashFlowRow {...sharedProps} generic={'mortgage'}> Mortgage </CashFlowRow>
        <CashFlowRow {...sharedProps} generic={'housingInsurance'}> Insurance Costs </CashFlowRow>
        <CashFlowRow {...sharedProps} generic={'propertyTax'}> Property Tax </CashFlowRow>
        <Utilities {...sharedProps}/>

    );

  }  // end which expenses
};  // End HousingDetails(<>)

const HousingRadio = function ({ currentValue, label, time, setClientProperty }) {

  var value = label.toLowerCase();

  return (
    <Form.Field>
      <Radio
        name={'shelter'}
        label={label}
        value={value}
        checked={currentValue === value}
        onChange={setClientProperty}
      />
    </Form.Field>
  );

};  // End HousingRadio(<>)

/**
 * @function
 * @param {object} props
 * @param {object} props.current - Client data of current user circumstances
 * @param {string} props.type - 'expense' or 'income', etc., for classes
 * @param {string} props.time - 'current' or 'future'
 * @param {function} props.setClientProperty - Sets state values
 *
 * @returns React element
 */
const Housing = function ({ current, type, time, setClientProperty }) {

  // We're using a bunch of radio buttons. Since `checked` is defined
  // in Radio components, `setClientProperty()` would store it, but we
  // want the value, so get rid of checked.
  /** Makes sure values are propagated to 'current' properties if needed. */
  let ensureRouteAndValue = function ( evnt, inputProps ) {
    var obj = { ...inputProps, name: inputProps.name, value: inputProps.value, checked: null };
    setClientProperty( evnt, obj );
  };

  let sharedProps = {
    current: current, type: type, time: time,
    setClientProperty: ensureRouteAndValue
  };

  return (

      <FormHeading>Housing</FormHeading>

      { current.shelter === 'voucher'
      ? null
      :

        What is your housing situation?
        <HousingRadio
          currentValue={current.shelter}
          label={'Homeless'}
          time={time}
          setClientProperty={ensureRouteAndValue}
        />
        <HousingRadio
          currentValue={current.shelter}
          label={'Renter'}
          time={time}
          setClientProperty={ensureRouteAndValue}
        />
        <HousingRadio
          currentValue={current.shelter}
          label={'Homeowner'}
          time={time}
          setClientProperty={ensureRouteAndValue}
        />

}

      <HousingDetails {...sharedProps}/>

  );

};  // End Housing()

/**
 * @function
 * @param {object} props
 * @param {object} props.current - Client data of current user circumstances
 * @param {object} props.time - 'current' or 'future'
 * @param {object} props.setClientProperty - Sets state values
 *
 * @returns React element
 */
const ExpensesFormContent = function ({ current, time, setClientProperty }) {

  let type        = 'expense',
      household   = current.household,
      sharedProps = { timeState: current, type: type, time: time, setClientProperty: setClientProperty };

  /** @todo Make an age-checking function to
   *     keep household data structure under
   *     control in one place. */
  var isOver12 = function ( member ) { return !isUnder13( member ); };

  // Won't include head or spouse
  var allDependents = getDependentMembers( household ),
      under13       = getEveryMember( allDependents, isUnder13 ),
      over12        = getEveryMember( allDependents, isOver12 );

  // 'Elderly' here is using the lowest common denominator - SNAP standards.
  var isElderlyOrDisabled = function ( member ) {
    return isDisabled( member ) || member.m_age >= 60;
  };
  var elderlyOrDisabled = getEveryMember( household, isElderlyOrDisabled ),
      elderlyOrDisabledHeadOrSpouse = getEveryMember( elderlyOrDisabled, isHeadOrSpouse );

  return (

      { under13.length > 0
        ?

          <FormHeading subheading = {'A "child" is a person 12 or younger. Don\'t include amounts that are paid for by other benefit programs.\n'}>
            Reasonable Unreimbursed Non-Medical Child(ren) Care</FormHeading>
          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'childDirectCare'}> Direct care costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'childBeforeAndAfterSchoolCare'}> Before- and after-school care </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'childTransportation'}> Transportation costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'childOtherCare'}> Other care </CashFlowRow>
          <CashFlowRowWithPrompt {...sharedProps}
            generic={'earnedBecauseOfChildCare'}
            promptLabel={'Does childcare allow you to make additional income?'}
          >
            Income made possible by child care expenses
          </CashFlowRowWithPrompt>

        : null
      }

      { current.hasSnap
        ?

          <FormHeading>Child Support</FormHeading>
          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'childSupportPaidOut'}> Legally obligated child support </CashFlowRow>

        : null
      }

      {/* Head or spouse can't be a dependent, so they don't count. */}
      { over12.length > 0
        ?

          <FormHeading subheading = {'For the care of people who are older than 12, but are still dependents (those under 18 or disabled). Don\'t include amounts that are paid for by other benefit programs.\n'}>
            Dependent Care of Persons Over 12 Years of Age</FormHeading>
          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'adultDirectCare'}> Direct care costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'adultTransportation'}> Transportation costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'adultOtherCare'}> Other care </CashFlowRow>

        : null
      }

      { elderlyOrDisabled.length > 0
        ?

          <FormHeading>Unreimbursed Disabled/Handicapped/Elderly Assistance</FormHeading>

Unreimbursed expenses to cover care attendants and auxiliary apparatus for any family member who is elderly or is a person with disabilities. Auxiliary apparatus are items such as wheelchairs, ramps, adaptations to vehicles, or special equipment to enable a blind person to read or type, but only if these items are directly related to permitting the disabled person or other family member to work.

Examples of eligible disability assistance expenses:

The payments made on a motorized wheelchair for the 42 year old son of the head of household enable the son to leave the house and go to work each day on his own. Prior to the purchase of the motorized wheelchair, the son was unable to make the commute to work. These payments are an eligible disability assistance expense.

Payments to a care attendant to stay with a disabled 16-year-old child allow the child’s mother to go to work every day. These payments are an eligible disability assistance allowance.

          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'disabledAssistance'}> Disabled/Handicapped assistance </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'earnedBecauseOfAdultCare'}> Income made possible by assistance expenses </CashFlowRow>

        : null
      }

      {/** These medical expenses don't count for Section 8 unless
        *     the disabled person is the head or spouse. From
        *     {@link http://www.tacinc.org/media/58886/S8MS%20Full%20Book.pdf}
        *     Appendix B, item (D) */}
      { elderlyOrDisabledHeadOrSpouse.length > 0 || (current.hasSnap && elderlyOrDisabled.length > 0)
        ?

          <FormHeading>Unreimbursed Medical Expenses</FormHeading>

Do not repeat anything you already listed in the section above. Examples of allowable medical expenses:

The orthodontist expenses for a child’s braces.

Services of doctors and health care professionals.

Services of health care facilities.

Medical insurance premiums.

Prescription/non-prescription medicines (prescribed by a physician).

Transportation to treatment (cab fare, bus fare, mileage).

Dental expenses, eyeglasses, hearing aids, batteries.

Live-in or periodic medical assistance.

Monthly payment on accumulated medical bills (regular monthly payments on a bill that was previously incurred).

          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic='disabledMedical'> Disabled/Elderly medical expenses </CashFlowRow>
          <CashFlowRow {...sharedProps} generic='otherMedical'> Medical expenses of other members </CashFlowRow>

        : null
      }

      <Housing current={current} time={time} type={type} setClientProperty={setClientProperty} />

  );

};  // End ExpensesFormContent()

/**
 * @todo SNAP: Does a medical assistant's payments count as a medical expense?
 *     (Answer: Yes. @see {@link https://www.mass.gov/service-details/snap-verifications})
 * @todo SNAP: Medical expense only matters if household has elder/disabled, but
 *     are they any medical expenses or only those of the disabled person? "Medical
 *     Expenses for Disabled or Elderly". Also, do they sometimes need to
 *     enter medical expenses even if they don't have an elderly or disabled
 *     household member?
 */

/**
  * @function
  * @param {object} props
  * @param {function} props.changeClient - Setting client state
  * @param {function} props.previousStep - Go to previous form step
  * @param {function} props.nextStep - Go to next form step
  * @param {object} props.client - Object will all the data for calculating benefits
  *
  * @returns React element
  */
// `props` is a cloned version of the original props. References broken.
const CurrentExpensesStep = function ({ changeClient, previousStep, nextStep, client }) {

  const setTimeProp = getTimeSetter( 'current', changeClient );

  return (
    <Form className = 'expense-form flex-item flex-column'>
      <FormPartsContainer
        title     = {'Current Household Expenses'}
        clarifier = {null}
        left      = {{name: 'Previous', func: previousStep}}
        right     = {{name: 'Next', func: nextStep}}
      >
        <ExpensesFormContent setClientProperty={setTimeProp} current={client.current} time={'current'} />
      </FormPartsContainer>
    </Form>
  );

};  // End CurrentExpensesStep()

export { CurrentExpensesStep };
<commit_msg>Prompt before accepting earnedBecauseOfAdultCare<commit_after>// REACT COMPONENTS
import React from 'react';
import {
  Form,
  Radio,
  Checkbox,
  Header
} from 'semantic-ui-react';

// PROJECT COMPONENTS
import {
  FormPartsContainer,
  // MassiveToggle,
  FormHeading,
  IntervalColumnHeadings,
  CashFlowRow
} from './formHelpers';
import {
  ContractRentField,
  RentShareField,
  PlainRentRow
} from './rentFields';
import CashFlowRowWithPrompt from './CashFlowRowWithPrompt';

// COMPONENT HELPER FUNCTIONS
import { getTimeSetter } from '../utils/getTimeSetter';

// LOGIC
import {
  getEveryMember,
  isHeadOrSpouse,
  getDependentMembers,
  isDisabled,
  isUnder13,
} from '../utils/getMembers';

// ========================================
// COMPONENTS
// ========================================

const Utilities = function ({ current, type, time, setClientProperty }) {

  let climate     = current.climateControl,
      electricity = current.nonHeatElectricity,
      phone       = current.phone,
      fuelAssist  = current.fuelAssistance;

  let setChecked = function ( evnt, inputProps ) {
    var obj = { ...inputProps, value: inputProps.checked };
    setClientProperty( evnt, obj );
  };  // End setChecked()

  return (

      Which of these utilities do you pay for?

      <Checkbox
        name={'climateControl'}
        label={'Heating or cooling (e.g. A/C during summer)'}
        checked={climate}
        onChange={setChecked}
      />

      <Checkbox
        name={'nonHeatElectricity'}
        label={'Electricity for non-heating purposes'}
        checked={electricity}
        onChange={setChecked}
      />

      <Checkbox
        name={'phone'}
        label={'Telephone service'}
        checked={phone}
        onChange={setChecked}
      />

      Do you get Fuel Assistance?
      <Form.Field style={{display: 'inline-block', paddingRight: '1em'}}>
        <Radio
          name={'fuelAssistance'}
          label={'Yes'} value={'Yes'}
          checked={fuelAssist}
          onChange={setClientProperty}
        />
      </Form.Field>
      <Form.Field style={{display: 'inline-block', paddingRight: '1em'}}>
        <Radio
          name={'fuelAssistance'}
          label={'No'} value={'No'}
          checked={!fuelAssist}
          onChange={setClientProperty}
        />
      </Form.Field>

  );
};  // End Utilities(<>)

const HousingDetails = function ({ current, type, time, setClientProperty }) {

  let shelter = current.shelter,
      sharedProps = {
        timeState: current, current: current, type: type, time: time,
        setClientProperty: setClientProperty
      };

  if ( current.shelter === 'voucher' ) {
    return (

        <ContractRentField {...sharedProps} />
        <RentShareField {...sharedProps} />
        <Utilities {...sharedProps}/>

    );

  } else if ( shelter === 'homeless' ) {
    return null;

  } else if ( shelter === 'renter' ) {
    return (

        <PlainRentRow {...sharedProps} />
        <Utilities {...sharedProps}/>

    );

  } else if ( shelter === 'homeowner' ) {
    return (

        <IntervalColumnHeadings type={ type }/>
        <CashFlowRow {...sharedProps} generic={'mortgage'}> Mortgage </CashFlowRow>
        <CashFlowRow {...sharedProps} generic={'housingInsurance'}> Insurance Costs </CashFlowRow>
        <CashFlowRow {...sharedProps} generic={'propertyTax'}> Property Tax </CashFlowRow>
        <Utilities {...sharedProps}/>

    );

  }  // end which expenses
};  // End HousingDetails(<>)

const HousingRadio = function ({ currentValue, label, time, setClientProperty }) {

  var value = label.toLowerCase();

  return (
    <Form.Field>
      <Radio
        name={'shelter'}
        label={label}
        value={value}
        checked={currentValue === value}
        onChange={setClientProperty}
      />
    </Form.Field>
  );

};  // End HousingRadio(<>)

/**
 * @function
 * @param {object} props
 * @param {object} props.current - Client data of current user circumstances
 * @param {string} props.type - 'expense' or 'income', etc., for classes
 * @param {string} props.time - 'current' or 'future'
 * @param {function} props.setClientProperty - Sets state values
 *
 * @returns React element
 */
const Housing = function ({ current, type, time, setClientProperty }) {

  // We're using a bunch of radio buttons. Since `checked` is defined
  // in Radio components, `setClientProperty()` would store it, but we
  // want the value, so get rid of checked.
  /** Makes sure values are propagated to 'current' properties if needed. */
  let ensureRouteAndValue = function ( evnt, inputProps ) {
    var obj = { ...inputProps, name: inputProps.name, value: inputProps.value, checked: null };
    setClientProperty( evnt, obj );
  };

  let sharedProps = {
    current: current, type: type, time: time,
    setClientProperty: ensureRouteAndValue
  };

  return (

      <FormHeading>Housing</FormHeading>

      { current.shelter === 'voucher'
      ? null
      :

        What is your housing situation?
        <HousingRadio
          currentValue={current.shelter}
          label={'Homeless'}
          time={time}
          setClientProperty={ensureRouteAndValue}
        />
        <HousingRadio
          currentValue={current.shelter}
          label={'Renter'}
          time={time}
          setClientProperty={ensureRouteAndValue}
        />
        <HousingRadio
          currentValue={current.shelter}
          label={'Homeowner'}
          time={time}
          setClientProperty={ensureRouteAndValue}
        />

}

      <HousingDetails {...sharedProps}/>

  );

};  // End Housing()

/**
 * @function
 * @param {object} props
 * @param {object} props.current - Client data of current user circumstances
 * @param {object} props.time - 'current' or 'future'
 * @param {object} props.setClientProperty - Sets state values
 *
 * @returns React element
 */
const ExpensesFormContent = function ({ current, time, setClientProperty }) {

  let type        = 'expense',
      household   = current.household,
      sharedProps = { timeState: current, type: type, time: time, setClientProperty: setClientProperty };

  /** @todo Make an age-checking function to
   *     keep household data structure under
   *     control in one place. */
  var isOver12 = function ( member ) { return !isUnder13( member ); };

  // Won't include head or spouse
  var allDependents = getDependentMembers( household ),
      under13       = getEveryMember( allDependents, isUnder13 ),
      over12        = getEveryMember( allDependents, isOver12 );

  // 'Elderly' here is using the lowest common denominator - SNAP standards.
  var isElderlyOrDisabled = function ( member ) {
    return isDisabled( member ) || member.m_age >= 60;
  };
  var elderlyOrDisabled = getEveryMember( household, isElderlyOrDisabled ),
      elderlyOrDisabledHeadOrSpouse = getEveryMember( elderlyOrDisabled, isHeadOrSpouse );

  return (

      { under13.length > 0
        ?

          <FormHeading subheading = {'A "child" is a person 12 or younger. Don\'t include amounts that are paid for by other benefit programs.\n'}>
            Reasonable Unreimbursed Non-Medical Child(ren) Care</FormHeading>
          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'childDirectCare'}> Direct care costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'childBeforeAndAfterSchoolCare'}> Before- and after-school care </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'childTransportation'}> Transportation costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'childOtherCare'}> Other care </CashFlowRow>
          <CashFlowRowWithPrompt {...sharedProps}
            generic={'earnedBecauseOfChildCare'}
            promptLabel={'Does childcare allow you to make additional income?'}
          >
            Income made possible by child care expenses
          </CashFlowRowWithPrompt>

        : null
      }

      { current.hasSnap
        ?

          <FormHeading>Child Support</FormHeading>
          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'childSupportPaidOut'}> Legally obligated child support </CashFlowRow>

        : null
      }

      {/* Head or spouse can't be a dependent, so they don't count. */}
      { over12.length > 0
        ?

          <FormHeading subheading = {'For the care of people who are older than 12, but are still dependents (those under 18 or disabled). Don\'t include amounts that are paid for by other benefit programs.\n'}>
            Dependent Care of Persons Over 12 Years of Age</FormHeading>
          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'adultDirectCare'}> Direct care costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'adultTransportation'}> Transportation costs </CashFlowRow>
          <CashFlowRow {...sharedProps} generic={'adultOtherCare'}> Other care </CashFlowRow>

        : null
      }

      { elderlyOrDisabled.length > 0
        ?

          <FormHeading>Unreimbursed Disabled/Handicapped/Elderly Assistance</FormHeading>

Unreimbursed expenses to cover care attendants and auxiliary apparatus for any family member who is elderly or is a person with disabilities. Auxiliary apparatus are items such as wheelchairs, ramps, adaptations to vehicles, or special equipment to enable a blind person to read or type, but only if these items are directly related to permitting the disabled person or other family member to work.

Examples of eligible disability assistance expenses:

The payments made on a motorized wheelchair for the 42 year old son of the head of household enable the son to leave the house and go to work each day on his own. Prior to the purchase of the motorized wheelchair, the son was unable to make the commute to work. These payments are an eligible disability assistance expense.

Payments to a care attendant to stay with a disabled 16-year-old child allow the child’s mother to go to work every day. These payments are an eligible disability assistance allowance.

          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic={'disabledAssistance'}> Disabled/Handicapped assistance </CashFlowRow>
          <CashFlowRowWithPrompt {...sharedProps}
            generic={'earnedBecauseOfAdultCare'}
            promptLabel={'Do assistance expenses allow you to make additional income?'}
          >
            Income made possible by assistance expenses
          </CashFlowRowWithPrompt>

        : null
      }

      {/** These medical expenses don't count for Section 8 unless
        *     the disabled person is the head or spouse. From
        *     {@link http://www.tacinc.org/media/58886/S8MS%20Full%20Book.pdf}
        *     Appendix B, item (D) */}
      { elderlyOrDisabledHeadOrSpouse.length > 0 || (current.hasSnap && elderlyOrDisabled.length > 0)
        ?

          <FormHeading>Unreimbursed Medical Expenses</FormHeading>

Do not repeat anything you already listed in the section above. Examples of allowable medical expenses:

The orthodontist expenses for a child’s braces.

Services of doctors and health care professionals.

Services of health care facilities.

Medical insurance premiums.

Prescription/non-prescription medicines (prescribed by a physician).

Transportation to treatment (cab fare, bus fare, mileage).

Dental expenses, eyeglasses, hearing aids, batteries.

Live-in or periodic medical assistance.

Monthly payment on accumulated medical bills (regular monthly payments on a bill that was previously incurred).

          <IntervalColumnHeadings type={type}/>
          <CashFlowRow {...sharedProps} generic='disabledMedical'> Disabled/Elderly medical expenses </CashFlowRow>
          <CashFlowRow {...sharedProps} generic='otherMedical'> Medical expenses of other members </CashFlowRow>

        : null
      }

      <Housing current={current} time={time} type={type} setClientProperty={setClientProperty} />

  );

};  // End ExpensesFormContent()

/**
 * @todo SNAP: Does a medical assistant's payments count as a medical expense?
 *     (Answer: Yes. @see {@link https://www.mass.gov/service-details/snap-verifications})
 * @todo SNAP: Medical expense only matters if household has elder/disabled, but
 *     are they any medical expenses or only those of the disabled person? "Medical
 *     Expenses for Disabled or Elderly". Also, do they sometimes need to
 *     enter medical expenses even if they don't have an elderly or disabled
 *     household member?
 */

/**
  * @function
  * @param {object} props
  * @param {function} props.changeClient - Setting client state
  * @param {function} props.previousStep - Go to previous form step
  * @param {function} props.nextStep - Go to next form step
  * @param {object} props.client - Object will all the data for calculating benefits
  *
  * @returns React element
  */
// `props` is a cloned version of the original props. References broken.
const CurrentExpensesStep = function ({ changeClient, previousStep, nextStep, client }) {

  const setTimeProp = getTimeSetter( 'current', changeClient );

  return (
    <Form className = 'expense-form flex-item flex-column'>
      <FormPartsContainer
        title     = {'Current Household Expenses'}
        clarifier = {null}
        left      = {{name: 'Previous', func: previousStep}}
        right     = {{name: 'Next', func: nextStep}}
      >
        <ExpensesFormContent setClientProperty={setTimeProp} current={client.current} time={'current'} />
      </FormPartsContainer>
    </Form>
  );

};  // End CurrentExpensesStep()

export { CurrentExpensesStep };
<|endoftext|>