<commit_before>import ViewNode from 'renderer/ViewNode'
import * as elReg from 'element-registry'

jest.mock('runtime/components', () => {
  return {}
})
jest.mock('renderer/utils', () => ({
  insertChild: jest.fn(),
  removeChild: jest.fn()
}))
jest.mock('@nativescript/core/platform', () => {
  return {
    isAndroid() {
    },
    isIOS() {
    }
  }
}, {virtual: true})

describe('ViewNode', () => {
  test('firstChild returns null initially', () => {
    let node = new ViewNode()

    expect(node.firstChild).toBeNull()
  })

  test('firstChild returns the only child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    node.childNodes = [childNode]

    expect(node.firstChild).toEqual(childNode)
  })

  test('firstChild returns the correct child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let otherChildNode = new ViewNode()

    node.childNodes = [childNode, otherChildNode]

    expect(node.firstChild).toEqual(childNode)
  })

  test('lastChild returns null initially', () => {
    let node = new ViewNode()

    expect(node.lastChild).toBeNull()
  })

  test('lastChild returns the only child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    node.childNodes = [childNode]

    expect(node.lastChild).toEqual(childNode)
  })

  test('lastChild returns the correct child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let otherChildNode = new ViewNode()

    node.childNodes = [otherChildNode, childNode]

    expect(node.lastChild).toEqual(childNode)
  })

  test('insertBefore throws if no childNode is given', () => {
    let node = new ViewNode()

    expect(node.insertBefore).toThrow(`Can't insert child.`)
  })

  test('insertBefore throws if childNode has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = new ViewNode()

    expect(() => node.insertBefore(childNode)).toThrow(
      `already has a different parent`
    )
  })

  // no longer correct see #127 #240
  test.skip('insertBefore throws if childNode is already a child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = node

    expect(() => node.insertBefore(childNode)).toThrow(`already a child`)
  })

  test('insertBefore throws if reference node has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let refNode = new ViewNode()

    refNode.parentNode = new ViewNode()

    expect(() => node.insertBefore(childNode, refNode)).toThrow(
      `reference node has a different parent`
    )
  })

  test('insertBefore sets the correct node relations', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let refNode = new ViewNode()
    node.childNodes = [refNode]
    refNode.parentNode = node

    node.insertBefore(childNode, refNode)

    expect(node.childNodes.length).toBe(2)
    expect(childNode.parentNode).toEqual(node)
    expect(childNode.prevSibling).toBeFalsy()
    expect(childNode.nextSibling).toEqual(refNode)
    expect(refNode.prevSibling).toEqual(childNode)
    expect(refNode.nextSibling).toBeFalsy()
  })

  test('appendChild throws if no childNode is given', () => {
    let node = new ViewNode()

    expect(node.appendChild).toThrow(`Can't append child.`)
  })

  test('appendChild throws if childNode has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = new ViewNode()

    expect(() => node.appendChild(childNode)).toThrow(
      `already has a different parent`
    )
  })

  // no longer correct see #127 #240
  test.skip('appendChild throws if childNode is already a child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = node

    expect(() => node.appendChild(childNode)).toThrow(`already a child`)
  })

  test('appendChild sets the correct node relations for only child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    node.appendChild(childNode)

    expect(node.childNodes.length).toBe(1)
    expect(childNode.parentNode).toEqual(node)
    expect(childNode.prevSibling).toBeFalsy()
  })

  test('appendChild sets the correct node relations for multiple children', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let prevChildNode = new ViewNode()

    node.appendChild(prevChildNode)
    node.appendChild(childNode)

    expect(node.childNodes.length).toBe(2)
    expect(childNode.prevSibling).toEqual(prevChildNode)
    expect(prevChildNode.nextSibling).toEqual(childNode)
  })

  test('removeChild throws if no childNode is given', () => {
    let node = new ViewNode()

    expect(node.removeChild).toThrow(`Can't remove child.`)
  })

  test('removeChild throws if childNode has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = new ViewNode()

    expect(() => node.removeChild(childNode)).toThrow(`different parent.`)
  })

  test('removeChild throws if childNode has no parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    expect(() => node.removeChild(childNode)).toThrow(`no parent.`)
  })

  test('removeChild sets the correct node relations for firstChild', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let nextChildNode = new ViewNode()

    node.appendChild(childNode)
    node.appendChild(nextChildNode)

    expect(nextChildNode.prevSibling).toEqual(childNode)

    node.removeChild(childNode)

    expect(nextChildNode.prevSibling).toBeNull()
  })

  test('removeChild sets the correct node relations for lastChild', () => {
    let node = new ViewNode()
    let prevChildNode = new ViewNode()
    let childNode = new ViewNode()

    node.appendChild(prevChildNode)
    node.appendChild(childNode)

    expect(prevChildNode.nextSibling).toEqual(childNode)

    node.removeChild(childNode)

    expect(prevChildNode.nextSibling).toBeNull()
  })

  test('removeChild sets the correct node relations for prevChildNode and nextChildNode', () => {
    let node = new ViewNode()
    let prevChildNode = new ViewNode()
    let childNode = new ViewNode()
    let nextChildNode = new ViewNode()

    node.appendChild(prevChildNode)
    node.appendChild(childNode)
    node.appendChild(nextChildNode)

    expect(prevChildNode.nextSibling).toEqual(childNode)
    expect(nextChildNode.prevSibling).toEqual(childNode)

    node.removeChild(childNode)

    expect(node.childNodes.length).toBe(2)
    expect(prevChildNode.nextSibling).toEqual(nextChildNode)
    expect(nextChildNode.prevSibling).toEqual(prevChildNode)
    expect(childNode.parentNode).toBeNull()
    expect(childNode.prevSibling).toBeNull()
    expect(childNode.nextSibling).toBeNull()
  })

  test('nativeView can be set once', () => {
    let node = new ViewNode()
    let dummyView = {name: 'dummy'}
    node.nativeView = dummyView

    expect(node.nativeView).toEqual(dummyView)
  })

  it("nativeView can't be set multiple times", () => {
    let node = new ViewNode()
    let dummyView = {name: 'dummy'}
    node.nativeView = dummyView

    expect(() => (node.nativeView = dummyView)).toThrow(`Can't override`)
    expect(node.nativeView).toEqual(dummyView)
  })

  test('meta should be fetched only once upon get', () => {
    elReg.getViewMeta = jest.fn()
    elReg.getViewMeta.mockReturnValue('meta')

    let node = new ViewNode()
    node.tagName = 'testing'

    let meta = node.meta
    let second_meta = node.meta

    expect(elReg.getViewMeta).toHaveBeenCalledWith('nativetesting')
    expect(elReg.getViewMeta.mock.calls.length).toBe(1)
    expect(meta).toEqual('meta')
    expect(second_meta).toEqual('meta')
  })

  test('tagName should be normalized', () => {
    let node = new ViewNode()

    node.tagName = 'Testing'
    expect(node.tagName).toEqual('nativetesting')

    node.tagName = 'TestingTesting'
    expect(node.tagName).toEqual('nativetestingtesting')

    node.tagName = 'testing-testing'
    expect(node.tagName).toEqual('nativetestingtesting')
  })
})
<commit_msg>test: fix failing test<commit_after>import ViewNode from 'renderer/ViewNode'
import * as elReg from 'element-registry'

jest.mock('shared/util', () => {
  return {
    makeMap() {},
    once() {}
  }
}, { virtual: true })
jest.mock('runtime/components', () => {
  return {}
})
jest.mock('renderer/utils', () => ({
  insertChild: jest.fn(),
  removeChild: jest.fn()
}))
jest.mock('@nativescript/core/platform', () => {
  return {
    isAndroid() {
    },
    isIOS() {
    }
  }
}, {virtual: true})

describe('ViewNode', () => {
  test('firstChild returns null initially', () => {
    let node = new ViewNode()

    expect(node.firstChild).toBeNull()
  })

  test('firstChild returns the only child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    node.childNodes = [childNode]

    expect(node.firstChild).toEqual(childNode)
  })

  test('firstChild returns the correct child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let otherChildNode = new ViewNode()

    node.childNodes = [childNode, otherChildNode]

    expect(node.firstChild).toEqual(childNode)
  })

  test('lastChild returns null initially', () => {
    let node = new ViewNode()

    expect(node.lastChild).toBeNull()
  })

  test('lastChild returns the only child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    node.childNodes = [childNode]

    expect(node.lastChild).toEqual(childNode)
  })

  test('lastChild returns the correct child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let otherChildNode = new ViewNode()

    node.childNodes = [otherChildNode, childNode]

    expect(node.lastChild).toEqual(childNode)
  })

  test('insertBefore throws if no childNode is given', () => {
    let node = new ViewNode()

    expect(node.insertBefore).toThrow(`Can't insert child.`)
  })

  test('insertBefore throws if childNode has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = new ViewNode()

    expect(() => node.insertBefore(childNode)).toThrow(
      `already has a different parent`
    )
  })

  // no longer correct see #127 #240
  test.skip('insertBefore throws if childNode is already a child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = node

    expect(() => node.insertBefore(childNode)).toThrow(`already a child`)
  })

  test('insertBefore throws if reference node has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let refNode = new ViewNode()

    refNode.parentNode = new ViewNode()

    expect(() => node.insertBefore(childNode, refNode)).toThrow(
      `reference node has a different parent`
    )
  })

  test('insertBefore sets the correct node relations', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let refNode = new ViewNode()
    node.childNodes = [refNode]
    refNode.parentNode = node

    node.insertBefore(childNode, refNode)

    expect(node.childNodes.length).toBe(2)
    expect(childNode.parentNode).toEqual(node)
    expect(childNode.prevSibling).toBeFalsy()
    expect(childNode.nextSibling).toEqual(refNode)
    expect(refNode.prevSibling).toEqual(childNode)
    expect(refNode.nextSibling).toBeFalsy()
  })

  test('appendChild throws if no childNode is given', () => {
    let node = new ViewNode()

    expect(node.appendChild).toThrow(`Can't append child.`)
  })

  test('appendChild throws if childNode has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = new ViewNode()

    expect(() => node.appendChild(childNode)).toThrow(
      `already has a different parent`
    )
  })

  // no longer correct see #127 #240
  test.skip('appendChild throws if childNode is already a child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = node

    expect(() => node.appendChild(childNode)).toThrow(`already a child`)
  })

  test('appendChild sets the correct node relations for only child', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    node.appendChild(childNode)

    expect(node.childNodes.length).toBe(1)
    expect(childNode.parentNode).toEqual(node)
    expect(childNode.prevSibling).toBeFalsy()
  })

  test('appendChild sets the correct node relations for multiple children', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let prevChildNode = new ViewNode()

    node.appendChild(prevChildNode)
    node.appendChild(childNode)

    expect(node.childNodes.length).toBe(2)
    expect(childNode.prevSibling).toEqual(prevChildNode)
    expect(prevChildNode.nextSibling).toEqual(childNode)
  })

  test('removeChild throws if no childNode is given', () => {
    let node = new ViewNode()

    expect(node.removeChild).toThrow(`Can't remove child.`)
  })

  test('removeChild throws if childNode has a different parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    childNode.parentNode = new ViewNode()

    expect(() => node.removeChild(childNode)).toThrow(`different parent.`)
  })

  test('removeChild throws if childNode has no parent', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()

    expect(() => node.removeChild(childNode)).toThrow(`no parent.`)
  })

  test('removeChild sets the correct node relations for firstChild', () => {
    let node = new ViewNode()
    let childNode = new ViewNode()
    let nextChildNode = new ViewNode()

    node.appendChild(childNode)
    node.appendChild(nextChildNode)

    expect(nextChildNode.prevSibling).toEqual(childNode)

    node.removeChild(childNode)

    expect(nextChildNode.prevSibling).toBeNull()
  })

  test('removeChild sets the correct node relations for lastChild', () => {
    let node = new ViewNode()
    let prevChildNode = new ViewNode()
    let childNode = new ViewNode()

    node.appendChild(prevChildNode)
    node.appendChild(childNode)

    expect(prevChildNode.nextSibling).toEqual(childNode)

    node.removeChild(childNode)

    expect(prevChildNode.nextSibling).toBeNull()
  })

  test('removeChild sets the correct node relations for prevChildNode and nextChildNode', () => {
    let node = new ViewNode()
    let prevChildNode = new ViewNode()
    let childNode = new ViewNode()
    let nextChildNode = new ViewNode()

    node.appendChild(prevChildNode)
    node.appendChild(childNode)
    node.appendChild(nextChildNode)

    expect(prevChildNode.nextSibling).toEqual(childNode)
    expect(nextChildNode.prevSibling).toEqual(childNode)

    node.removeChild(childNode)

    expect(node.childNodes.length).toBe(2)
    expect(prevChildNode.nextSibling).toEqual(nextChildNode)
    expect(nextChildNode.prevSibling).toEqual(prevChildNode)
    expect(childNode.parentNode).toBeNull()
    expect(childNode.prevSibling).toBeNull()
    expect(childNode.nextSibling).toBeNull()
  })

  test('nativeView can be set once', () => {
    let node = new ViewNode()
    let dummyView = {name: 'dummy'}
    node.nativeView = dummyView

    expect(node.nativeView).toEqual(dummyView)
  })

  it("nativeView can't be set multiple times", () => {
    let node = new ViewNode()
    let dummyView = {name: 'dummy'}
    node.nativeView = dummyView

    expect(() => (node.nativeView = dummyView)).toThrow(`Can't override`)
    expect(node.nativeView).toEqual(dummyView)
  })

  test('meta should be fetched only once upon get', () => {
    elReg.getViewMeta = jest.fn()
    elReg.getViewMeta.mockReturnValue('meta')

    let node = new ViewNode()
    node.tagName = 'testing'

    let meta = node.meta
    let second_meta = node.meta

    expect(elReg.getViewMeta).toHaveBeenCalledWith('nativetesting')
    expect(elReg.getViewMeta.mock.calls.length).toBe(1)
    expect(meta).toEqual('meta')
    expect(second_meta).toEqual('meta')
  })

  test('tagName should be normalized', () => {
    let node = new ViewNode()

    node.tagName = 'Testing'
    expect(node.tagName).toEqual('nativetesting')

    node.tagName = 'TestingTesting'
    expect(node.tagName).toEqual('nativetestingtesting')

    node.tagName = 'testing-testing'
    expect(node.tagName).toEqual('nativetestingtesting')
  })
})
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert'),
    dnsSync = require('../index');

describe('dns sync', function () {

    it('should resolve dns', function () {
        assert.ok(dnsSync.resolve('www.example.com'));
        assert.ok(dnsSync.resolve('www.paypal.com'));
        assert.ok(dnsSync.resolve('www.google.com'));
        assert.ok(dnsSync.resolve('www.yahoo.com'));
    });

    it('should fail to resolve dns', function () {
        assert.ok(!dnsSync.resolve('www.example.con'));
        assert.ok(!dnsSync.resolve('www.paypal.con'));
        assert.ok(!dnsSync.resolve('www.not-google.first'));
        assert.ok(!dnsSync.resolve('www.hello-yahoo.next'));
    });

    it('should fail to resolve valid dns', function () {
        assert.ok(!dnsSync.resolve("$(id > /tmp/foo)'"));
        assert.ok(!dnsSync.resolve("cd /tmp; rm -f /tmp/echo; env 'x=() { (a)=>\' bash -c \"echo date\"; cat /tmp/echo"));
        assert.ok(!dnsSync.resolve("$(grep -l -z '[^)]=() {' /proc/[1-9]*/environ | cut -d/ -f3)'"));
    });
});
<commit_msg>Add tests for additional resolve functionality<commit_after>'use strict';

var assert = require('assert'),
    dnsSync = require('../index');

describe('dns sync', function () {

    it('should resolve dns', function () {
        assert.ok(dnsSync.resolve('www.example.com'));
        assert.ok(dnsSync.resolve('www.paypal.com'));
        assert.ok(dnsSync.resolve('www.google.com'));
        assert.ok(dnsSync.resolve('www.yahoo.com'));
    });

    it('should fail to resolve dns', function () {
        assert.ok(!dnsSync.resolve('www.example.con'));
        assert.ok(!dnsSync.resolve('www.paypal.con'));
        assert.ok(!dnsSync.resolve('www.not-google.first'));
        assert.ok(!dnsSync.resolve('www.hello-yahoo.next'));
    });

    it('should fail to resolve valid dns', function () {
        assert.ok(!dnsSync.resolve("$(id > /tmp/foo)'"));
        assert.ok(!dnsSync.resolve("cd /tmp; rm -f /tmp/echo; env 'x=() { (a)=>\' bash -c \"echo date\"; cat /tmp/echo"));
        assert.ok(!dnsSync.resolve("$(grep -l -z '[^)]=() {' /proc/[1-9]*/environ | cut -d/ -f3)'"));
    });

    it('should resolve AAAA records if asked', function () {
        var aaaa = dnsSync.resolve('www.google.com', 'AAAA');
        assert.ok(aaaa);
        assert.ok(aaaa[0].match(/^([0-9a-f]{2,4}(:|$))+/));
        assert.ok(dnsSync.resolve('www.google.com') !== aaaa);
    });

    it('should resolve NS records if asked', function () {
        var ns = dnsSync.resolve('google.com', 'NS')
        assert.ok(ns);
        assert.ok(ns.length >= 1);
        assert.ok(ns[0].match(/^ns[0-9]+\.google\.com$/));
    });
});
<|endoftext|>


<commit_before>// Generated on 2014-04-05 using generator-angular 0.8.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

	// Load grunt tasks automatically
	require('load-grunt-tasks')(grunt);

	// Time how long tasks take. Can help when optimizing build times
	require('time-grunt')(grunt);

	// Define the configuration for all the tasks
	grunt.initConfig({

		// Project settings
		yeoman: {
			// configurable paths
			app: require('./bower.json').appPath || 'app',
			dist: 'dist'
		},

		// Watches files for changes and runs tasks based on the changed files
		watch: {
			bower: {
				files: ['bower.json'],
				tasks: ['bowerInstall']
			},
			js: {
				files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
				tasks: ['newer:jshint:all'],
				options: {
					livereload: true
				}
			},
			jsTest: {
				files: ['test/spec/{,*/}*.js'],
				tasks: ['newer:jshint:test', 'karma']
			},
			styles: {
				files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
				tasks: ['newer:copy:styles', 'autoprefixer']
			},
			gruntfile: {
				files: ['Gruntfile.js']
			},
			livereload: {
				options: {
					livereload: '<%= connect.options.livereload %>'
				},
				files: [
					'<%= yeoman.app %>/{,*/}*.html',
					'.tmp/styles/{,*/}*.css',
					'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
				]
			}
		},

		// The actual grunt server settings
		connect: {
			options: {
				port: 9000,
				// Change this to '0.0.0.0' to access the server from outside.
				hostname: 'localhost',
				livereload: 35729
			},
			livereload: {
				options: {
					open: true,
					base: [
						'.tmp',
						'<%= yeoman.app %>'
					]
				}
			},
			test: {
				options: {
					port: 9001,
					base: [
						'.tmp',
						'test',
						'<%= yeoman.app %>'
					]
				}
			},
			dist: {
				options: {
					base: '<%= yeoman.dist %>'
				}
			}
		},

		// Make sure code styles are up to par and there are no obvious mistakes
		jshint: {
			options: {
				jshintrc: '.jshintrc',
				reporter: require('jshint-stylish')
			},
			all: [
				'Gruntfile.js',
				'<%= yeoman.app %>/scripts/{,*/}*.js'
			],
			test: {
				options: {
					jshintrc: 'test/.jshintrc'
				},
				src: ['test/spec/{,*/}*.js']
			}
		},

		// Empties folders to start fresh
		clean: {
			dist: {
				files: [{
					dot: true,
					src: [
						'.tmp',
						'<%= yeoman.dist %>/*',
						'!<%= yeoman.dist %>/.git*'
					]
				}]
			},
			server: '.tmp'
		},

		// Add vendor prefixed styles
		autoprefixer: {
			options: {
				browsers: ['last 1 version']
			},
			dist: {
				files: [{
					expand: true,
					cwd: '.tmp/styles/',
					src: '{,*/}*.css',
					dest: '.tmp/styles/'
				}]
			}
		},

		// Automatically inject Bower components into the app
		bowerInstall: {
			app: {
				src: ['<%= yeoman.app %>/index.html'],
				ignorePath: '<%= yeoman.app %>/'
			}
		},

		// Renames files for browser caching purposes
		rev: {
			dist: {
				files: {
					src: [
						'<%= yeoman.dist %>/scripts/{,*/}*.js',
						'<%= yeoman.dist %>/styles/{,*/}*.css',
						'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
						'<%= yeoman.dist %>/styles/fonts/*'
					]
				}
			}
		},

		// Reads HTML for usemin blocks to enable smart builds that automatically
		// concat, minify and revision files. Creates configurations in memory so
		// additional tasks can operate on them
		useminPrepare: {
			html: '<%= yeoman.app %>/index.html',
			options: {
				dest: '<%= yeoman.dist %>',
				flow: {
					html: {
						steps: {
							js: ['concat', 'uglifyjs'],
							css: ['cssmin']
						},
						post: {}
					}
				}
			}
		},

		// Performs rewrites based on rev and the useminPrepare configuration
		usemin: {
			html: ['<%= yeoman.dist %>/{,*/}*.html'],
			css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
			options: {
				assetsDirs: ['<%= yeoman.dist %>']
			}
		},

		// The following *-min tasks produce minified files in the dist folder
		cssmin: {
			options: {
				root: '<%= yeoman.app %>'
			}
		},

		imagemin: {
			dist: {
				files: [{
					expand: true,
					cwd: '<%= yeoman.app %>/images',
					src: '{,*/}*.{png,jpg,jpeg,gif}',
					dest: '<%= yeoman.dist %>/images'
				}]
			}
		},

		svgmin: {
			dist: {
				files: [{
					expand: true,
					cwd: '<%= yeoman.app %>/images',
					src: '{,*/}*.svg',
					dest: '<%= yeoman.dist %>/images'
				}]
			}
		},

		htmlmin: {
			dist: {
				options: {
					collapseWhitespace: true,
					collapseBooleanAttributes: true,
					removeCommentsFromCDATA: true,
					removeOptionalTags: true
				},
				files: [{
					expand: true,
					cwd: '<%= yeoman.dist %>',
					src: ['*.html', 'views/{,*/}*.html'],
					dest: '<%= yeoman.dist %>'
				}]
			}
		},

		// ngmin tries to make the code safe for minification automatically by
		// using the Angular long form for dependency injection. It doesn't work on
		// things like resolve or inject so those have to be done manually.
		ngmin: {
			dist: {
				files: [{
					expand: true,
					cwd: '.tmp/concat/scripts',
					src: '*.js',
					dest: '.tmp/concat/scripts'
				}]
			}
		},

		// Replace Google CDN references
		cdnify: {
			dist: {
				html: ['<%= yeoman.dist %>/*.html']
			}
		},

		// Copies remaining files to places other tasks can use
		copy: {
			dist: {
				files: [{
					expand: true,
					dot: true,
					cwd: '<%= yeoman.app %>',
					dest: '<%= yeoman.dist %>',
					src: [
						'*.{ico,png,txt}',
						'.htaccess',
						'*.html',
						'views/{,*/}*.html',
						'images/{,*/}*.{webp}',
						'fonts/*'
					]
				}, {
					expand: true,
					cwd: '.tmp/images',
					dest: '<%= yeoman.dist %>/images',
					src: ['generated/*']
				}]
			},
			styles: {
				expand: true,
				cwd: '<%= yeoman.app %>/styles',
				dest: '.tmp/styles/',
				src: '{,*/}*.css'
			}
		},

		// Run some tasks in parallel to speed up the build process
		concurrent: {
			server: ['copy:styles'],
			test: ['copy:styles'],
			dist: [
				'copy:styles',
				'imagemin',
				'svgmin'
			]
		},

		// By default, your `index.html`'s <!-- Usemin block --> will take care of
		// minification. These next options are pre-configured if you do not wish
		// to use the Usemin blocks.
		// cssmin: {
		//   dist: {
		//     files: {
		//       '<%= yeoman.dist %>/styles/main.css': [
		//         '.tmp/styles/{,*/}*.css',
		//         '<%= yeoman.app %>/styles/{,*/}*.css'
		//       ]
		//     }
		//   }
		// },
		// uglify: {
		//   dist: {
		//     files: {
		//       '<%= yeoman.dist %>/scripts/scripts.js': [
		//         '<%= yeoman.dist %>/scripts/scripts.js'
		//       ]
		//     }
		//   }
		// },
		// concat: {
		//   dist: {}
		// },

		// Test settings
		karma: {
			unit: {
				configFile: 'karma.conf.js',
				singleRun: true
			}
		},
		ngtemplates: {
			MainModule: {
				cwd: '<%= yeoman.app %>',
				src: 'templates/*.tmpl.html',
				dest: '.tmp/template.js',
				options: {
					usemin: 'dist/app.js' // <~~ This came from the <!-- build:js --> block
				}
			}
		},
		smoosher: {
			options: {},
			all: {
				files: {
					'dist/index.full.html': 'dist/index.html',
				},
			},
		},
	});

	grunt.registerTask('serve', function (target) {
		if (target === 'dist') {
			return grunt.task.run(['build', 'connect:dist:keepalive']);
		}

		grunt.task.run([
			'clean:server',
			'bowerInstall',
			'concurrent:server',
			'autoprefixer',
			'connect:livereload',
			'watch'
		]);
	});

	grunt.registerTask('server', function (target) {
		grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
		grunt.task.run(['serve:' + target]);
	});

	grunt.registerTask('test', [
		'clean:server',
		'concurrent:test',
		'autoprefixer',
		'connect:test',
		'karma'
	]);

	grunt.registerTask('build', [
		'clean:dist',
		'bowerInstall',
		'useminPrepare',
		'concurrent:dist',
		'autoprefixer',
		'ngtemplates',
		'concat',
		'ngmin',
		'copy:dist',
		'cdnify',
		'cssmin',
		'uglify',
		'rev',
		'usemin',
		'htmlmin',
		'smoosher'
	]);

	grunt.registerTask('default', [
		'newer:jshint',
		'test',
		'build'
	]);
};
<commit_msg>fix watch performance issue on windows<commit_after>// Generated on 2014-04-05 using generator-angular 0.8.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

	// Load grunt tasks automatically
	require('load-grunt-tasks')(grunt);

	// Time how long tasks take. Can help when optimizing build times
	require('time-grunt')(grunt);

	// Define the configuration for all the tasks
	grunt.initConfig({

		// Project settings
		yeoman: {
			// configurable paths
			app: require('./bower.json').appPath || 'app',
			dist: 'dist'
		},

		// Watches files for changes and runs tasks based on the changed files
		watch: {
			bower: {
				files: ['bower.json'],
				tasks: ['bowerInstall']
			},
			js: {
				files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
				tasks: ['newer:jshint:all'],
				options: {
					spawn: false,
					livereload: true
				}
			},
			jsTest: {
				files: ['test/spec/{,*/}*.js'],
				tasks: ['newer:jshint:test', 'karma']
			},
			styles: {
				files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
				tasks: ['newer:copy:styles', 'autoprefixer']
			},
			gruntfile: {
				files: ['Gruntfile.js']
			},
			livereload: {
				options: {
					livereload: '<%= connect.options.livereload %>'
				},
				files: [
					'<%= yeoman.app %>/{,*/}*.html',
					'.tmp/styles/{,*/}*.css',
					'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
				]
			}
		},

		// The actual grunt server settings
		connect: {
			options: {
				port: 9000,
				// Change this to '0.0.0.0' to access the server from outside.
				hostname: 'localhost',
				livereload: 35729
			},
			livereload: {
				options: {
					open: true,
					base: [
						'.tmp',
						'<%= yeoman.app %>'
					]
				}
			},
			test: {
				options: {
					port: 9001,
					base: [
						'.tmp',
						'test',
						'<%= yeoman.app %>'
					]
				}
			},
			dist: {
				options: {
					base: '<%= yeoman.dist %>'
				}
			}
		},

		// Make sure code styles are up to par and there are no obvious mistakes
		jshint: {
			options: {
				jshintrc: '.jshintrc',
				reporter: require('jshint-stylish')
			},
			all: [
				'Gruntfile.js',
				'<%= yeoman.app %>/scripts/{,*/}*.js'
			],
			test: {
				options: {
					jshintrc: 'test/.jshintrc'
				},
				src: ['test/spec/{,*/}*.js']
			}
		},

		// Empties folders to start fresh
		clean: {
			dist: {
				files: [{
					dot: true,
					src: [
						'.tmp',
						'<%= yeoman.dist %>/*',
						'!<%= yeoman.dist %>/.git*'
					]
				}]
			},
			server: '.tmp'
		},

		// Add vendor prefixed styles
		autoprefixer: {
			options: {
				browsers: ['last 1 version']
			},
			dist: {
				files: [{
					expand: true,
					cwd: '.tmp/styles/',
					src: '{,*/}*.css',
					dest: '.tmp/styles/'
				}]
			}
		},

		// Automatically inject Bower components into the app
		bowerInstall: {
			app: {
				src: ['<%= yeoman.app %>/index.html'],
				ignorePath: '<%= yeoman.app %>/'
			}
		},

		// Renames files for browser caching purposes
		rev: {
			dist: {
				files: {
					src: [
						'<%= yeoman.dist %>/scripts/{,*/}*.js',
						'<%= yeoman.dist %>/styles/{,*/}*.css',
						'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
						'<%= yeoman.dist %>/styles/fonts/*'
					]
				}
			}
		},

		// Reads HTML for usemin blocks to enable smart builds that automatically
		// concat, minify and revision files. Creates configurations in memory so
		// additional tasks can operate on them
		useminPrepare: {
			html: '<%= yeoman.app %>/index.html',
			options: {
				dest: '<%= yeoman.dist %>',
				flow: {
					html: {
						steps: {
							js: ['concat', 'uglifyjs'],
							css: ['cssmin']
						},
						post: {}
					}
				}
			}
		},

		// Performs rewrites based on rev and the useminPrepare configuration
		usemin: {
			html: ['<%= yeoman.dist %>/{,*/}*.html'],
			css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
			options: {
				assetsDirs: ['<%= yeoman.dist %>']
			}
		},

		// The following *-min tasks produce minified files in the dist folder
		cssmin: {
			options: {
				root: '<%= yeoman.app %>'
			}
		},

		imagemin: {
			dist: {
				files: [{
					expand: true,
					cwd: '<%= yeoman.app %>/images',
					src: '{,*/}*.{png,jpg,jpeg,gif}',
					dest: '<%= yeoman.dist %>/images'
				}]
			}
		},

		svgmin: {
			dist: {
				files: [{
					expand: true,
					cwd: '<%= yeoman.app %>/images',
					src: '{,*/}*.svg',
					dest: '<%= yeoman.dist %>/images'
				}]
			}
		},

		htmlmin: {
			dist: {
				options: {
					collapseWhitespace: true,
					collapseBooleanAttributes: true,
					removeCommentsFromCDATA: true,
					removeOptionalTags: true
				},
				files: [{
					expand: true,
					cwd: '<%= yeoman.dist %>',
					src: ['*.html', 'views/{,*/}*.html'],
					dest: '<%= yeoman.dist %>'
				}]
			}
		},

		// ngmin tries to make the code safe for minification automatically by
		// using the Angular long form for dependency injection. It doesn't work on
		// things like resolve or inject so those have to be done manually.
		ngmin: {
			dist: {
				files: [{
					expand: true,
					cwd: '.tmp/concat/scripts',
					src: '*.js',
					dest: '.tmp/concat/scripts'
				}]
			}
		},

		// Replace Google CDN references
		cdnify: {
			dist: {
				html: ['<%= yeoman.dist %>/*.html']
			}
		},

		// Copies remaining files to places other tasks can use
		copy: {
			dist: {
				files: [{
					expand: true,
					dot: true,
					cwd: '<%= yeoman.app %>',
					dest: '<%= yeoman.dist %>',
					src: [
						'*.{ico,png,txt}',
						'.htaccess',
						'*.html',
						'views/{,*/}*.html',
						'images/{,*/}*.{webp}',
						'fonts/*'
					]
				}, {
					expand: true,
					cwd: '.tmp/images',
					dest: '<%= yeoman.dist %>/images',
					src: ['generated/*']
				}]
			},
			styles: {
				expand: true,
				cwd: '<%= yeoman.app %>/styles',
				dest: '.tmp/styles/',
				src: '{,*/}*.css'
			}
		},

		// Run some tasks in parallel to speed up the build process
		concurrent: {
			server: ['copy:styles'],
			test: ['copy:styles'],
			dist: [
				'copy:styles',
				'imagemin',
				'svgmin'
			]
		},

		// By default, your `index.html`'s <!-- Usemin block --> will take care of
		// minification. These next options are pre-configured if you do not wish
		// to use the Usemin blocks.
		// cssmin: {
		//   dist: {
		//     files: {
		//       '<%= yeoman.dist %>/styles/main.css': [
		//         '.tmp/styles/{,*/}*.css',
		//         '<%= yeoman.app %>/styles/{,*/}*.css'
		//       ]
		//     }
		//   }
		// },
		// uglify: {
		//   dist: {
		//     files: {
		//       '<%= yeoman.dist %>/scripts/scripts.js': [
		//         '<%= yeoman.dist %>/scripts/scripts.js'
		//       ]
		//     }
		//   }
		// },
		// concat: {
		//   dist: {}
		// },

		// Test settings
		karma: {
			unit: {
				configFile: 'karma.conf.js',
				singleRun: true
			}
		},
		ngtemplates: {
			MainModule: {
				cwd: '<%= yeoman.app %>',
				src: 'templates/*.tmpl.html',
				dest: '.tmp/template.js',
				options: {
					usemin: 'dist/app.js' // <~~ This came from the <!-- build:js --> block
				}
			}
		},
		smoosher: {
			options: {},
			all: {
				files: {
					'dist/index.full.html': 'dist/index.html',
				},
			},
		},
	});

	grunt.registerTask('serve', function (target) {
		if (target === 'dist') {
			return grunt.task.run(['build', 'connect:dist:keepalive']);
		}

		grunt.task.run([
			'clean:server',
			'bowerInstall',
			'concurrent:server',
			'autoprefixer',
			'connect:livereload',
			'watch'
		]);
	});

	grunt.registerTask('server', function (target) {
		grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
		grunt.task.run(['serve:' + target]);
	});

	grunt.registerTask('test', [
		'clean:server',
		'concurrent:test',
		'autoprefixer',
		'connect:test',
		'karma'
	]);

	grunt.registerTask('build', [
		'clean:dist',
		'bowerInstall',
		'useminPrepare',
		'concurrent:dist',
		'autoprefixer',
		'ngtemplates',
		'concat',
		'ngmin',
		'copy:dist',
		'cdnify',
		'cssmin',
		'uglify',
		'rev',
		'usemin',
		'htmlmin',
		'smoosher'
	]);

	grunt.registerTask('default', [
		'newer:jshint',
		'test',
		'build'
	]);
};
<|endoftext|>


<commit_before>'use strict';

var path = require( 'path' )
  , fs = require( 'fs' )
  , packageJson = require( __dirname + '/package.json' )
  , merge = require( 'deepmerge' )
  , getModulePaths = require( __dirname + '/lib/utils/getModulePaths.js' );

// Set the node path - this works only because the other processes are forked.
process.env.NODE_PATH = process.env.NODE_PATH ? './lib/:./modules/:' + process.env.NODE_PATH : './lib/:./modules/';

module.exports = function( grunt ) {
    // load all grunt tasks
    require( 'matchdep' ).filterDev( 'grunt-*' ).forEach( grunt.loadNpmTasks );

    // Create the project wide
    var gruntConfig = {
        watch: {
            tests: {
                files: [ 'lib/**/*.js', 'modules/**/*.js' ],
                tasks: [ 'mochaTest:ci' ]
            }
        },
        nodemon: {
            web: {
                options: {
                    file: 'app.js',
                    ignoredFiles: [ 'README.md', 'node_modules/**' ],
                    watchedExtensions: [ 'js' ],
                    watchedFolders: [ 'lib','modules' ],
                    delayTime: 1,
                    cwd: __dirname
                }
            }
        },
        mochaTest: {
            unit: {
                options: {
                    require: [ 'chai' ],
                    reporter: 'spec'
                },
                src: [ 'tests/unit/*.js' ].concat( getModulePaths( 'tests', 'unit' ) )
            },
            e2e: {
                options: {
                    require: 'chai',
                    reporter: 'spec'
                },
                src: [ 'tests/integration/*.js' ].concat( getModulePaths( 'tests', 'integration' ) )
            },
            ci: {
                options: {
                    require: 'chai',
                    reporter: 'min'
                },
                src: [ 'tests/**/*.js' ].concat( getModulePaths( 'tests', 'unit' ), getModulePaths( 'tests', 'integration' ) )
            }
        },
        concurrent: {
            servers: {
                tasks: [ 'server:web' ],
                options: {
                    logConcurrentOutput: true
                }
            }
        }
    };

    // Module's Gruntfiles.js
    var callbacks = [];

    // Load all modules Gruntfiles.js
    packageJson.bundledDependencies.forEach(function( moduleName ) {
        var moduleGruntfile = [ path.resolve( __dirname ), 'modules', moduleName, 'Gruntfile.js' ].join( path.sep );
        if ( fs.existsSync( moduleGruntfile ) ) {
            var gruntfile = require( moduleGruntfile )( grunt );

            // Merge (deep) the grunt config objects
            gruntConfig = merge( gruntConfig, gruntfile[ 0 ] );

            // Add the register function to our callbacks
            callbacks.push( gruntfile[ 1 ] );
        }
    });
console.dir(gruntConfig.concurrent.servers);
    // Initialize the config
    grunt.initConfig( gruntConfig );

    // Fire the callbacks and allow the modules to register their tasks
    callbacks.forEach( function( cb ) {
        cb( grunt );
    });

    // Register all project wide tasks with grunt
    grunt.registerTask( 'test', [ 'mochaTest:unit', 'mochaTest:e2e' ] );
    grunt.registerTask( 'test:unit', [ 'mochaTest:unit' ] );
    grunt.registerTask( 'test:e2e', [ 'mochaTest:e2e' ] );
    grunt.registerTask( 'test:ci', [ 'watch:tests' ] );
    grunt.registerTask( 'server', [ 'concurrent:servers' ] );
    grunt.registerTask( 'server:web', [ 'nodemon:web' ] );
    grunt.registerTask( 'default', [ 'server'] );
};<commit_msg>chore(cleanup): Remove debugging console.log<commit_after>'use strict';

var path = require( 'path' )
  , fs = require( 'fs' )
  , packageJson = require( __dirname + '/package.json' )
  , merge = require( 'deepmerge' )
  , getModulePaths = require( __dirname + '/lib/utils/getModulePaths.js' );

// Set the node path - this works only because the other processes are forked.
process.env.NODE_PATH = process.env.NODE_PATH ? './lib/:./modules/:' + process.env.NODE_PATH : './lib/:./modules/';

module.exports = function( grunt ) {
    // load all grunt tasks
    require( 'matchdep' ).filterDev( 'grunt-*' ).forEach( grunt.loadNpmTasks );

    // Create the project wide
    var gruntConfig = {
        watch: {
            tests: {
                files: [ 'lib/**/*.js', 'modules/**/*.js' ],
                tasks: [ 'mochaTest:ci' ]
            }
        },
        nodemon: {
            web: {
                options: {
                    file: 'app.js',
                    ignoredFiles: [ 'README.md', 'node_modules/**' ],
                    watchedExtensions: [ 'js' ],
                    watchedFolders: [ 'lib','modules' ],
                    delayTime: 1,
                    cwd: __dirname
                }
            }
        },
        mochaTest: {
            unit: {
                options: {
                    require: [ 'chai' ],
                    reporter: 'spec'
                },
                src: [ 'tests/unit/*.js' ].concat( getModulePaths( 'tests', 'unit' ) )
            },
            e2e: {
                options: {
                    require: 'chai',
                    reporter: 'spec'
                },
                src: [ 'tests/integration/*.js' ].concat( getModulePaths( 'tests', 'integration' ) )
            },
            ci: {
                options: {
                    require: 'chai',
                    reporter: 'min'
                },
                src: [ 'tests/**/*.js' ].concat( getModulePaths( 'tests', 'unit' ), getModulePaths( 'tests', 'integration' ) )
            }
        },
        concurrent: {
            servers: {
                tasks: [ 'server:web' ],
                options: {
                    logConcurrentOutput: true
                }
            }
        }
    };

    // Module's Gruntfiles.js
    var callbacks = [];

    // Load all modules Gruntfiles.js
    packageJson.bundledDependencies.forEach(function( moduleName ) {
        var moduleGruntfile = [ path.resolve( __dirname ), 'modules', moduleName, 'Gruntfile.js' ].join( path.sep );
        if ( fs.existsSync( moduleGruntfile ) ) {
            var gruntfile = require( moduleGruntfile )( grunt );

            // Merge (deep) the grunt config objects
            gruntConfig = merge( gruntConfig, gruntfile[ 0 ] );

            // Add the register function to our callbacks
            callbacks.push( gruntfile[ 1 ] );
        }
    });

    // Initialize the config
    grunt.initConfig( gruntConfig );

    // Fire the callbacks and allow the modules to register their tasks
    callbacks.forEach( function( cb ) {
        cb( grunt );
    });

    // Register all project wide tasks with grunt
    grunt.registerTask( 'test', [ 'mochaTest:unit', 'mochaTest:e2e' ] );
    grunt.registerTask( 'test:unit', [ 'mochaTest:unit' ] );
    grunt.registerTask( 'test:e2e', [ 'mochaTest:e2e' ] );
    grunt.registerTask( 'test:ci', [ 'watch:tests' ] );
    grunt.registerTask( 'server', [ 'concurrent:servers' ] );
    grunt.registerTask( 'server:web', [ 'nodemon:web' ] );
    grunt.registerTask( 'default', [ 'server'] );
};<|endoftext|>


<commit_before>const mongoose 			= require("mongoose");
const Schema 			= mongoose.Schema;

const ObjectId 		= mongoose.Schema.Types.ObjectId;
const Organisation 	= require("./organisation_model");
const Product 		= require("./product_model");
const Invoice 		= require("./invoice_model");
const Booking 		= require("./booking_model");
const License 		= require("./license_model");
const Location 		= require("./location_model");
const User 			= require("./user_model");
const Discount 		= require("./discount_model");
const postFind 	 	= require('mongoose-post-find-findone');

const LineItemSchema = new Schema({
	description: String,
	organisation_id: { type: ObjectId, ref: "Organisation", index: true },
	location_id: { type: ObjectId, ref: "Location", index: true },
	user_id: { type: ObjectId, ref: "User" },
	product_id: { type: ObjectId, ref: "Product" },
	invoice_id: { type: ObjectId, ref: "Invoice" },
	booking_id: { type: ObjectId, ref: "Booking" },
	license_id: { type: ObjectId, ref: "License" },
	amount: {
		type: Number,
		validate: function(v) {
			return v > 0;
		},
		required: true
	},
	price: {
		type: Number,
		validate: function(v) {
			return v >= 0;
		},
		required: true
	},
	price_customised: { type: Boolean, default: false },
	price_customised_user_id: { type: ObjectId, ref: "User" },
	price_customised_reason: String,
	price_customised_date: Date,
	tax_type: String,
	comment: String,
	discount: { type: Number, default: 0 },
	date_created: { type: Date, default: Date.now },
	is_quote: Boolean,
	xero_id: String,
	date_start: Date,
	date_end: Date,
	_owner_id: ObjectId,
	_deleted: { type: Boolean, default: false, index: true },
	_version: { type: Number, default: 0 },
}, {
	toObject: {
		virtuals: true
	},
	toJSON: {
		virtuals: true
	},
	timestamps: true
});

LineItemSchema.set("_perms", {
	admin: "crud",
	owner: "cr",
	primary_member: "r",
	user: "r",
	all: ""
});

LineItemSchema.virtual("status").get(function() {
	var now = new Date();
	if (!this.date_start) return "current";
	var date_start = +new Date(this.date_start);
	if (date_start > now) return "pending";
	if (!this.date_end) return "current";
	var date_end = +new Date(this.date_end);
	if (date_end && date_end < now) return "expired";
	return "current";
});

var _calculate_row_discount = (row, org_discounts) => {
	var now = new Date();
	row._doc.calculated_discount = row._doc.discount;
	if (!org_discounts.length) {
		return row;
	}
	var lineitem_discounts = [];
	for (discount of org_discounts) {
		if (discount.lineitem_id && discount.lineitem_id + "" === row._id + "") {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("all")) {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("product") && row.product_id) {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("license") && row.license_id) {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("booking") && row.booking_id) {
			lineitem_discounts.push(discount);
		}
	}
	row._doc.discounts = lineitem_discounts.map(discount => discount._id);
	row._doc.calculated_discount = lineitem_discounts.filter(discount => (!discount.date_start || now > discount.date_start) && (!discount.date_end || now < discount.date_end)).reduce((sum, b) => ( sum + b.discount ), row._doc.discount);
	if (row._doc.calculated_discount > 100) {
		row._doc.calculated_discount = 100;
	}
	return row;
}

LineItemSchema.plugin(postFind, {
	find: function(rows, done) {
		Discount.find({ _deleted: false })
		.then(discounts => {
			rows.forEach(row => {
				row._doc.calculated_discount = 0;
				var org_discounts = discounts
					.filter(discount => (row.organisation_id + "" === discount.organisation_id + "") || (row.organisation_id && row.organisation_id._id + "" === discount.organisation_id + ""));
				row = _calculate_row_discount(row, org_discounts);
			});
			done(null, rows);
		})
		.catch(err => {
			console.error(err);
			done(err);
		});
	},

	findOne: function(row, done) {
		if (!row) {
			return done(null);
		}
		Discount.find({ organisation_id: row.organisation_id, _deleted: false })
		.then(discounts => {
			row = _calculate_row_discount(row, discounts);
			done(null, row);
		})
		.catch(err => {
			console.error(err);
			done(err);
		});
	}
});

// Check if we've changed the value of the product or license
LineItemSchema.pre("save", function(next) {
	var lineitem = this;
	if (!lineitem.product_id && !lineitem.license_id) {
		// Nothing to see here
		return next();
	}
	var LineItem = require("./lineitem_model");
	LineItem.findOne({ _id: lineitem._id })
	.then(result => {
		if (result) {
			lineitem._is_new = false;
			if (result.price !== lineitem.price) {
				lineitem.price_customised = true;
				lineitem.price_customised_user_id = lineitem.__user._id;
				lineitem.price_customised_date = new Date();
			}
			next();
		} else {
			lineitem._is_new = false;
			if (lineitem.product_id) {
				Product.findOne({ _id: lineitem.product_id })
				.then(product => {
					if (product.price !== lineitem.price) {
						lineitem.price_customised = true;
						lineitem.price_customised_user_id = lineitem.__user._id;
						lineitem.price_customised_date = new Date();
					}
					next();
				})
				.catch(err => {
					console.error(err);
					next(err);
				});
			} else {
				License.findOne({ _id: lineitem.license_id }).populate('membership_id').populate('organisation_id')
				.then(license => {
					var price = null;
					if (license.organisation_id.user_id === license.user_id) {
						price = license.membership_id.cost;
					} else {
						price = license.membership_id.cost_extra_member;
					}
					if (price !== lineitem.price) {
						lineitem.price_customised = true;
						lineitem.price_customised_user_id = lineitem.__user._id;
						lineitem.price_customised_date = new Date();
					}
					next();
				})
				.catch(err => {
					console.error(err);
					next(err);
				});
			}
		}
	})
	.catch(err => {
		console.error(err);
		next(err);
	});
});

module.exports = mongoose.model("LineItem", LineItemSchema);
<commit_msg>Return row<commit_after>const mongoose 			= require("mongoose");
const Schema 			= mongoose.Schema;

const ObjectId 		= mongoose.Schema.Types.ObjectId;
const Organisation 	= require("./organisation_model");
const Product 		= require("./product_model");
const Invoice 		= require("./invoice_model");
const Booking 		= require("./booking_model");
const License 		= require("./license_model");
const Location 		= require("./location_model");
const User 			= require("./user_model");
const Discount 		= require("./discount_model");
const postFind 	 	= require('mongoose-post-find-findone');

const LineItemSchema = new Schema({
	description: String,
	organisation_id: { type: ObjectId, ref: "Organisation", index: true },
	location_id: { type: ObjectId, ref: "Location", index: true },
	user_id: { type: ObjectId, ref: "User" },
	product_id: { type: ObjectId, ref: "Product" },
	invoice_id: { type: ObjectId, ref: "Invoice" },
	booking_id: { type: ObjectId, ref: "Booking" },
	license_id: { type: ObjectId, ref: "License" },
	amount: {
		type: Number,
		validate: function(v) {
			return v > 0;
		},
		required: true
	},
	price: {
		type: Number,
		validate: function(v) {
			return v >= 0;
		},
		required: true
	},
	price_customised: { type: Boolean, default: false },
	price_customised_user_id: { type: ObjectId, ref: "User" },
	price_customised_reason: String,
	price_customised_date: Date,
	tax_type: String,
	comment: String,
	discount: { type: Number, default: 0 },
	date_created: { type: Date, default: Date.now },
	is_quote: Boolean,
	xero_id: String,
	date_start: Date,
	date_end: Date,
	_owner_id: ObjectId,
	_deleted: { type: Boolean, default: false, index: true },
	_version: { type: Number, default: 0 },
}, {
	toObject: {
		virtuals: true
	},
	toJSON: {
		virtuals: true
	},
	timestamps: true
});

LineItemSchema.set("_perms", {
	admin: "crud",
	owner: "cr",
	primary_member: "r",
	user: "r",
	all: ""
});

LineItemSchema.virtual("status").get(function() {
	var now = new Date();
	if (!this.date_start) return "current";
	var date_start = +new Date(this.date_start);
	if (date_start > now) return "pending";
	if (!this.date_end) return "current";
	var date_end = +new Date(this.date_end);
	if (date_end && date_end < now) return "expired";
	return "current";
});

var _calculate_row_discount = (row, org_discounts) => {
	var now = new Date();
	row._doc.calculated_discount = row._doc.discount;
	if (!org_discounts.length) {
		return row;
	}
	var lineitem_discounts = [];
	for (discount of org_discounts) {
		if (discount.lineitem_id && discount.lineitem_id + "" === row._id + "") {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("all")) {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("product") && row.product_id) {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("license") && row.license_id) {
			lineitem_discounts.push(discount);
		} else if (discount.apply_to.includes("booking") && row.booking_id) {
			lineitem_discounts.push(discount);
		}
	}
	row._doc.discounts = lineitem_discounts.map(discount => discount._id);
	row._doc.calculated_discount = lineitem_discounts.filter(discount => (!discount.date_start || now > discount.date_start) && (!discount.date_end || now < discount.date_end)).reduce((sum, b) => ( sum + b.discount ), row._doc.discount);
	if (row._doc.calculated_discount > 100) {
		row._doc.calculated_discount = 100;
	}
	return row;
}

LineItemSchema.plugin(postFind, {
	find: function(rows, done) {
		Discount.find({ _deleted: false })
		.then(discounts => {
			rows.forEach(row => {
				row._doc.calculated_discount = 0;
				var org_discounts = discounts
					.filter(discount => (row.organisation_id + "" === discount.organisation_id + "") || (row.organisation_id && row.organisation_id._id + "" === discount.organisation_id + ""));
				row = _calculate_row_discount(row, org_discounts);
			});
			done(null, rows);
		})
		.catch(err => {
			console.error(err);
			done(err);
		});
	},

	findOne: function(row, done) {
		if (!row) {
			return done(null, row);
		}
		Discount.find({ organisation_id: row.organisation_id, _deleted: false })
		.then(discounts => {
			row = _calculate_row_discount(row, discounts);
			done(null, row);
		})
		.catch(err => {
			console.error(err);
			done(err);
		});
	}
});

// Check if we've changed the value of the product or license
LineItemSchema.pre("save", function(next) {
	var lineitem = this;
	if (!lineitem.product_id && !lineitem.license_id) {
		// Nothing to see here
		return next();
	}
	var LineItem = require("./lineitem_model");
	LineItem.findOne({ _id: lineitem._id })
	.then(result => {
		if (result) {
			lineitem._is_new = false;
			if (result.price !== lineitem.price) {
				lineitem.price_customised = true;
				lineitem.price_customised_user_id = lineitem.__user._id;
				lineitem.price_customised_date = new Date();
			}
			next();
		} else {
			lineitem._is_new = false;
			if (lineitem.product_id) {
				Product.findOne({ _id: lineitem.product_id })
				.then(product => {
					if (product.price !== lineitem.price) {
						lineitem.price_customised = true;
						lineitem.price_customised_user_id = lineitem.__user._id;
						lineitem.price_customised_date = new Date();
					}
					next();
				})
				.catch(err => {
					console.error(err);
					next(err);
				});
			} else {
				License.findOne({ _id: lineitem.license_id }).populate('membership_id').populate('organisation_id')
				.then(license => {
					var price = null;
					if (license.organisation_id.user_id === license.user_id) {
						price = license.membership_id.cost;
					} else {
						price = license.membership_id.cost_extra_member;
					}
					if (price !== lineitem.price) {
						lineitem.price_customised = true;
						lineitem.price_customised_user_id = lineitem.__user._id;
						lineitem.price_customised_date = new Date();
					}
					next();
				})
				.catch(err => {
					console.error(err);
					next(err);
				});
			}
		}
	})
	.catch(err => {
		console.error(err);
		next(err);
	});
});

module.exports = mongoose.model("LineItem", LineItemSchema);
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

  // Default task.
  grunt.registerTask('default', ['karma', 'jshint']);
  grunt.registerTask('build', ['karma', 'jshint', 'concat', 'uglify']);

  var karmaConfig = function(configFile, customOptions) {
    var options = { configFile: configFile, keepalive: true };
    var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
    return grunt.util._.extend(options, customOptions, travisOptions);
  };

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('bower.json'),
    meta: {
      banner: '/*!\n' +
        ' * <%= pkg.name %> v<%= pkg.version %>\n' +
        ' * The MIT License\n' +
        ' * Copyright (c) 2013 Jan Antala\n' +
        ' */'
    },
    uglify: {
      options: {
        preserveComments: 'some'
      },
      dist: {
        src: '<%= pkg.name %>.js',
        dest: '<%= pkg.name %>.min.js'
      }
    },
    concat: {
      options: {
        process: true,
        banner: '<%= meta.banner %>\n\n'
      },
      dist: {
        src: 'src/<%= pkg.name %>.js',
        dest: '<%= pkg.name %>.js'
      }
    },
    karma: {
      unit: {
        options: karmaConfig('test/test.conf.js')
      }
    },
    jshint:{
      files:['src/**/*.js', 'test/**/*.js'],
      options: {
        curly:true,
        eqeqeq:true,
        immed:true,
        latedef:true,
        newcap:true,
        noarg:true,
        sub:true,
        boss:true,
        eqnull:true,
        devel:true,
        globals:{}
      }
    },
    changelog: {
      options: {
        dest: 'CHANGELOG.md'
      }
    },
  });
};
<commit_msg>chore(Grunt): use load-grunt-tasks<commit_after>module.exports = function (grunt) {
  require('load-grunt-tasks')(grunt);

  // Default task.
  grunt.registerTask('default', ['karma', 'jshint']);
  grunt.registerTask('build', ['karma', 'jshint', 'concat', 'uglify']);

  var karmaConfig = function(configFile, customOptions) {
    var options = { configFile: configFile, keepalive: true };
    var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
    return grunt.util._.extend(options, customOptions, travisOptions);
  };

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('bower.json'),
    meta: {
      banner: '/*!\n' +
        ' * <%= pkg.name %> v<%= pkg.version %>\n' +
        ' * The MIT License\n' +
        ' * Copyright (c) 2013 Jan Antala\n' +
        ' */'
    },
    uglify: {
      options: {
        preserveComments: 'some'
      },
      dist: {
        src: '<%= pkg.name %>.js',
        dest: '<%= pkg.name %>.min.js'
      }
    },
    concat: {
      options: {
        process: true,
        banner: '<%= meta.banner %>\n\n'
      },
      dist: {
        src: 'src/<%= pkg.name %>.js',
        dest: '<%= pkg.name %>.js'
      }
    },
    karma: {
      unit: {
        options: karmaConfig('test/test.conf.js')
      }
    },
    jshint:{
      files:['src/**/*.js', 'test/**/*.js'],
      options: {
        curly:true,
        eqeqeq:true,
        immed:true,
        latedef:true,
        newcap:true,
        noarg:true,
        sub:true,
        boss:true,
        eqnull:true,
        devel:true,
        globals:{}
      }
    },
    changelog: {
      options: {
        dest: 'CHANGELOG.md'
      }
    },
  });
};
<|endoftext|>


<commit_before>/*
** Module dependencies
*/
var _ = require('lodash');
var util = require('util');
var es = require('event-stream');
var csw = require('csw-client');

var mongoose = require('../../mongoose');
var ServiceSyncJob = require('../syncJob');
var parseRecord = require('../../parsers/record').parse;

var Record = mongoose.model('Record');

/*
** Constructor
*/
function CswHarvestJob(job, options) {
    ServiceSyncJob.call(this, job, options);
}

util.inherits(CswHarvestJob, ServiceSyncJob);

/*
** Methods
*/
CswHarvestJob.prototype.createCswHarvester = function() {
    var location = this.service.location;

    location.replace('metadata.carmencarto.fr/geosource-', 'metadata.carmencarto.fr/geosource/');

    var client = csw(location, {
        // Removed since redirections may break agent definition (example: http > https)
        // maxSockets: this.data.maxSockets || 5,
        // keepAlive: true,
        retry: this.data.maxRetry || 3,
        userAgent: 'Afigeo CSW harvester',
        concurrency: 5,
        noEncodeQs: location.indexOf('metadata.carmencarto.fr') !== -1
    });

    var harvesterOptions = {
        typeNames: 'gmd:MD_Metadata',
        outputSchema: 'http://www.isotc211.org/2005/gmd',
        elementSetName: 'full',
        constraintLanguage: 'CQL_TEXT'
    };

    if (location.indexOf('isogeo') !== -1) harvesterOptions.namespace = 'xmlns(gmd=http://www.isotc211.org/2005/gmd)';
    if (location.indexOf('geoportal/csw/discovery') !== -1) delete harvesterOptions.constraintLanguage;

    return client.harvest(harvesterOptions);
};

CswHarvestJob.prototype.stats = function () {
    var recordTypeStats = this.recordTypeStats = {};
    var recordStatusStats = this.recordStatusStats = {};

    return es.mapSync(function (processResult) {
        var parseResult = processResult.parseResult;
        var recordType = parseResult.recordType;
        var processStatus = parseResult.valid ? processResult.upsertStatus : 'not-valid';

        if (!(recordType in recordTypeStats)) {
            recordTypeStats[recordType] = 1;
        } else {
            recordTypeStats[recordType]++;
        }

        if (!(processStatus in recordStatusStats)) {
            recordStatusStats[processStatus] = 1;
        } else {
            recordStatusStats[processStatus]++;
        }

        return processResult;
    });
};

CswHarvestJob.prototype.globalProgress = function () {
    this.returned = 0;
    var job = this;

    return es.mapSync(function (record) {
        job.returned++;
        job.progress(job.returned, job.matched);
        return record;
    });
};

CswHarvestJob.prototype.processRecord = function () {
    var job = this;

    return es.map(function (xmlElement, done) {
        var parseResult = parseRecord(xmlElement);

        if (!parseResult.parsedRecord || !parseResult.valid) {
            return done(null, { parseResult: parseResult });
        }

        var record = {
            parentCatalog: job.service._id,
            hashedId: parseResult.hashedId,
            hashedRecord: parseResult.hashedRecord,
            dateStamp: parseResult.updatedAt,
            metadata: parseResult.parsedRecord,
            identifier: parseResult.id
        };

        Record.upsert(record, function (err, upsertStatus) {
            if (err) return done(err);
            done(null, { parseResult: parseResult, upsertStatus: upsertStatus });
        });
    });
};

/*
** Sync method
*/
CswHarvestJob.prototype._sync = function() {
    var job = this;
    var harvester = this.harvester = this.createCswHarvester();

    harvester.on('error', function(err) {
        job.log(util.inspect(err));
    });

    harvester.on('failed', function () {
        job.fail(new Error('Harvesting has failed'));
    });

    harvester.on('started', function() {
        job.matched = this.matched;
        job.log('Records matched: %d', this.matched);
    });

    harvester
        .pipe(this.processRecord())
        .pipe(this.stats())
        .pipe(this.globalProgress())
        .on('end', function () {
            job.log('Records returned: %d', harvester.returned);
            job.log('Statistics by record type:');
            _.forEach(job.recordTypeStats, function(count, recordType) {
                job.log('* %s: %d', recordType, count);
            });
            job.log('Statistics by record status:');
            _.forEach(job.recordStatusStats, function(count, recordStatus) {
                job.log('* %s: %d', recordStatus, count);
            });
            job.success(harvester.returned);
        })
        .resume();
};

CswHarvestJob.prototype._finish = function () {
    if (this.harvester) {
        this.harvester.pause();
        this.harvester.unpipe();
        this.harvester.removeAllListeners();
        this.harvester = null;
    }
};

/*
** Exports
*/
exports.harvest = function(job, done) {
    (new CswHarvestJob(job, { failsAfter: 600 })).start(done);
};
<commit_msg>Ensure Tigéo is not harvested in legacy mode<commit_after>/*
** Module dependencies
*/
var _ = require('lodash');
var s = require('underscore.string');
var util = require('util');
var es = require('event-stream');
var csw = require('csw-client');

var mongoose = require('../../mongoose');
var ServiceSyncJob = require('../syncJob');
var parseRecord = require('../../parsers/record').parse;

var Record = mongoose.model('Record');

/*
** Constructor
*/
function CswHarvestJob(job, options) {
    ServiceSyncJob.call(this, job, options);
}

util.inherits(CswHarvestJob, ServiceSyncJob);

/*
** Methods
*/
CswHarvestJob.prototype.createCswHarvester = function() {
    var location = this.service.location;

    location.replace('metadata.carmencarto.fr/geosource-', 'metadata.carmencarto.fr/geosource/');

    var client = csw(location, {
        // Removed since redirections may break agent definition (example: http > https)
        // maxSockets: this.data.maxSockets || 5,
        // keepAlive: true,
        retry: this.data.maxRetry || 3,
        userAgent: 'Afigeo CSW harvester',
        concurrency: 5,
        noEncodeQs: location.indexOf('metadata.carmencarto.fr') !== -1
    });

    var harvesterOptions = {
        typeNames: 'gmd:MD_Metadata',
        outputSchema: 'http://www.isotc211.org/2005/gmd',
        elementSetName: 'full',
        constraintLanguage: 'CQL_TEXT'
    };

    if (location.indexOf('isogeo') !== -1) harvesterOptions.namespace = 'xmlns(gmd=http://www.isotc211.org/2005/gmd)';
    if (location.indexOf('geoportal/csw/discovery') !== -1) delete harvesterOptions.constraintLanguage;
    if (s.include(location, 'tigeo')) delete harvesterOptions.constraintLanguage;

    return client.harvest(harvesterOptions);
};

CswHarvestJob.prototype.stats = function () {
    var recordTypeStats = this.recordTypeStats = {};
    var recordStatusStats = this.recordStatusStats = {};

    return es.mapSync(function (processResult) {
        var parseResult = processResult.parseResult;
        var recordType = parseResult.recordType;
        var processStatus = parseResult.valid ? processResult.upsertStatus : 'not-valid';

        if (!(recordType in recordTypeStats)) {
            recordTypeStats[recordType] = 1;
        } else {
            recordTypeStats[recordType]++;
        }

        if (!(processStatus in recordStatusStats)) {
            recordStatusStats[processStatus] = 1;
        } else {
            recordStatusStats[processStatus]++;
        }

        return processResult;
    });
};

CswHarvestJob.prototype.globalProgress = function () {
    this.returned = 0;
    var job = this;

    return es.mapSync(function (record) {
        job.returned++;
        job.progress(job.returned, job.matched);
        return record;
    });
};

CswHarvestJob.prototype.processRecord = function () {
    var job = this;

    return es.map(function (xmlElement, done) {
        var parseResult = parseRecord(xmlElement);

        if (!parseResult.parsedRecord || !parseResult.valid) {
            return done(null, { parseResult: parseResult });
        }

        var record = {
            parentCatalog: job.service._id,
            hashedId: parseResult.hashedId,
            hashedRecord: parseResult.hashedRecord,
            dateStamp: parseResult.updatedAt,
            metadata: parseResult.parsedRecord,
            identifier: parseResult.id
        };

        Record.upsert(record, function (err, upsertStatus) {
            if (err) return done(err);
            done(null, { parseResult: parseResult, upsertStatus: upsertStatus });
        });
    });
};

/*
** Sync method
*/
CswHarvestJob.prototype._sync = function() {
    var job = this;
    var harvester = this.harvester = this.createCswHarvester();

    harvester.on('error', function(err) {
        job.log(util.inspect(err));
    });

    harvester.on('failed', function () {
        job.fail(new Error('Harvesting has failed'));
    });

    harvester.on('started', function() {
        job.matched = this.matched;
        job.log('Records matched: %d', this.matched);
    });

    harvester
        .pipe(this.processRecord())
        .pipe(this.stats())
        .pipe(this.globalProgress())
        .on('end', function () {
            job.log('Records returned: %d', harvester.returned);
            job.log('Statistics by record type:');
            _.forEach(job.recordTypeStats, function(count, recordType) {
                job.log('* %s: %d', recordType, count);
            });
            job.log('Statistics by record status:');
            _.forEach(job.recordStatusStats, function(count, recordStatus) {
                job.log('* %s: %d', recordStatus, count);
            });
            job.success(harvester.returned);
        })
        .resume();
};

CswHarvestJob.prototype._finish = function () {
    if (this.harvester) {
        this.harvester.pause();
        this.harvester.unpipe();
        this.harvester.removeAllListeners();
        this.harvester = null;
    }
};

/*
** Exports
*/
exports.harvest = function(job, done) {
    (new CswHarvestJob(job, { failsAfter: 600 })).start(done);
};
<|endoftext|>


<commit_before>/**
 * Test that we're able to add a custom type via the
 * addType method.
 */
describe('ngNotify addType method', function() {
    'use strict';

    var ngNotify,
        doc,
        element,
        scope;

    var message = 'Message to display during tests.';
    var newTypeName = 'notice';
    var newTypeClass = 'ngn-notice';

    /**
     * Setup our application before running each test.
     */

    beforeEach(module('ngNotify'));

    beforeEach(inject(function($injector, $document) {

        ngNotify = $injector.get('ngNotify');

        doc = $document;

        element = angular.element(
            document.querySelector('.ngn')
        );

        scope = element.scope();
    }));

    /**
     * Start from a clean slate between every single test.
     */

    afterEach(function() {
        doc.find('body').empty();
    });

    /**
     * Setup addType method tests.
     */

    it('string type notice is not set', function() {

        ngNotify.set(message, newTypeName);

        expect(
            scope.ngNotify.notifyClass.indexOf("ngn-" + newTypeName) > -1
        ).toBe(false);
    });

    it('object type notice is not set', function() {

        ngNotify.set(message, {
            type: newTypeName
        });

        expect(
            scope.ngNotify.notifyClass.indexOf("ngn-" + newTypeName) > -1
        ).toBe(false);
    });

    it('config type notice is not set', function() {

        ngNotify.config({
            type: newTypeName
        });

        ngNotify.set(message);

        expect(
            scope.ngNotify.notifyClass.indexOf("ngn-" + newTypeName) > -1
        ).toBe(false);
    });

    it('string type notice is set', function() {

        ngNotify.addType(newTypeName, newTypeClass);

        ngNotify.set(message, newTypeName);

        expect(
            scope.ngNotify.notifyClass.indexOf("ngn-" + newTypeName) > -1
        ).toBe(true);
    });

    it('object type notice is set', function() {

        ngNotify.addType(newTypeName, newTypeClass);

        ngNotify.set(message, {
            type: newTypeName
        });

        expect(
            scope.ngNotify.notifyClass.indexOf("ngn-" + newTypeName) > -1
        ).toBe(true);
    });

    it('config type notice is set', function() {

        ngNotify.addType(newTypeName, newTypeClass);

        ngNotify.config({
            type: newTypeName
        });

        ngNotify.set(message);

        expect(
            scope.ngNotify.notifyClass.indexOf("ngn-" + newTypeName) > -1
        ).toBe(true);
    });

});
<commit_msg>Update params for newType.<commit_after>/**
 * Test that we're able to add a custom type via the
 * addType method.
 */
describe('ngNotify addType method', function() {
    'use strict';

    var ngNotify,
        doc,
        element,
        scope;

    var message = 'Message to display during tests.';
    var newTypeName = 'notice';
    var newTypeClass = 'ngn-notice';

    /**
     * Setup our application before running each test.
     */

    beforeEach(module('ngNotify'));

    beforeEach(inject(function($injector, $document) {

        ngNotify = $injector.get('ngNotify');

        doc = $document;

        element = angular.element(
            document.querySelector('.ngn')
        );

        scope = element.scope();
    }));

    /**
     * Start from a clean slate between every single test.
     */

    afterEach(function() {
        doc.find('body').empty();
    });

    /**
     * Setup addType method tests.
     */

    it('string type notice is not set', function() {

        ngNotify.set(message, newTypeName);

        expect(
            scope.ngNotify.notifyClass.indexOf(newTypeClass) > -1
        ).toBe(false);
    });

    it('object type notice is not set', function() {

        ngNotify.set(message, {
            type: newTypeName
        });

        expect(
            scope.ngNotify.notifyClass.indexOf(newTypeClass) > -1
        ).toBe(false);
    });

    it('config type notice is not set', function() {

        ngNotify.config({
            type: newTypeName
        });

        ngNotify.set(message);

        expect(
            scope.ngNotify.notifyClass.indexOf(newTypeClass) > -1
        ).toBe(false);
    });

    it('string type notice is set', function() {

        ngNotify.addType(newTypeName, newTypeClass);

        ngNotify.set(message, newTypeName);

        expect(
            scope.ngNotify.notifyClass.indexOf(newTypeClass) > -1
        ).toBe(true);
    });

    it('object type notice is set', function() {

        ngNotify.addType(newTypeName, newTypeClass);

        ngNotify.set(message, {
            type: newTypeName
        });

        expect(
            scope.ngNotify.notifyClass.indexOf(newTypeClass) > -1
        ).toBe(true);
    });

    it('config type notice is set', function() {

        ngNotify.addType(newTypeName, newTypeClass);

        ngNotify.config({
            type: newTypeName
        });

        ngNotify.set(message);

        expect(
            scope.ngNotify.notifyClass.indexOf(newTypeClass) > -1
        ).toBe(true);
    });

});
<|endoftext|>


<commit_before>angular.module( 'App.Client.Launcher' )
.run( function( $rootScope, Client_Launcher )
{
	$rootScope.$on( 'Client_Library.watchersSet', function()
	{
		Client_Launcher.init();
	} );
} )
.service( 'Client_Launcher', function( $q, $rootScope, Client_Library, Device, Growls )
{
	var _this = this;

	this.currentlyPlaying = [];

	this.init = function()
	{
		// Reattach all running games after a restart.
		_.forEach( Client_Library.packages, function( localPackage )
		{
			if ( localPackage.isRunning() ) {
				_this.reattach( localPackage );
			}
		} );
	};

	this.launch = function( localPackage )
	{
		var Launcher = require( 'client-voodoo' ).Launcher;
		var os = Device.os();
		var arch = Device.arch();

		return $q.when( Launcher.launch( localPackage, os, arch ).promise )
			.then( function( launchInstance )
			{
				return _this.attach( localPackage, launchInstance );
			} )
			.catch( function( e )
			{
				console.error( e );
				Growls.error( 'Could not launch game.' );
			} );
	};

	this.reattach = function( localPackage )
	{
		var Launcher = require( 'client-voodoo' ).Launcher;

		return $q.when( Launcher.attach( localPackage.running_pid ) )
			.then( function( launchInstance )
			{
				// It's no longer running.
				if ( !launchInstance ) {
					_this.gameClosed( localPackage );
					return;
				}

				return _this.attach( localPackage, launchInstance );
			} );
	};

	this.attach = function( localPackage, launchInstance )
	{
		this.currentlyPlaying.push( localPackage );

		launchInstance.on( 'end', function()
		{
			_this.gameClosed( localPackage );
		} );

		$rootScope.$emit( 'Client_Launcher.gameLaunched', this.currentlyPlaying.length );

		return localPackage.$setRunningPid( launchInstance.pid );
	};

	this.gameClosed = function( localPackage )
	{
		localPackage.$clearRunningPid();
		_.remove( this.currentlyPlaying, { id: localPackage.id } );
		$rootScope.$emit( 'Client_Launcher.gameClosed', this.currentlyPlaying.length );
	};
} );
<commit_msg>Tightening up how we clear running pid for packages. Also set up for new pid finder.<commit_after>angular.module( 'App.Client.Launcher' )
.run( function( $rootScope, Client_Launcher )
{
	$rootScope.$on( 'Client_Library.watchersSet', function()
	{
		Client_Launcher.init();
	} );
} )
.service( 'Client_Launcher', function( $q, $rootScope, Client_Library, Device, Growls )
{
	var _this = this;

	this.currentlyPlaying = [];

	this.init = function()
	{
		// Reattach all running games after a restart.
		_.forEach( Client_Library.packages, function( localPackage )
		{
			if ( localPackage.isRunning() ) {
				_this.reattach( localPackage );
			}
		} );
	};

	this.launch = function( localPackage )
	{
		var Launcher = require( 'client-voodoo' ).Launcher;
		var os = Device.os();
		var arch = Device.arch();

		return $q.when( Launcher.launch( localPackage, os, arch ).promise )
			.then( function( launchInstance )
			{
				return _this.attach( localPackage, launchInstance );
			} )
			.catch( function( e )
			{
				_this.clear( localPackage );
				console.error( e );
				Growls.error( 'Could not launch game.' );
			} );
	};

	this.reattach = function( localPackage )
	{
		var Launcher = require( 'client-voodoo' ).Launcher;

		return $q.when( Launcher.attach( localPackage.running_pid ) )
			.then( function( launchInstance )
			{
				return _this.attach( localPackage, launchInstance );
			} )
			.catch( function()
			{
				_this.clear( localPackage );
			} );
	};

	this.attach = function( localPackage, launchInstance )
	{
		this.currentlyPlaying.push( localPackage );

		launchInstance.on( 'pid', function()
		{
			localPackage.$setRunningPid( launchInstance.pid )
		} );

		launchInstance.on( 'end', function()
		{
			_this.clear( localPackage );
		} );

		$rootScope.$emit( 'Client_Launcher.gameLaunched', this.currentlyPlaying.length );

		return localPackage.$setRunningPid( launchInstance.pid );
	};

	this.clear = function( localPackage )
	{
		var removedItems = _.remove( this.currentlyPlaying, { id: localPackage.id } );
		localPackage.$clearRunningPid();
		if ( removedItems.length ) {
			$rootScope.$emit( 'Client_Launcher.gameClosed', this.currentlyPlaying.length );
		}
	};
} );
<|endoftext|>


<commit_before>
export default Em.Component.extend({
  fileInput: null,
  loading: false,
  expectedRootObjectName: null,
  hover: 0,

  classNames: ['json-uploader'],

  _initialize: function() {
    const $this = this.$();
    const self = this;

    const $fileInput = $this.find('#js-file-input');
    this.set('fileInput', $fileInput[0]);

    $fileInput.on('change', function() {
      self.fileSelected(this.files);
    });

    const $dragContainer = $this.find('.jsfu-shade-container');

    $this.on('dragover', function(e) {
      if (e.preventDefault) e.preventDefault();
      //self.set('hover', true);
      return false;
    });
    $this.on('dragenter', function(e) {
      if (e.preventDefault) e.preventDefault();
      console.log('dragenter');
      self.set('hover', self.get('hover') + 1);
      return false;
    });
    $this.on('dragleave', function(e) {
      if (e.preventDefault) e.preventDefault();
      console.log('dragleave');
      self.set('hover', self.get('hover') - 1);
      return false;
    });
    $this.on('drop', function(e) {
      if (e.preventDefault) e.preventDefault();

      self.set('hover', 0);
      self.fileSelected(e.dataTransfer.files);
      return false;
    });

  }.on('didInsertElement'),

  accept: function() {
    return ".json,application/json" + (this.get('extension') ? "," + this.get('extension') : "");
  }.property('extension'),

  setReady: function() {
    let parsed;
    try {
      parsed = JSON.parse(this.get('value'));
    } catch (e) {
      this.set('ready', false);
      return;
    }

    const rootObject = parsed[this.get('expectedRootObjectName')];

    if (rootObject !== null && rootObject !== undefined) {
      this.set('ready', true);
    } else {
      this.set('ready', false);
    }
  }.observes('destination', 'expectedRootObjectName'),

  actions: {
    selectFile: function() {
      const $fileInput = $(this.get('fileInput'));
      $fileInput.click();
    }
  },

  fileSelected(fileList) {
    const self = this;
    const numFiles = fileList.length;
    const firstFile = fileList[0];

    this.set('loading', true);

    let reader = new FileReader();
    reader.onload = function(evt) {
      self.set('value', evt.target.result);
      self.set('loading', false);
    };

    reader.readAsText(firstFile);
  }

});
<commit_msg>Filter files to only plain-text<commit_after>
export default Em.Component.extend({
  fileInput: null,
  loading: false,
  expectedRootObjectName: null,
  hover: 0,

  classNames: ['json-uploader'],

  _initialize: function() {
    const $this = this.$();
    const self = this;

    const $fileInput = $this.find('#js-file-input');
    this.set('fileInput', $fileInput[0]);

    $fileInput.on('change', function() {
      self.fileSelected(this.files);
    });

    const $dragContainer = $this.find('.jsfu-shade-container');

    $this.on('dragover', function(e) {
      if (e.preventDefault) e.preventDefault();
      return false;
    });
    $this.on('dragenter', function(e) {
      if (e.preventDefault) e.preventDefault();
      self.set('hover', self.get('hover') + 1);
      return false;
    });
    $this.on('dragleave', function(e) {
      if (e.preventDefault) e.preventDefault();
      self.set('hover', self.get('hover') - 1);
      return false;
    });
    $this.on('drop', function(e) {
      if (e.preventDefault) e.preventDefault();

      self.set('hover', 0);
      self.fileSelected(e.dataTransfer.files);
      return false;
    });

  }.on('didInsertElement'),

  accept: function() {
    return ".json,application/json" + (this.get('extension') ? "," + this.get('extension') : "");
  }.property('extension'),

  setReady: function() {
    let parsed;
    try {
      parsed = JSON.parse(this.get('value'));
    } catch (e) {
      this.set('ready', false);
      return;
    }

    const rootObject = parsed[this.get('expectedRootObjectName')];

    if (rootObject !== null && rootObject !== undefined) {
      this.set('ready', true);
    } else {
      this.set('ready', false);
    }
  }.observes('destination', 'expectedRootObjectName'),

  actions: {
    selectFile: function() {
      const $fileInput = $(this.get('fileInput'));
      $fileInput.click();
    }
  },

  fileSelected(fileList) {
    const self = this;
    let files = [];
    for (let i = 0; i < fileList.length; i++) {
      files[i] = fileList[i];
    }
    const fileNameRegex = /\.(json|txt)$/;
    files = files.filter(function(file) {
      if (fileNameRegex.test(file.name)) {
        return true;
      }
      if (file.type === "text/plain") {
        return true;
      }
      return false;
    });
    const firstFile = fileList[0];

    this.set('loading', true);

    let reader = new FileReader();
    reader.onload = function(evt) {
      self.set('value', evt.target.result);
      self.set('loading', false);
    };

    reader.readAsText(firstFile);
  }

});
<|endoftext|>


<commit_before>var LIB_Model = function() {
    evento.EventTarget.call(this);
};

evento.EventTarget.mixin(LIB_Model.prototype);
<commit_msg>add model to namespace<commit_after>maria.Model = function() {
    evento.EventTarget.call(this);
};

evento.EventTarget.mixin(LIB_Model.prototype);
<|endoftext|>


<commit_before>var game = zepto

var canvas;

var ticks;
var ticker;
var events;

var stdout;

// Tick about 40 times per second.
// This should sync okay with the music at 144 bpm.
var tickMillis = 26.041;

function StampedEvent (stamp, event) {
    this.stamp = ticks;
    this.event = event;
}

function startPlaying() {
    stdout.innerHTML = "YOU ARE NOW PLAYING";
    game.init(canvas);
    canvas.onmousedown = mdown;
    window.onkeyup = kup;
    window.onkeydown = kdown;
    ticks = 0;
    events = Array();
    ticker = window.setInterval(tick, tickMillis);
}

function startReplaying() {
    events.reverse();
    console.log(events);
    stdout.innerHTML = "REPLAY";
    game.init(canvas);
    ticks = 0;
    ticker = window.setInterval(tickReplay, tickMillis);
}

function tickReplay() {
//    var event = events.pop();
//    while(event.stamp < ticks) {
//        console.out(event);
//        event = events.pop();
//    }

    game.tick();
    ++ticks;
}

function mainKdown(event) {
    if (event.keyCode == ' '.charCodeAt(0)) {
        startPlaying();
    } else if (event.keyCode == 82) {
        startReplaying();
    }
}

function mainMenu() {
    stdout = document.getElementById('stdout');
    canvas = document.getElementById('canvas');
    stdout.innerHTML = "MAIN MENU. SPACE TO PLAY";
    window.onkeydown = mainKdown;
}

function stopPlaying() {
    clearInterval(ticker);
    mainMenu();
}

function tick() {
    game.tick();
    if (game.isgameover()) {
        stdout.innerHTML = "you're dead";
        stopPlaying();
    }
    if (game.atcheckpoint()) {
        console.log("at checkpoint");
    }

    ++ticks;
}

function kup(event) {
    events.push(new StampedEvent(ticks, event));
    game.kup(event);
}

function kdown(event) {
    events.push(new StampedEvent(ticks, event));
    game.kdown(event);
}

function mdown(event) {
    events.push(new StampedEvent(ticks, event));
    game.mdown(event);
}

<commit_msg>replaying kinda works now<commit_after>var game = zepto

var canvas;

var ticks;
var ticker;
var events;

var stdout;

// Tick about 40 times per second.
// This should sync okay with the music at 144 bpm.
var tickMillis = 26.041;

function StampedEvent (stamp, event) {
    this.stamp = ticks;
    this.event = event;
}

function startPlaying() {
    stdout.innerHTML = "YOU ARE NOW PLAYING";
    game.init(canvas);
    canvas.onmousedown = mdown;
    window.onkeyup = kup;
    window.onkeydown = kdown;
    ticks = 0;
    events = Array();
    ticker = window.setInterval(tick, tickMillis);
}

function startReplaying() {
    events.reverse();
    stdout.innerHTML = "REPLAY";
    game.init(canvas);
    ticks = 0;
    ticker = window.setInterval(tickReplay, tickMillis);
}

function tickReplay() {
    var stampedEvent = events[events.length - 1];
    while(stampedEvent && (stampedEvent.stamp <= ticks) && (events.length > 0)) {
        stampedEvent = events.pop();
        event = stampedEvent.event;
        switch (event.type) {
        case "keydown":
            game.kdown(event);
            break;
        case "keyup":
            game.kup(event);
            break;
        case "gameover":
            stopPlaying();
        }
        stampedEvent = events[events.length - 1];
    }

    game.tick();
    ++ticks;
}

function mainKdown(event) {
    if (event.keyCode == ' '.charCodeAt(0)) {
        startPlaying();
    } else if (event.keyCode == 82) {
        startReplaying();
    }
}

function mainMenu() {
    stdout = document.getElementById('stdout');
    canvas = document.getElementById('canvas');
    stdout.innerHTML += "MAIN MENU. SPACE TO PLAY";
    window.onkeydown = mainKdown;
}

function stopPlaying() {
    clearInterval(ticker);
    mainMenu();
}

function tick() {
    game.tick();
    if (game.isgameover()) {
        stdout.innerHTML = "you're dead";
        events.push(new StampedEvent(ticks, {'type':'gameover'}));
        stopPlaying();
    }
    if (game.atcheckpoint()) {
        console.log("at checkpoint");
    }

    ++ticks;
}

function kup(event) {
    events.push(new StampedEvent(ticks, event));
    game.kup(event);
}

function kdown(event) {
    events.push(new StampedEvent(ticks, event));
    game.kdown(event);
}

function mdown(event) {
    events.push(new StampedEvent(ticks, event));
    game.mdown(event);
}

<|endoftext|>