<commit_before>/*
	The Cedric's Swiss Knife (CSK) - CSK REST Query test suite

	Copyright (c) 2015 Cédric Ronvel

	The MIT License (MIT)

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
*/

/* jshint unused:false */
/* global describe, it, before, after */

var restQuery = require( '../lib/restQuery.js' ) ;

var net = require( 'net' ) ;
var stream = require( 'stream' ) ;
var childProcess = require( 'child_process' ) ;

var async = require( 'async-kit' ) ;
var tree = require( 'tree-kit' ) ;
var string = require( 'string-kit' ) ;
var odm = require( 'odm-kit' ) ;

var buffertools = require( 'buffertools' ) ;
var mongodb = require( 'mongodb' ) ;

var expect = require( 'expect.js' ) ;

// Collections...
var blogs , posts , comments ;

var blogsDescriptor = {
	url: 'mongodb://localhost:27017/restQuery/blogs' ,
	properties: {
		description: { constraint: 'string' }
	} ,
	meta: {
	} ,
	indexes: [
	] ,
	hooks: {
	} ,
	useMemProxy: true
} ;

var postsDescriptor = {
	url: 'mongodb://localhost:27017/restQuery/posts' ,
	properties: {
		content: { constraint: 'string' }
	} ,
	meta: {
	} ,
	indexes: [
	] ,
	hooks: {
	} ,
	useMemProxy: true
} ;

var commentsDescriptor = {
	url: 'mongodb://localhost:27017/restQuery/comments' ,
	properties: {
		content: { constraint: 'string' }
	} ,
	meta: {
	} ,
	indexes: [
	] ,
	hooks: {
	} ,
	useMemProxy: true
} ;

			/* Utils */

// it flatten prototype chain, so a single object owns every property of its parents
var protoflatten = tree.extend.bind( undefined , { deep: true , deepFilter: { blacklist: [ mongodb.ObjectID.prototype ] } } , null ) ;

// clear DB: remove every item, so we can safely test
function clearDB( callback )
{
	async.parallel( [
		[ clearCollection , blogs ] ,
		[ clearCollection , posts ] ,
		[ clearCollection , comments ]
	] )
	.exec( callback ) ;
}

// clear DB: remove every item, so we can safely test
function clearDBIndexes( callback )
{
	async.parallel( [
		[ clearCollectionIndexes , blogs ] ,
		[ clearCollectionIndexes , posts ] ,
		[ clearCollectionIndexes , comments ]
	] )
	.exec( callback ) ;
}

function clearCollection( collection , callback )
{
	collection.driver.rawInit( function( error ) {
		if ( error ) { callback( error ) ; return ; }
		collection.driver.raw.remove( callback ) ;
	} ) ;
}

function clearCollectionIndexes( collection , callback )
{
	collection.driver.rawInit( function( error ) {
		if ( error ) { callback( error ) ; return ; }
		collection.driver.raw.dropIndexes( callback ) ;
	} ) ;
}

function commonApp()
{
	var app = restQuery.createApp() ;

	var blogsNode = app.createCollectionNode( 'blogs' , blogsDescriptor ) ;
	var postsNode = app.createCollectionNode( 'posts' , postsDescriptor ) ;
	var commentsNode = app.createCollectionNode( 'comments' , commentsDescriptor ) ;

	app.root.contains( blogsNode ) ;
	blogsNode.contains( postsNode ) ;
	postsNode.contains( commentsNode ) ;

	return app ;
}

			/* Tests */

// Force creating the collection
/*
before( function( done ) {

	blogs = world.createCollection( 'blogs' , blogsDescriptor ) ;
	expect( blogs ).to.be.a( odm.Collection ) ;

	posts = world.createCollection( 'posts' , postsDescriptor ) ;
	expect( posts ).to.be.a( odm.Collection ) ;

	comments = world.createCollection( 'comments' , commentsDescriptor ) ;
	expect( comments ).to.be.a( odm.Collection ) ;

	done() ;
} ) ;
*/

describe( "restQuery" , function() {

	/*
	it( "" , function( done ) {

		var root = restQuery.Root() ;

		root.attach( 'blogs' , blogsDescriptor ) ;
		root.attach( 'posts' , postsDescriptor ) ;
		root.attach( 'comments' , commentsDescriptor ) ;

		expect( root.children ).to.only.have.keys( 'Blogs' , 'Posts' , 'Comments' ) ;

		done() ;
	} ) ;
	*/

	it( "GET" , function( done ) {

		var app = commonApp() ;
		var performer = app.createPerformer() ;

		var blog = app.root.children.blogs.collection.createDocument( {
			title: 'My wonderful life' ,
			description: 'This is a supa blog!'
		} ) ;

		var id = blog.$._id ;

		async.series( [
			function( callback ) {
				blog.save( callback ) ;
			} ,
			function( callback ) {
				//app.root.get( '/' , function( error , object ) {
				//app.get( '/Blogs/my-blog/Posts/my-first-article/Comment/1' ) ;
				//app.root.get( '/Posts/' , function( error , object ) {
				//app.root.get( '/Blogs/' , function( error , object ) {
				app.root.get( performer , '/Blogs/' + id , function( error , object ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( 'result of get:' ) ;
					//console.log( string.inspect( { style: 'color' , proto: true } , object ) ) ;
					//delete object[''] ;
					//delete object._id ;
					console.log( object ) ;
					console.log( JSON.stringify( object ) ) ;
					expect( object.title ).to.be( 'My wonderful life' ) ;
					expect( object.description ).to.be( 'This is a supa blog!' ) ;
					callback() ;
				} ) ;
			}
		] )
		.exec( done ) ;

	} ) ;

	it( "PUT then GET" , function( done ) {

		var app = commonApp() ;
		var performer = app.createPerformer() ;

		async.series( [
			function( callback ) {
				app.root.put( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , {
					title: 'My wonderful life 2!!!' ,
					description: 'This is a supa blog! (x2)'
				} , function( error ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' ) ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				//app.root.get( '/' , function( error , object ) {
				//app.get( '/Blogs/my-blog/Posts/my-first-article/Comment/1' ) ;
				//app.root.get( '/Posts/' , function( error , object ) {
				//app.root.get( '/Blogs/' , function( error , object ) {
				app.root.get( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , function( error , object ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( 'result of get:' ) ;
					//console.log( string.inspect( { style: 'color' , proto: true } , object ) ) ;
					//delete object[''] ;
					//delete object._id ;
					console.log( object ) ;
					console.log( JSON.stringify( object ) ) ;
					expect( object.title ).to.be( 'My wonderful life 2!!!' ) ;
					expect( object.description ).to.be( 'This is a supa blog! (x2)' ) ;
					callback() ;
				} ) ;
			}
		] )
		.exec( done ) ;

	} ) ;

} ) ;

<commit_msg>better unit test<commit_after>/*
	The Cedric's Swiss Knife (CSK) - CSK REST Query test suite

	Copyright (c) 2015 Cédric Ronvel

	The MIT License (MIT)

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
*/

/* jshint unused:false */
/* global describe, it, before, after, beforeEach */

var restQuery = require( '../lib/restQuery.js' ) ;

var net = require( 'net' ) ;
var stream = require( 'stream' ) ;
var childProcess = require( 'child_process' ) ;

var async = require( 'async-kit' ) ;
var tree = require( 'tree-kit' ) ;
var string = require( 'string-kit' ) ;
var odm = require( 'odm-kit' ) ;

var buffertools = require( 'buffertools' ) ;
var mongodb = require( 'mongodb' ) ;

var expect = require( 'expect.js' ) ;

// Collections...
var blogs , posts , comments ;

var blogsDescriptor = {
	url: 'mongodb://localhost:27017/restQuery/blogs' ,
	properties: {
		description: { constraint: 'string' }
	} ,
	meta: {
	} ,
	indexes: [
	] ,
	hooks: {
	} ,
	useMemProxy: true
} ;

var postsDescriptor = {
	url: 'mongodb://localhost:27017/restQuery/posts' ,
	properties: {
		content: { constraint: 'string' }
	} ,
	meta: {
	} ,
	indexes: [
	] ,
	hooks: {
	} ,
	useMemProxy: true
} ;

var commentsDescriptor = {
	url: 'mongodb://localhost:27017/restQuery/comments' ,
	properties: {
		content: { constraint: 'string' }
	} ,
	meta: {
	} ,
	indexes: [
	] ,
	hooks: {
	} ,
	useMemProxy: true
} ;

			/* Utils */

// it flatten prototype chain, so a single object owns every property of its parents
var protoflatten = tree.extend.bind( undefined , { deep: true , deepFilter: { blacklist: [ mongodb.ObjectID.prototype ] } } , null ) ;

function clearCollection( collection , callback )
{
	collection.driver.rawInit( function( error ) {
		if ( error ) { callback( error ) ; return ; }
		collection.driver.raw.remove( callback ) ;
	} ) ;
}

function commonApp( callback )
{
	var app = restQuery.createApp() ;
	var performer = app.createPerformer() ;

	var blogsNode = app.createCollectionNode( 'blogs' , blogsDescriptor ) ;
	var postsNode = app.createCollectionNode( 'posts' , postsDescriptor ) ;
	var commentsNode = app.createCollectionNode( 'comments' , commentsDescriptor ) ;

	app.root.contains( blogsNode ) ;
	blogsNode.contains( postsNode ) ;
	postsNode.contains( commentsNode ) ;

	async.parallel( [
		[ clearCollection , blogsNode.collection ] ,
		[ clearCollection , postsNode.collection ] ,
		[ clearCollection , commentsNode.collection ]
	] )
	.exec( function( error ) {
		expect( error ).not.to.be.ok() ;
		if ( error ) { callback( error ) ; return ; }
		callback( undefined , app , performer ) ;
	} ) ;
}

			/* Tests */

// Force creating the collection
/*
before( function( done ) {

	blogs = world.createCollection( 'blogs' , blogsDescriptor ) ;
	expect( blogs ).to.be.a( odm.Collection ) ;

	posts = world.createCollection( 'posts' , postsDescriptor ) ;
	expect( posts ).to.be.a( odm.Collection ) ;

	comments = world.createCollection( 'comments' , commentsDescriptor ) ;
	expect( comments ).to.be.a( odm.Collection ) ;

	done() ;
} ) ;
*/

describe( "restQuery" , function() {

	/*
	it( "" , function( done ) {

		var root = restQuery.Root() ;

		root.attach( 'blogs' , blogsDescriptor ) ;
		root.attach( 'posts' , postsDescriptor ) ;
		root.attach( 'comments' , commentsDescriptor ) ;

		expect( root.children ).to.only.have.keys( 'Blogs' , 'Posts' , 'Comments' ) ;

		done() ;
	} ) ;
	*/

	it( "GET on an unexisting item" , function( done ) {

		commonApp( function( error , app , performer ) {

			app.root.get( performer , '/Blogs/111111111111111111111111' , function( error , object ) {

				expect( error ).to.be.ok() ;
				expect( error.type ).to.be( 'notFound' ) ;
				expect( error.httpStatus ).to.be( 404 ) ;
				console.log( error ) ;
				console.log( object ) ;
				done() ;
			} ) ;
		} ) ;
	} ) ;

	it( "GET on an existing item" , function( done ) {

		var app , performer , blog , id ;

		async.series( [
			function( callback ) {
				commonApp( function( error , a , p ) {
					app = a ;
					performer = p ;
					blog = app.root.children.blogs.collection.createDocument( {
						title: 'My wonderful life' ,
						description: 'This is a supa blog!'
					} ) ;
					id = blog.$._id ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				blog.save( callback ) ;
			} ,
			function( callback ) {
				//app.root.get( '/' , function( error , object ) {
				//app.get( '/Blogs/my-blog/Posts/my-first-article/Comment/1' ) ;
				//app.root.get( '/Posts/' , function( error , object ) {
				//app.root.get( '/Blogs/' , function( error , object ) {
				app.root.get( performer , '/Blogs/' + id , function( error , object ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( 'result of get:' ) ;
					//console.log( string.inspect( { style: 'color' , proto: true } , object ) ) ;
					//delete object[''] ;
					//delete object._id ;
					console.log( object ) ;
					console.log( JSON.stringify( object ) ) ;
					expect( object.title ).to.be( 'My wonderful life' ) ;
					expect( object.description ).to.be( 'This is a supa blog!' ) ;
					callback() ;
				} ) ;
			}
		] )
		.exec( done ) ;
	} ) ;

	it( "PUT then GET" , function( done ) {

		var app , performer , blog , id ;

		async.series( [
			function( callback ) {
				commonApp( function( error , a , p ) {
					app = a ;
					performer = p ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				app.root.put( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , {
					title: 'My wonderful life 2!!!' ,
					description: 'This is a supa blog! (x2)'
				} , function( error ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' ) ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				//app.root.get( '/' , function( error , object ) {
				//app.get( '/Blogs/my-blog/Posts/my-first-article/Comment/1' ) ;
				//app.root.get( '/Posts/' , function( error , object ) {
				//app.root.get( '/Blogs/' , function( error , object ) {
				app.root.get( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , function( error , object ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( 'result of get:' ) ;
					//console.log( string.inspect( { style: 'color' , proto: true } , object ) ) ;
					//delete object[''] ;
					//delete object._id ;
					console.log( object ) ;
					console.log( JSON.stringify( object ) ) ;
					expect( object.title ).to.be( 'My wonderful life 2!!!' ) ;
					expect( object.description ).to.be( 'This is a supa blog! (x2)' ) ;
					callback() ;
				} ) ;
			}
		] )
		.exec( done ) ;
	} ) ;

	it( "PUT, then DELETE, then GET" , function( done ) {

		var app , performer , blog , id ;

		async.series( [
			function( callback ) {
				commonApp( function( error , a , p ) {
					app = a ;
					performer = p ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				app.root.put( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , {
					title: 'My wonderful life 2!!!' ,
					description: 'This is a supa blog! (x2)'
				} , function( error ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' ) ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				app.root.delete( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , function( error ) {
					if ( error ) { callback( error ) ; return ; }
					console.log( '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' ) ;
					callback() ;
				} ) ;
			} ,
			function( callback ) {
				//app.root.get( '/' , function( error , object ) {
				//app.get( '/Blogs/my-blog/Posts/my-first-article/Comment/1' ) ;
				//app.root.get( '/Posts/' , function( error , object ) {
				//app.root.get( '/Blogs/' , function( error , object ) {
				app.root.get( performer , '/Blogs/5437f846c41d0e910ec9a5d8' , function( error , object ) {
					expect( error ).to.be.ok() ;
					expect( error.type ).to.be( 'notFound' ) ;
					expect( error.httpStatus ).to.be( 404 ) ;
					console.log( error ) ;
					console.log( object ) ;
					callback() ;
				} ) ;
			}
		] )
		.exec( done ) ;
	} ) ;

} ) ;

<|endoftext|>


<commit_before>describe('Tasks Table', function () {

  context('Task row', function () {
    beforeEach(function () {
      cy.configureCluster({
        mesos: '1-service-with-executor-task',
        nodeHealth: true
      });
      cy.visitUrl({url: '/services/%2Fcassandra/'});
    });

    it('displays task detail page on task click', function () {
      cy.get('a[title="server-0"]').click();
      cy.get('.page-content h1').should('to.have.text', 'server-0_10ab666b-cf9b-44eb-bc53-b6dba1b7c737');
    });

  });
});

<commit_msg>Added integration tests for task detail page files tab<commit_after>describe('Tasks Table', function () {

  context('Task row', function () {
    beforeEach(function () {
      cy.configureCluster({
        mesos: '1-service-with-executor-task',
        nodeHealth: true
      });
    });

    it('displays task detail page on task click', function () {
      cy.visitUrl({url: '/services/%2Fcassandra/'});
      cy.get('a[title="server-0"]').click();
      cy.get('.page-content h1').should('to.have.text', 'server-0_10ab666b-cf9b-44eb-bc53-b6dba1b7c737');
    });

    context('Files tab', function () {

      beforeEach(function () {
        cy.visitUrl({
          url: '/services/%2Fcassandra/task-detail/server-0_10ab666b-cf9b-44eb-bc53-b6dba1b7c737/'
        });
        cy.get('.page-content .tab-item-label').contains('Files').click();
      });

      it('shows the contents of the Mesos sandbox', function () {
        cy.get('.page-content tbody tr:visible')
          .should(function ($rows) {
            expect($rows.length).to.equal(13);
          });
      });

      it('shows directories as well as files', function () {
        cy.get('.page-content tbody tr:visible:first')
          .contains('jre1.7.0_76');
      });

    });

  });
});

<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var express = require('express'),
	gzippo = require('gzippo'),
	routes = require('./routes'),
	http = require('http'),
	path = require('path'),
	tag = require('./app/lexitag.js');

var app = express();

app.configure(function(){
	app.set('port', process.env.PORT || 3000);
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');
	app.use(express.favicon());
	app.use(express.logger('dev'));
	app.use(express.bodyParser());
	app.use(express.methodOverride());
	app.use(app.router);
	app.use(gzippo.staticGzip(path.join(__dirname, 'public')));
	app.use(gzippo.compress());
});

app.configure('development', function(){
	app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/test', routes.test);
app.get('/sw', routes.sw);
app.get('/lex', tag.lexitag);

http.createServer(app).listen(app.get('port'), function(){
	console.log("Express server listening on port " + app.get('port'));
});
<commit_msg>Switched from gzippo back to static delivery. zippo is waiting for bugfix<commit_after>
/**
 * Module dependencies.
 */

var express = require('express'),
	gzippo = require('gzippo'),
	routes = require('./routes'),
	http = require('http'),
	path = require('path'),
	tag = require('./app/lexitag.js');

var app = express();

app.configure(function(){
	app.set('port', process.env.PORT || 3000);
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');
	app.use(express.favicon());
	app.use(express.logger('dev'));
	app.use(express.bodyParser());
	app.use(express.methodOverride());
	app.use(app.router);
	app.use(express.static(__dirname + '/public'));
//	app.use(gzippo.staticGzip(path.join(__dirname, 'public')));
//	app.use(gzippo.compress());
});

app.configure('development', function(){
	app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/test', routes.test);
app.get('/sw', routes.sw);
app.get('/lex', tag.lexitag);

http.createServer(app).listen(app.get('port'), function(){
	console.log("Express server listening on port " + app.get('port'));
});
<|endoftext|>


<commit_before>import _ from 'lodash'; // eslint-disable-line
import React, { Component, PropTypes } from 'react' // eslint-disable-line
import { connect } from '@folio/stripes-connect'; // eslint-disable-line
import Pane from '@folio/stripes-components/lib/Pane' // eslint-disable-line
import PaneMenu from '@folio/stripes-components/lib/PaneMenu' // eslint-disable-line
import Button from '@folio/stripes-components/lib/Button' // eslint-disable-line
import KeyValue from '@folio/stripes-components/lib/KeyValue' // eslint-disable-line
import {Row, Col} from 'react-bootstrap' // eslint-disable-line
import TextField from '@folio/stripes-components/lib/TextField' // eslint-disable-line
import MultiColumnList from '@folio/stripes-components/lib/MultiColumnList' // eslint-disable-line
import Icon from '@folio/stripes-components/lib/Icon' // eslint-disable-line
import Layer from '@folio/stripes-components/lib/Layer'; // eslint-disable-line

import UserForm from './UserForm';
import UserPermissions from './UserPermissions';

class ViewUser extends Component {

  static propTypes = {
    params: PropTypes.object,
    data: PropTypes.shape({
      user: PropTypes.arrayOf(PropTypes.object),
      availablePermissions: PropTypes.arrayOf(PropTypes.object),
    }),
    mutator: React.PropTypes.shape({
      users: React.PropTypes.shape({
        PUT: React.PropTypes.func.isRequired,
      }),
    }),
  };

  static manifest = Object.freeze({
    users: {
      type: 'okapi',
      path: 'users/:{userid}',
      clear: false,
    },
    availablePermissions: {
      type: 'okapi',
      records: 'permissions',
      path: 'perms/permissions?length=100',
    },
    usersPermissions: {
      type: 'okapi',
      records: 'permissionNames',
      DELETE: {
        pk: 'permissionName',
        path: 'perms/users/:{username}/permissions',
      },
      GET: {
        path: 'perms/users/:{username}/permissions?full=true',
      },
      path: 'perms/users/:{username}/permissions',
    },
  });

  constructor(props) {
    super(props);
    this.state = {
      editUserMode: false,
    };
    this.onClickEditUser = this.onClickEditUser.bind(this);
    this.onClickCloseEditUser = this.onClickCloseEditUser.bind(this);
  }

  // EditUser Handlers
  onClickEditUser(e) {
    if (e) e.preventDefault();
    this.setState({
      editUserMode: true,
    });
  }

  onClickCloseEditUser(e) {
    if (e) e.preventDefault();
    this.setState({
      editUserMode: false,
    });
  }

  update(data) {
    // eslint-disable-next-line no-param-reassign
    if (data.creds) delete data.creds; // not handled on edit (yet at least)
    this.props.mutator.users.PUT(data).then(() => {
      this.onClickCloseEditUser();
    });
  }

  render() {
    const fineHistory = [{ 'Due Date': '11/12/2014', 'Amount': '34.23', 'Status': 'Unpaid' }]; // eslint-disable-line quote-props

    const detailMenu = <PaneMenu><button onClick={this.onClickEditUser} title="Edit User"><Icon icon="edit" />Edit</button></PaneMenu>;

    const { data: { users, availablePermissions, usersPermissions }, params: { userid } } = this.props;

    if (!users || users.length === 0 || !userid) return
;
    const user = users.find(u => u.id === userid);
    if (!user) return
;
    const userStatus = (_.get(user, ['active'], '') ? 'active' : 'inactive');

    return (
      <Pane defaultWidth="fill" paneTitle="User Details" lastMenu={detailMenu}>
        <Row>
          <Col xs={8} >
            <Row>
              <Col xs={12}>

{_.get(user, ['personal', 'last_name'], '')}, {_.get(user, ['personal', 'first_name'], '')}

              </Col>
            </Row>
            <Row>
              <Col xs={12}>
                <KeyValue label="Username" value={_.get(user, ['username'], '')} />
              </Col>
            </Row>

            <Row>
              <Col xs={12}>
                <KeyValue label="Status" value={userStatus} />
              </Col>
            </Row>

            <Row>
              <Col xs={12}>
                <KeyValue label="Email" value={_.get(user, ['personal', 'email'], '')} />
              </Col>
            </Row>

            <Row>
              <Col xs={12}>
                <KeyValue label="Patron group" value={_.get(user, ['patron_group'], '')} />
              </Col>
            </Row>
          </Col>
          <Col xs={4} >

          </Col>
        </Row>

        <Row>
          <Col xs={3}>

Fines

          </Col>
          <Col xs={4} sm={3}>
            <TextField
              rounded
              endControl={<Button buttonStyle="fieldControl"><Icon icon="clearX" /></Button>}
              startControl={<Icon icon="search" />}
              placeholder="Search"
              fullWidth
            />
          </Col>
          <Col xs={5} sm={6}>
            <Button align="end" bottomMargin0 >View Full History</Button>
          </Col>
        </Row>
        <MultiColumnList fullWidth contentData={fineHistory} />
        <UserPermissions availablePermissions={availablePermissions} usersPermissions={usersPermissions} viewUserProps={this.props} />

        <Layer isOpen={this.state.editUserMode} label="Edit User Dialog">
          <UserForm
            onSubmit={(record) => { this.update(record); }}
            initialValues={user}
            onCancel={this.onClickCloseEditUser}
          />
        </Layer>
      </Pane>
    );
  }
}

export default connect(ViewUser, '@folio/users');
<commit_msg>Remove unnecessary eslint-disable-line comments. Fix a few minor list-errors thereby revealed.<commit_after>import _ from 'lodash';
import React, { Component, PropTypes } from 'react';
import { connect } from '@folio/stripes-connect';
import Pane from '@folio/stripes-components/lib/Pane';
import PaneMenu from '@folio/stripes-components/lib/PaneMenu';
import Button from '@folio/stripes-components/lib/Button';
import KeyValue from '@folio/stripes-components/lib/KeyValue';
import { Row, Col } from 'react-bootstrap';
import TextField from '@folio/stripes-components/lib/TextField';
import MultiColumnList from '@folio/stripes-components/lib/MultiColumnList';
import Icon from '@folio/stripes-components/lib/Icon';
import Layer from '@folio/stripes-components/lib/Layer';

import UserForm from './UserForm';
import UserPermissions from './UserPermissions';

class ViewUser extends Component {

  static propTypes = {
    params: PropTypes.object,
    data: PropTypes.shape({
      user: PropTypes.arrayOf(PropTypes.object),
      availablePermissions: PropTypes.arrayOf(PropTypes.object),
    }),
    mutator: React.PropTypes.shape({
      users: React.PropTypes.shape({
        PUT: React.PropTypes.func.isRequired,
      }),
    }),
  };

  static manifest = Object.freeze({
    users: {
      type: 'okapi',
      path: 'users/:{userid}',
      clear: false,
    },
    availablePermissions: {
      type: 'okapi',
      records: 'permissions',
      path: 'perms/permissions?length=100',
    },
    usersPermissions: {
      type: 'okapi',
      records: 'permissionNames',
      DELETE: {
        pk: 'permissionName',
        path: 'perms/users/:{username}/permissions',
      },
      GET: {
        path: 'perms/users/:{username}/permissions?full=true',
      },
      path: 'perms/users/:{username}/permissions',
    },
  });

  constructor(props) {
    super(props);
    this.state = {
      editUserMode: false,
    };
    this.onClickEditUser = this.onClickEditUser.bind(this);
    this.onClickCloseEditUser = this.onClickCloseEditUser.bind(this);
  }

  // EditUser Handlers
  onClickEditUser(e) {
    if (e) e.preventDefault();
    this.setState({
      editUserMode: true,
    });
  }

  onClickCloseEditUser(e) {
    if (e) e.preventDefault();
    this.setState({
      editUserMode: false,
    });
  }

  update(data) {
    // eslint-disable-next-line no-param-reassign
    if (data.creds) delete data.creds; // not handled on edit (yet at least)
    this.props.mutator.users.PUT(data).then(() => {
      this.onClickCloseEditUser();
    });
  }

  render() {
    const fineHistory = [{ 'Due Date': '11/12/2014', 'Amount': '34.23', 'Status': 'Unpaid' }]; // eslint-disable-line quote-props

    const detailMenu = <PaneMenu><button onClick={this.onClickEditUser} title="Edit User"><Icon icon="edit" />Edit</button></PaneMenu>;

    const { data: { users, availablePermissions, usersPermissions }, params: { userid } } = this.props;

    if (!users || users.length === 0 || !userid) return
;
    const user = users.find(u => u.id === userid);
    if (!user) return
;
    const userStatus = (_.get(user, ['active'], '') ? 'active' : 'inactive');

    return (
      <Pane defaultWidth="fill" paneTitle="User Details" lastMenu={detailMenu}>
        <Row>
          <Col xs={8} >
            <Row>
              <Col xs={12}>

{_.get(user, ['personal', 'last_name'], '')}, {_.get(user, ['personal', 'first_name'], '')}

              </Col>
            </Row>
            <Row>
              <Col xs={12}>
                <KeyValue label="Username" value={_.get(user, ['username'], '')} />
              </Col>
            </Row>

            <Row>
              <Col xs={12}>
                <KeyValue label="Status" value={userStatus} />
              </Col>
            </Row>

            <Row>
              <Col xs={12}>
                <KeyValue label="Email" value={_.get(user, ['personal', 'email'], '')} />
              </Col>
            </Row>

            <Row>
              <Col xs={12}>
                <KeyValue label="Patron group" value={_.get(user, ['patron_group'], '')} />
              </Col>
            </Row>
          </Col>
          <Col xs={4} >

          </Col>
        </Row>

        <Row>
          <Col xs={3}>

Fines

          </Col>
          <Col xs={4} sm={3}>
            <TextField
              rounded
              endControl={<Button buttonStyle="fieldControl"><Icon icon="clearX" /></Button>}
              startControl={<Icon icon="search" />}
              placeholder="Search"
              fullWidth
            />
          </Col>
          <Col xs={5} sm={6}>
            <Button align="end" bottomMargin0 >View Full History</Button>
          </Col>
        </Row>
        <MultiColumnList fullWidth contentData={fineHistory} />
        <UserPermissions availablePermissions={availablePermissions} usersPermissions={usersPermissions} viewUserProps={this.props} />

        <Layer isOpen={this.state.editUserMode} label="Edit User Dialog">
          <UserForm
            onSubmit={(record) => { this.update(record); }}
            initialValues={user}
            onCancel={this.onClickCloseEditUser}
          />
        </Layer>
      </Pane>
    );
  }
}

export default connect(ViewUser, '@folio/users');
<|endoftext|>


<commit_before>/**
 * @author: Shaun Janssens
 * @copyright: open Summer of code
 */
$(document).ready(function() {

    /**
     * Swipe controller
     * @type {{images: {}, index: number, liked: Array, disliked: Array, init: Function, getImages: Function,
     * getImage: Function, addImage: Function, setIndex: Function, checkLikes: Function, reset: Function, like:
     * Function, dislike: Function, tinder: Function}}
     */
    var swipe = {
        images : {},
        index : 0,
        liked : [],
        disliked : [],
        swipes : 0,
        maxswipes : 5,
        checkBooks : false,

        init : function() {
            swipe.getImages();
        },

        /**
         * Get images
         * Save tags
         * Add 3 images for init
         * Init tinder module
         */
        getImages : function() {
            jQuery.ajax({
                url: "http://api.bieblo.be/API/illustrations",
                type:"GET",
                dataType: "json",
                success: function(data) {
                    swipe.images = swipe.shuffle(data);

                    for(var i = 0; i < 3; i++) {
                        swipe.addImage();
                    }

                    swipe.tinder();
                },
                error : function(xhr, textStatus, errorThrown ) {
                    alert("Error: fout bij ophalen afbeelding. Code: " + xhr.status);
                }
            });
        },

        /**
         * Shuffle array object
         * @param data
         * @returns {*}
         */
        shuffle : function(data){
            for(var j, x, i = data.length; i; j = Math.floor(Math.random() * i), x = data[--i], data[i] = data[j], data[j] = x);
            return data;
        },

        /**
         * Get the next image
         * @returns {null|*}
         */
        getImage : function() {
            if(swipe.index >= swipe.images.length) {
                image = null;
            }
            else {
                image = swipe.images[swipe.index];
                swipe.index = swipe.index + 1;
            }

            return image;
        },

        /**
         * Add an image to the stack
         */
        addImage : function() {
            var data = swipe.getImage();

            if(data != null) {
                var handlebars = Handlebars.templates['tag-template'];
                $(".stack ul").append(handlebars(data));
            }

            swipe.setIndex();
        },

        /**
         * Calculate z-index on stack
         */
        setIndex : function() {
            $(".stack ul").children().each(function(i) {
                $(this).removeClass().addClass("tag_" + (i + 1));
                $(this).css("z-index", -i);
            });
        },

        /**
         * Check likes
         */
        checkSwipes : function() {
            swipe.swipes = swipe.swipes + 1;

            /**
             * Get books after 3 likes or after 5 swipes
             */
            if(parseInt(swipe.liked.length) == 3 && swipe.checkBooks == false) {
                overview.getBooks();
                swipe.checkBooks = true;
            }
            else if(parseInt(swipe.liked.length) < 3 && parseInt(swipe.swipes) == parseInt(swipe.maxswipes) && swipe.checkBooks == false) {
                overview.getBooks();
                swipe.checkBooks = true;
            }

            /**
             * Go to page 2 if all images are swiped
             */
            if(parseInt(swipe.swipes) == parseInt(swipe.images.length)) {
                page.showPage(2);
            }

            /**
             * Go to page 2 if swipe.maxswipes likes
             */
            if(parseInt(swipe.liked.length) == parseInt(swipe.maxswipes)) {
                page.showPage(2);
            }
        },

        /**
         * Reset and reinit
         */
        reset : function() {
            swipe.images = {};
            swipe.index = 0;
            swipe.liked = [];
            swipe.disliked = [];
            swipe.swipes = 0;
            swipe.checkBooks = false;
            $(".stack ul").empty();
            $(".books").empty();
            swipe.init();
            page.showPage(1);
        },

        /**
         * Like tag
         * @param item
         */
        like : function(item) {
            var id = $(item).data("id");
            swipe.liked.push(id);
            swipe.checkSwipes();
            $(item).remove();
            swipe.addImage();
            swipe.tinder();
        },

        /**
         * Dislike tag
         * @param item
         */
        dislike : function(item) {
            var id = $(item).data("id");
            swipe.disliked.push(id);
            swipe.checkSwipes();
            $(item).remove();
            swipe.addImage();
            swipe.tinder();
        },

        /**
         * Animate background on like and dislike
         * @param color
         */
        animateBackground : function(color) {
            if(color == "like") {
                $("body").removeClass().addClass("bg-liked2");

                setTimeout(function () {
                    $("body").removeClass("bg-liked2");
                }, 1000);
            }

            if(color == "dislike") {
                $("body").removeClass().addClass("bg-disliked2");

                setTimeout(function () {
                    $("body").removeClass("bg-disliked2");
                }, 1000);
            }
        },

        /**
         * Tinder plugin
         */
        tinder : function() {
            $(".stack").jTinder({
                onDislike: function (item) {
                    swipe.dislike(item);
                },
                onLike: function (item) {
                    swipe.like(item);
                },
                animationRevertSpeed: 200,
                animationSpeed: 400,
                threshold: 1,
                likeSelector: '#like',
                dislikeSelector: '#dislike'
            });
        }
    };

    /**
     * Overview controller
     * @type {{books: {}, index: number, booksPerPage: number, getBooks: Function, showBooks: Function,
     * showDetail: Function, removeDetail: Function}}
     */
    var overview = {
        books : {},
        index : 0,
        booksPerPage : 8,

        /**
         * Get the recommendations
         * Save all the books
         */
        getBooks : function() {
            var likes = overview.removeComma(swipe.liked.join());
            var dislikes = overview.removeComma(swipe.disliked.join());
            var url = "http://api.bieblo.be/API/recommendations?likes=" + likes + "&dislikes=" + dislikes;

            jQuery.ajax({
                url: url,
                type:"GET",
                dataType: "json",
                success: function(data) {
                    if(data == "unavailable") {
                        alert("Bibnet service niet beschikbaar. Probeer opnieuw.");
                        page.showPage(1);
                    }
                    else {
                        overview.index = overview.booksPerPage;
                        overview.books = data;
                        overview.showBooks(data);
                    }

                },
                error : function(xhr, textStatus, errorThrown ) {
                    console.log("Error: fout bij ophalen boeken. Code: " + xhr.status);
                    if(xhr.status == 404) {
                        alert("Bibnet service niet beschikbaar. Probeer opnieuw.");
                        swipe.reset();
                    }
                }
            });
        },

        /**
         * Remove the last comma of a string
         * @param str
         * @returns {XML|void|string}
         */
        removeComma : function(str) {
            return str.replace(/,(\s+)?$/, '');
        },

        /**
         * Show the overview
         * @param data
         */
        showBooks : function(data) {
            data = data.slice(0, overview.booksPerPage);
            var handlebars = Handlebars.templates['overview-template'];
            $(".books").append(handlebars(data));
        },

        /**
         * Show details popup
         * @param id
         */
        showDetail : function(id) {
            $(".books, header").addClass("blur", 200);
            $(".details").fadeIn(200);
            $(".overlay").fadeIn(200);

            var book = overview.books[id];
            var handlebars = Handlebars.templates['detail-template'];
            $(".overlay").append(handlebars(book));
        },

        /**
         * Remove details popup
         */
        removeDetail : function() {
            $(".books, header").removeClass("blur", 200);
            $(".details").fadeOut(200);
            $(".overlay").fadeOut(200).empty();
        },

        /**
         * Print function
         */
        print : function() {
            window.print()
        },

        /**
         * Show e-mail popup
         */
        showEmail : function() {
            var handlebars = Handlebars.templates['email-template'];
            $(".overview").append(handlebars());
            $(".books, header").addClass("blur", 200);
            $(".overview").fadeIn(200);
        },

        /**
         * Send e-mail with all the books
         */
        sendEmail : function() {
            var email = $("input[type=email]").val();
            var form = $(".email-popup form");

            $.ajax({
                url: "api/email",
                contentType: "application/json",
                type: "POST",
                data: {"email": email, "books": overview.books},
                dataType: 'json',
                success: function(data){
                    form.empty();
                    form.append("
U krijgt zo dadelijk een mail met uw boekenlijst
");
                    setTimeout(function() {
                        overview.closeEmail()
                    }, 5000);
                },
                error: function(){
                    form.empty();
                    form.append("
Er is iets mis gegaan. Gelieve contact op te nemen met de beheerder.
");
                    setTimeout(function() {
                        overview.closeEmail()
                    }, 5000);
                }
            })
        },

        /**
         * Close the e-mail popup
         */
        closeEmail : function() {
            $(".books, header").removeClass("blur", 200);
            $(".email-overlay").fadeOut(function() {
                $(this).remove();
            });
        },

        /**
         * Switch a book
         * @param id
         */
        switchBook : function(id) {
            if(overview.books.length == overview.index) {
                alert("Alle boeken zijn op");
            }
            else {
                overview.index++;

                var book = $("figure[data-index=" + id + "]").parent();

                $("figure[data-index=" + id + "]").parent().empty();

                data = overview.books[overview.index];
                var handlebars = Handlebars.templates["book-template"];
                $(book).append(handlebars(data));

                $(book).children("figure").attr("data-index", id);
            }
        },
    };

    /**
     * Page controller
     * @type {{startpage: number, currentpage: number, init: Function, showPage: Function}}
     */
    var page = {
        startpage : 1,
        currentpage: 1,

        init : function () {
            $("[data-page]").hide();
            page.showPage(page.startpage);

            swipe.init();
        },

        /**
         * Change page
         * @param newpage
         */
        showPage : function (newpage) {
            $("[data-page=" + page.currentpage +"]").fadeOut(300);
            $("[data-page=" + newpage +"]").fadeIn(300);
            page.currentpage = newpage;
        }

    };

    page.init();

    /**
     * Event handler
     */

    // Dislike button
    $(document).on('touchstart click', '#dislike', function(event){
        event.stopPropagation();
        event.preventDefault();
        if(event.handled !== true) {
            $(".tag_1").addClass("rotate-right");
            setTimeout(function() {
                var item = $(".rotate-right");
                swipe.dislike(item);
                swipe.animateBackground("dislike");
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Like button
    $(document).on('touchstart click', '#like', function(event){
        event.stopPropagation();
        event.preventDefault();
        if(event.handled !== true) {
            $(".tag_1").addClass("rotate-left");
            setTimeout(function() {
                var item = $(".rotate-left");
                swipe.like(item);
                swipe.animateBackground("like");
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Prevent touch move
    document.ontouchmove = function(event){
        event.preventDefault();
    };

    // Show detail overlay
    $(document).on("touchstart click", ".book figure", function(event){
        event.stopPropagation();
        event.preventDefault();

        var element = $(this);

        if(event.handled !== true) {
            setTimeout(function() {
                overview.showDetail($(element).data("index"));
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Hide detail overlay
    $(document).on("touchstart click", ".close", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.removeDetail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Keyboard shortcuts
    window.addEventListener('keydown', function(event) {
        switch (event.keyCode) {
            case 37: // Left => dislike
                $(".tag_1").addClass("rotate-right");
                setTimeout(function() {
                    var item = $(".rotate-right");
                    swipe.dislike(item);
                }, 400 );
                break;

            case 39: // Right => like
                $(".tag_1").addClass("rotate-left");
                setTimeout(function() {
                    var item = $(".rotate-left");
                    swipe.like(item);
                }, 400 );
                break;

            case 27: // Esc => close detail
                overview.removeDetail();
                break;
        }
    }, false);

    // Back button
    $(document).on("touchstart click", ".icon-home", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                swipe.reset();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Print button
    $(document).on("touchstart click", ".icon-print", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.print();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // E-mail button
    $(document).on("touchstart click", ".icon-email", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.showEmail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });
    $(document).on("touchstart click", ".email-overlay input[type=button]", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.sendEmail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });
    $(document).on("touchstart click", ".email-overlay .close img", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.closeEmail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Switch book
    $(document).on("touchstart click", ".book .delete", function(event){
        event.stopPropagation();
        event.preventDefault();

        var element = $(this);
        if(event.handled !== true) {
            setTimeout(function() {
                var id = $(element).closest("figure").data("index");
                overview.switchBook(id);
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });
});<commit_msg>Some event handler improvements + scrolling on mobile<commit_after>/**
 * @author: Shaun Janssens
 * @copyright: open Summer of code
 */
$(document).ready(function() {

    /**
     * Swipe controller
     * @type {{images: {}, index: number, liked: Array, disliked: Array, init: Function, getImages: Function,
     * getImage: Function, addImage: Function, setIndex: Function, checkLikes: Function, reset: Function, like:
     * Function, dislike: Function, tinder: Function}}
     */
    var swipe = {
        images : {},
        index : 0,
        liked : [],
        disliked : [],
        swipes : 0,
        maxswipes : 5,
        checkBooks : false,

        init : function() {
            swipe.getImages();
        },

        /**
         * Get images
         * Save tags
         * Add 3 images for init
         * Init tinder module
         */
        getImages : function() {
            jQuery.ajax({
                url: "http://api.bieblo.be/API/illustrations",
                type:"GET",
                dataType: "json",
                success: function(data) {
                    swipe.images = swipe.shuffle(data);

                    for(var i = 0; i < 3; i++) {
                        swipe.addImage();
                    }

                    swipe.tinder();
                },
                error : function(xhr, textStatus, errorThrown ) {
                    alert("Error: fout bij ophalen afbeelding. Code: " + xhr.status);
                }
            });
        },

        /**
         * Shuffle array object
         * @param data
         * @returns {*}
         */
        shuffle : function(data){
            for(var j, x, i = data.length; i; j = Math.floor(Math.random() * i), x = data[--i], data[i] = data[j], data[j] = x);
            return data;
        },

        /**
         * Get the next image
         * @returns {null|*}
         */
        getImage : function() {
            if(swipe.index >= swipe.images.length) {
                image = null;
            }
            else {
                image = swipe.images[swipe.index];
                swipe.index = swipe.index + 1;
            }

            return image;
        },

        /**
         * Add an image to the stack
         */
        addImage : function() {
            var data = swipe.getImage();

            if(data != null) {
                var handlebars = Handlebars.templates['tag-template'];
                $(".stack ul").append(handlebars(data));
            }

            swipe.setIndex();
        },

        /**
         * Calculate z-index on stack
         */
        setIndex : function() {
            $(".stack ul").children().each(function(i) {
                $(this).removeClass().addClass("tag_" + (i + 1));
                $(this).css("z-index", -i);
            });
        },

        /**
         * Check likes
         */
        checkSwipes : function() {
            swipe.swipes = swipe.swipes + 1;

            /**
             * Get books after 3 likes or after 5 swipes
             */
            if(parseInt(swipe.liked.length) == 3 && swipe.checkBooks == false) {
                overview.getBooks();
                swipe.checkBooks = true;
            }
            else if(parseInt(swipe.liked.length) < 3 && parseInt(swipe.swipes) == parseInt(swipe.maxswipes) && swipe.checkBooks == false) {
                overview.getBooks();
                swipe.checkBooks = true;
            }

            /**
             * Go to page 2 if all images are swiped
             */
            if(parseInt(swipe.swipes) == parseInt(swipe.images.length)) {
                page.showPage(2);
            }

            /**
             * Go to page 2 if swipe.maxswipes likes
             */
            if(parseInt(swipe.liked.length) == parseInt(swipe.maxswipes)) {
                page.showPage(2);
            }
        },

        /**
         * Reset and reinit
         */
        reset : function() {
            swipe.images = {};
            swipe.index = 0;
            swipe.liked = [];
            swipe.disliked = [];
            swipe.swipes = 0;
            swipe.checkBooks = false;
            $(".stack ul").empty();
            $(".books").empty();
            swipe.init();
            page.showPage(1);
        },

        /**
         * Like tag
         * @param item
         */
        like : function(item) {
            var id = $(item).data("id");
            swipe.liked.push(id);
            swipe.checkSwipes();
            $(item).remove();
            swipe.addImage();
            swipe.tinder();
        },

        /**
         * Dislike tag
         * @param item
         */
        dislike : function(item) {
            var id = $(item).data("id");
            swipe.disliked.push(id);
            swipe.checkSwipes();
            $(item).remove();
            swipe.addImage();
            swipe.tinder();
        },

        /**
         * Animate background on like and dislike
         * @param color
         */
        animateBackground : function(color) {
            if(color == "like") {
                $("body").removeClass().addClass("bg-liked2");

                setTimeout(function () {
                    $("body").removeClass("bg-liked2");
                }, 1000);
            }

            if(color == "dislike") {
                $("body").removeClass().addClass("bg-disliked2");

                setTimeout(function () {
                    $("body").removeClass("bg-disliked2");
                }, 1000);
            }
        },

        /**
         * Tinder plugin
         */
        tinder : function() {
            $(".stack").jTinder({
                onDislike: function (item) {
                    swipe.dislike(item);
                },
                onLike: function (item) {
                    swipe.like(item);
                },
                animationRevertSpeed: 200,
                animationSpeed: 400,
                threshold: 1,
                likeSelector: '#like',
                dislikeSelector: '#dislike'
            });
        }
    };

    /**
     * Overview controller
     * @type {{books: {}, index: number, booksPerPage: number, getBooks: Function, showBooks: Function,
     * showDetail: Function, removeDetail: Function}}
     */
    var overview = {
        books : {},
        index : 0,
        booksPerPage : 8,

        /**
         * Get the recommendations
         * Save all the books
         */
        getBooks : function() {
            var likes = overview.removeComma(swipe.liked.join());
            var dislikes = overview.removeComma(swipe.disliked.join());
            var url = "http://api.bieblo.be/API/recommendations?likes=" + likes + "&dislikes=" + dislikes;

            jQuery.ajax({
                url: url,
                type:"GET",
                dataType: "json",
                success: function(data) {
                    if(data == "unavailable") {
                        alert("Bibnet service niet beschikbaar. Probeer opnieuw.");
                        page.showPage(1);
                    }
                    else {
                        overview.index = overview.booksPerPage;
                        overview.books = data;
                        overview.showBooks(data);
                    }

                },
                error : function(xhr, textStatus, errorThrown ) {
                    console.log("Error: fout bij ophalen boeken. Code: " + xhr.status);
                    if(xhr.status == 404) {
                        alert("Bibnet service niet beschikbaar. Probeer opnieuw.");
                        swipe.reset();
                    }
                }
            });
        },

        /**
         * Remove the last comma of a string
         * @param str
         * @returns {XML|void|string}
         */
        removeComma : function(str) {
            return str.replace(/,(\s+)?$/, '');
        },

        /**
         * Show the overview
         * @param data
         */
        showBooks : function(data) {
            data = data.slice(0, overview.booksPerPage);
            var handlebars = Handlebars.templates['overview-template'];
            $(".books").append(handlebars(data));
        },

        /**
         * Show details popup
         * @param id
         */
        showDetail : function(id) {
            $(".books, header").addClass("blur", 200);
            $(".details").fadeIn(200);
            $(".overlay").fadeIn(200);

            var book = overview.books[id];
            var handlebars = Handlebars.templates['detail-template'];
            $(".overlay").append(handlebars(book));
        },

        /**
         * Remove details popup
         */
        removeDetail : function() {
            $(".books, header").removeClass("blur", 200);
            $(".details").fadeOut(200);
            $(".overlay").fadeOut(200).empty();
        },

        /**
         * Print function
         */
        print : function() {
            window.print()
        },

        /**
         * Show e-mail popup
         */
        showEmail : function() {
            var handlebars = Handlebars.templates['email-template'];
            $(".overview").append(handlebars());
            $(".books, header").addClass("blur", 200);
            $(".overview").fadeIn(200);
        },

        /**
         * Send e-mail with all the books
         */
        sendEmail : function() {
            var email = $("input[type=email]").val();
            var form = $(".email-popup form");

            $.ajax({
                url: "api/email",
                contentType: "application/json",
                type: "POST",
                data: {"email": email, "books": overview.books},
                dataType: 'json',
                success: function(data){
                    form.empty();
                    form.append("
U krijgt zo dadelijk een mail met uw boekenlijst
");
                    setTimeout(function() {
                        overview.closeEmail()
                    }, 5000);
                },
                error: function(){
                    form.empty();
                    form.append("
Er is iets mis gegaan. Gelieve contact op te nemen met de beheerder.
");
                    setTimeout(function() {
                        overview.closeEmail()
                    }, 5000);
                }
            })
        },

        /**
         * Close the e-mail popup
         */
        closeEmail : function() {
            $(".books, header").removeClass("blur", 200);
            $(".email-overlay").fadeOut(function() {
                $(this).remove();
            });
        },

        /**
         * Switch a book
         * @param id
         */
        switchBook : function(id) {
            if(overview.books.length == overview.index) {
                alert("Alle boeken zijn op");
            }
            else {
                overview.index++;

                var book = $("figure[data-index=" + id + "]").parent();

                $("figure[data-index=" + id + "]").parent().empty();

                data = overview.books[overview.index];
                var handlebars = Handlebars.templates["book-template"];
                $(book).append(handlebars(data));

                $(book).children("figure").attr("data-index", id);
            }
        },
    };

    /**
     * Page controller
     * @type {{startpage: number, currentpage: number, init: Function, showPage: Function}}
     */
    var page = {
        startpage : 1,
        currentpage: 1,

        init : function () {
            $("[data-page]").hide();
            page.showPage(page.startpage);

            swipe.init();
        },

        /**
         * Change page
         * @param newpage
         */
        showPage : function (newpage) {
            $("[data-page=" + page.currentpage +"]").fadeOut(300);
            $("[data-page=" + newpage +"]").fadeIn(300);
            page.currentpage = newpage;
        }

    };

    page.init();

    /**
     * Event handler
     */

    // Dislike button
    $(document).on('touchstart click', '#dislike', function(event){
        event.stopPropagation();
        event.preventDefault();
        if(event.handled !== true) {
            $(".tag_1").addClass("rotate-right");
            setTimeout(function() {
                var item = $(".rotate-right");
                swipe.dislike(item);
                swipe.animateBackground("dislike");
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Like button
    $(document).on('touchstart click', '#like', function(event){
        event.stopPropagation();
        event.preventDefault();
        if(event.handled !== true) {
            $(".tag_1").addClass("rotate-left");
            setTimeout(function() {
                var item = $(".rotate-left");
                swipe.like(item);
                swipe.animateBackground("like");
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Show detail overlay
    $(document).on("touchend click", ".book figure", function(event){
        event.stopPropagation();
        event.preventDefault();

        var element = $(this);

        if(event.handled !== true) {
            setTimeout(function() {
                overview.showDetail($(element).data("index"));
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Hide detail overlay
    $(document).on("touchstart click", ".close", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.removeDetail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Keyboard shortcuts
    window.addEventListener('keydown', function(event) {
        switch (event.keyCode) {
            case 37: // Left => dislike
                $(".tag_1").addClass("rotate-right");
                setTimeout(function() {
                    var item = $(".rotate-right");
                    swipe.dislike(item);
                }, 400 );
                break;

            case 39: // Right => like
                $(".tag_1").addClass("rotate-left");
                setTimeout(function() {
                    var item = $(".rotate-left");
                    swipe.like(item);
                }, 400 );
                break;

            case 27: // Esc => close detail
                overview.removeDetail();
                break;
        }
    }, false);

    // Back button
    $(document).on("touchstart click", ".icon-home", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                swipe.reset();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Print button
    $(document).on("touchstart click", ".icon-print", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.print();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // E-mail button
    $(document).on("touchstart click", ".icon-email", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.showEmail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });
    $(document).on("touchstart click", ".email-overlay input[type=button]", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.sendEmail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });
    $(document).on("touchstart click", ".email-overlay .close img", function(event){
        event.stopPropagation();
        event.preventDefault();

        if(event.handled !== true) {
            setTimeout(function() {
                overview.closeEmail();
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });

    // Switch book
    $(document).on("touchstart click", ".book .delete", function(event){
        event.stopPropagation();
        event.preventDefault();

        var element = $(this);
        if(event.handled !== true) {
            setTimeout(function() {
                var id = $(element).closest("figure").data("index");
                overview.switchBook(id);
            }, 400 );
            event.handled = true;
        } else {
            return false;
        }
    });
});<|endoftext|>


<commit_before>var AV = require('leanengine');

AV.Cloud.define('hello', function(req, res){console.log(req);res.success('Hello world in cloud function');})

<commit_msg>add module exports<commit_after>var AV = require('leanengine');

AV.Cloud.define('hello', function(req, res){console.log(req);res.success('Hello world in cloud function');})

module.exports = AV.Cloud;
<|endoftext|>


<commit_before>/* globals describe, it, beforeEach, afterEach */

var assert = require('chai').assert,
    path = require('path'),
    fs = require('fs'),
    mkdirp = require('mkdirp'),
    rimraf = require('rimraf'),
    codeRoot = path.resolve(__dirname, 'sample-code'),
    outputDir = path.resolve(__dirname, 'coverage'),
    configuration = require('../lib/config'),
    cover = require('../lib/run-cover'),
    hijack = require('./hijack-streams'),
    wrap = hijack.wrap,
    unhookFn;

describe('run cover', function () {

    beforeEach(function () {
        unhookFn = null;
        mkdirp.sync(outputDir);
        hijack.silent();
    });
    afterEach(function () {
        hijack.reset();
        rimraf.sync(outputDir);
        if (unhookFn) {
            unhookFn();
        }
    });

    function getConfig(overrides) {
        var cfg = configuration.loadObject({
            verbose: false,
            instrumentation: {
                root: codeRoot
            },
            reporting: {
                dir: outputDir
            }
        }, overrides);
        return cfg;
    }

    it('hooks require and provides coverage', function (cb) {
        cb = wrap(cb);
        var config = getConfig({ verbose: true, instrumentation: { 'include-all-sources': false }});
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                exitFn = data.exitFn,
                coverageMap,
                coverage,
                otherMap;
            unhookFn = data.unhookFn;
            assert.isFunction(fn);
            assert.isFunction(unhookFn);
            assert.isFunction(hookFn);
            assert.isFunction(exitFn);
            hookFn();
            require('./sample-code/foo');
            coverageMap = fn();
            assert.ok(coverageMap);
            coverage = coverageMap[path.resolve(codeRoot, 'foo.js')];
            assert.ok(coverage);
            assert.deepEqual(coverage.s, { 1:1, 2:0, 3:1, 4:1, 5:1 });
            assert.deepEqual(coverage.f, { 1:1, 2: 0 });
            assert.deepEqual(coverage.b, { 1: [1 ,0], 2: [1,0] });
            exitFn();
            assert.ok(fs.existsSync(path.resolve(outputDir, 'coverage.raw.json')));
            assert.ok(fs.existsSync(path.resolve(outputDir, 'lcov.info')));
            assert.ok(fs.existsSync(path.resolve(outputDir, 'lcov-report')));
            otherMap = JSON.parse(fs.readFileSync(path.resolve(outputDir, 'coverage.raw.json')));
            assert.deepEqual(otherMap, coverageMap);
            cb();
        });
    });

    it('hooks runInThisContext and provides coverage', function (cb) {
        cb = wrap(cb);
        var config = getConfig({
            hooks: { 'hook-run-in-context': true },
            instrumentation: { 'include-all-sources': false }
        });
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                coverageMap;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/context');
            coverageMap = fn();
            assert.ok(coverageMap);
            assert.ok(coverageMap[path.resolve(codeRoot, 'context.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'foo.js')]);
            cb();
        });
    });

    it('includes all sources by default (ignoring bad code)', function (cb) {
        cb = wrap(cb);
        var config = getConfig({
            verbose: true,
            instrumentation: {
                'default-excludes': false,
                'include-all-sources': true,
                extensions: [ '.js', '.xjs' ]
            }
        });
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                exitFn = data.exitFn,
                coverageMap;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/foo');
            exitFn();
            coverageMap = fn();
            assert.ok(coverageMap);
            assert.ok(coverageMap[path.resolve(codeRoot, 'context.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'foo.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'node_modules', 'adder.js')]);
            cb();
        });
    });

    it('includes pid in coverage JSON when requested', function (cb) {
        cb = wrap(cb);
        var config = getConfig({ instrumentation: { 'include-pid': true }});
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var hookFn = data.hookFn,
                exitFn = data.exitFn;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/foo');
            exitFn();
            assert.ok(fs.existsSync(path.resolve(outputDir, 'coverage-' + process.pid + '.raw.json')));
            cb();
        });
    });

    it('accepts specific includes', function (cb) {
        cb = wrap(cb);
        var config = getConfig({
            hooks: { 'hook-run-in-context': true },
            instrumentation: { 'include-all-sources': false }
        });
        cover.getCoverFunctions(config, [ '**/foo.js' ], function (err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                exitFn = data.exitFn,
                coverageMap;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/context');
            exitFn();
            coverageMap = fn();
            assert.ok(coverageMap);
            assert.ok(!coverageMap[path.resolve(codeRoot, 'context.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'foo.js')]);
            assert.ok(!coverageMap[path.resolve(codeRoot, 'node_modules', 'adder.js')]);
            cb();
        });
    });

    it('complains but does not throw when no coverage', function (cb) {
        cb = wrap(cb);
        var config = getConfig();
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            unhookFn = data.unhookFn;
            assert.doesNotThrow(data.exitFn);
            cb();
        });
    });

    describe('text reports', function () {
        var getTextReportConfig = function (type) {
            return getConfig({
                reporting: {
                    print: type,
                    'report-config': {
                        text: { file: 'rpt.txt'},
                        'text-summary': { file: 'summary.txt'}
                    }
                }
            });
        };
        it('prints text summary by default', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig();
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
        it('prints detail only', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig('detail');
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
        it('prints both', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig('both');
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
        it('prints nothing', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig('none');
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
    });
});
<commit_msg>chore: fix tests to use 0-indexed keys (#12)<commit_after>/* globals describe, it, beforeEach, afterEach */

var assert = require('chai').assert,
    path = require('path'),
    fs = require('fs'),
    mkdirp = require('mkdirp'),
    rimraf = require('rimraf'),
    codeRoot = path.resolve(__dirname, 'sample-code'),
    outputDir = path.resolve(__dirname, 'coverage'),
    configuration = require('../lib/config'),
    cover = require('../lib/run-cover'),
    hijack = require('./hijack-streams'),
    wrap = hijack.wrap,
    unhookFn;

describe('run cover', function () {

    beforeEach(function () {
        unhookFn = null;
        mkdirp.sync(outputDir);
        hijack.silent();
    });
    afterEach(function () {
        hijack.reset();
        rimraf.sync(outputDir);
        if (unhookFn) {
            unhookFn();
        }
    });

    function getConfig(overrides) {
        var cfg = configuration.loadObject({
            verbose: false,
            instrumentation: {
                root: codeRoot
            },
            reporting: {
                dir: outputDir
            }
        }, overrides);
        return cfg;
    }

    it('hooks require and provides coverage', function (cb) {
        cb = wrap(cb);
        var config = getConfig({ verbose: true, instrumentation: { 'include-all-sources': false }});
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                exitFn = data.exitFn,
                coverageMap,
                coverage,
                otherMap;
            unhookFn = data.unhookFn;
            assert.isFunction(fn);
            assert.isFunction(unhookFn);
            assert.isFunction(hookFn);
            assert.isFunction(exitFn);
            hookFn();
            require('./sample-code/foo');
            coverageMap = fn();
            assert.ok(coverageMap);
            coverage = coverageMap[path.resolve(codeRoot, 'foo.js')];
            assert.ok(coverage);
            assert.deepEqual(coverage.s, { 0:1, 1:0, 2:1, 3:1, 4:1 });
            assert.deepEqual(coverage.f, { 0:1, 1:0 });
            assert.deepEqual(coverage.b, { 0: [1 ,0], 1: [1,0] });
            exitFn();
            assert.ok(fs.existsSync(path.resolve(outputDir, 'coverage.raw.json')));
            assert.ok(fs.existsSync(path.resolve(outputDir, 'lcov.info')));
            assert.ok(fs.existsSync(path.resolve(outputDir, 'lcov-report')));
            otherMap = JSON.parse(fs.readFileSync(path.resolve(outputDir, 'coverage.raw.json')));
            assert.deepEqual(otherMap, coverageMap);
            cb();
        });
    });

    it('hooks runInThisContext and provides coverage', function (cb) {
        cb = wrap(cb);
        var config = getConfig({
            hooks: { 'hook-run-in-context': true },
            instrumentation: { 'include-all-sources': false }
        });
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                coverageMap;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/context');
            coverageMap = fn();
            assert.ok(coverageMap);
            assert.ok(coverageMap[path.resolve(codeRoot, 'context.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'foo.js')]);
            cb();
        });
    });

    it('includes all sources by default (ignoring bad code)', function (cb) {
        cb = wrap(cb);
        var config = getConfig({
            verbose: true,
            instrumentation: {
                'default-excludes': false,
                'include-all-sources': true,
                extensions: [ '.js', '.xjs' ]
            }
        });
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                exitFn = data.exitFn,
                coverageMap;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/foo');
            exitFn();
            coverageMap = fn();
            assert.ok(coverageMap);
            assert.ok(coverageMap[path.resolve(codeRoot, 'context.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'foo.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'node_modules', 'adder.js')]);
            cb();
        });
    });

    it('includes pid in coverage JSON when requested', function (cb) {
        cb = wrap(cb);
        var config = getConfig({ instrumentation: { 'include-pid': true }});
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            var hookFn = data.hookFn,
                exitFn = data.exitFn;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/foo');
            exitFn();
            assert.ok(fs.existsSync(path.resolve(outputDir, 'coverage-' + process.pid + '.raw.json')));
            cb();
        });
    });

    it('accepts specific includes', function (cb) {
        cb = wrap(cb);
        var config = getConfig({
            hooks: { 'hook-run-in-context': true },
            instrumentation: { 'include-all-sources': false }
        });
        cover.getCoverFunctions(config, [ '**/foo.js' ], function (err, data) {
            assert.ok(!err);
            var fn = data.coverageFn,
                hookFn = data.hookFn,
                exitFn = data.exitFn,
                coverageMap;
            unhookFn = data.unhookFn;
            hookFn();
            require('./sample-code/context');
            exitFn();
            coverageMap = fn();
            assert.ok(coverageMap);
            assert.ok(!coverageMap[path.resolve(codeRoot, 'context.js')]);
            assert.ok(coverageMap[path.resolve(codeRoot, 'foo.js')]);
            assert.ok(!coverageMap[path.resolve(codeRoot, 'node_modules', 'adder.js')]);
            cb();
        });
    });

    it('complains but does not throw when no coverage', function (cb) {
        cb = wrap(cb);
        var config = getConfig();
        cover.getCoverFunctions(config, function(err, data) {
            assert.ok(!err);
            unhookFn = data.unhookFn;
            assert.doesNotThrow(data.exitFn);
            cb();
        });
    });

    describe('text reports', function () {
        var getTextReportConfig = function (type) {
            return getConfig({
                reporting: {
                    print: type,
                    'report-config': {
                        text: { file: 'rpt.txt'},
                        'text-summary': { file: 'summary.txt'}
                    }
                }
            });
        };
        it('prints text summary by default', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig();
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
        it('prints detail only', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig('detail');
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
        it('prints both', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig('both');
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
        it('prints nothing', function (cb) {
            cb = wrap(cb);
            var config = getTextReportConfig('none');
            cover.getCoverFunctions(config, function(err, data) {
                assert.ok(!err);
                var hookFn = data.hookFn,
                    exitFn = data.exitFn;
                unhookFn = data.unhookFn;
                hookFn();
                require('./sample-code/foo');
                exitFn();
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'summary.txt')));
                assert.ok(!fs.existsSync(path.resolve(outputDir, 'rpt.txt')));
                cb();
            });
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

// Load environment variables from .env file, where API keys and passwords are configured.
require('dotenv').config();
const configureI18n = require('./config/i18n');
const bluebird = require('bluebird');

process.env.NODE_ENV = process.env.NODE_ENV || 'development';
global.Promise = bluebird;

const { is } = require('ramda');
const express = require('express');
const compression = require('compression');
const bodyParser = require('body-parser');
const logger = require('morgan');
const lusca = require('lusca');
const gstore = require('gstore-node');
const { ValidationError, ValidatorError } = require('gstore-node/lib/error');
const passport = require('passport');
const expressValidator = require('express-validator');
const cors = require('cors');
const multer = require('multer');

require('./config/cloudinary')();
const authentication = require('./config/authentication');
const responseError = require('./utils/responseError');

/**
 * Controllers (route handlers).
 */
const homeController = require('./controllers/home');
const userController = require('./controllers/user');
const beneficiariesController = require('./controllers/beneficiaries');
const projectsController = require('./controllers/projects');
const eventsController = require('./controllers/events');
const coursesController = require('./controllers/courses');

const datastore = require('./config/datastore');

/**
 * Create Express server.
 */
const app = express();

/**
 * Connect to Datastore
 */
gstore.connect(datastore);

/**
 * Express configuration.
 */
configureI18n(app);
if (process.env.NODE_ENV !== 'test') {
  app.use(logger(process.env.NODE_ENV === 'development' ? 'dev' : 'short'));
}
app.use(cors({
  origin: process.env.NODE_ENV === 'development' ? '*' : [process.env.CLIENT_URL, /\.gcriva\.ml$/]
}));
app.use(responseError);
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(passport.initialize());
app.use(lusca.xframe('SAMEORIGIN'));
app.use(lusca.xssProtection(true));

app.use(authentication.authenticate);

/**
 * Primary app routes.
 */
app.get('/', homeController.index);
app.post('/login', userController.postLogin);
app.post('/forgot', userController.postForgot);
app.post('/reset/:token', userController.postReset);
app.post('/signup', authentication.authorizeAdmin, userController.signup);
app.post('/account/password', userController.postUpdatePassword);
app.post('/account/image', multer().single('picture'), userController.updatePicture);
app.post('/users/delete', authentication.authorizeAdmin, userController.delete);
app.get('/beneficiaries', beneficiariesController.index);
app.post('/beneficiaries', beneficiariesController.create);
app.delete('/beneficiaries/:id', beneficiariesController.delete);
app.put('/beneficiaries/:id', beneficiariesController.update);
app.get('/projects', projectsController.index);
app.post('/projects', authentication.authorizeAdmin, projectsController.create);
app.put('/projects/:id', authentication.authorizeAdmin, projectsController.update);
app.delete('/projects/:id', authentication.authorizeAdmin, projectsController.delete);
app.get('/events', eventsController.index);
app.post('/events', eventsController.create);
app.put('/events/:id', eventsController.update);
app.delete('/events/:id', eventsController.delete);
app.get('/courses', coursesController.index);
app.post('/courses', coursesController.create);
app.put('/courses/:id', coursesController.update);
app.delete('/courses/:id', coursesController.delete);

/**
 * OAuth authentication routes. (Sign in)
 */
app.get('/auth/google', passport.authenticate('google', { scope: 'profile email' }));
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), (req, res) => {
  res.redirect(req.session.returnTo || '/');
});

const isValidationError = is(ValidationError);
const isValidatorError = is(ValidatorError);

function handleModelErrors(error, req, res, next) {
  if (isValidationError(error) || isValidatorError(error)) {
    res.error(422, error);
  } else if (error.code === 404) {
    res.error(404, error.message);
  } else if (process.env.NODE_ENV === 'development') {
    // Show the entire error for debugging purposes
    console.error(error);
    res.error(500, error);
  } else {
    next(error);
  }
}
app.use(handleModelErrors);

module.exports = app;
<commit_msg>Add gcriva.netlify.com to accepted origins<commit_after>'use strict';

// Load environment variables from .env file, where API keys and passwords are configured.
require('dotenv').config();
const configureI18n = require('./config/i18n');
const bluebird = require('bluebird');

process.env.NODE_ENV = process.env.NODE_ENV || 'development';
global.Promise = bluebird;

const { is } = require('ramda');
const express = require('express');
const compression = require('compression');
const bodyParser = require('body-parser');
const logger = require('morgan');
const lusca = require('lusca');
const gstore = require('gstore-node');
const { ValidationError, ValidatorError } = require('gstore-node/lib/error');
const passport = require('passport');
const expressValidator = require('express-validator');
const cors = require('cors');
const multer = require('multer');

require('./config/cloudinary')();
const authentication = require('./config/authentication');
const responseError = require('./utils/responseError');

/**
 * Controllers (route handlers).
 */
const homeController = require('./controllers/home');
const userController = require('./controllers/user');
const beneficiariesController = require('./controllers/beneficiaries');
const projectsController = require('./controllers/projects');
const eventsController = require('./controllers/events');
const coursesController = require('./controllers/courses');

const datastore = require('./config/datastore');

/**
 * Create Express server.
 */
const app = express();

/**
 * Connect to Datastore
 */
gstore.connect(datastore);

/**
 * Express configuration.
 */
configureI18n(app);
if (process.env.NODE_ENV !== 'test') {
  app.use(logger(process.env.NODE_ENV === 'development' ? 'dev' : 'short'));
}
app.use(cors({
  origin: process.env.NODE_ENV === 'development'
    ? '*' :
    [process.env.CLIENT_URL, /\.gcriva\.ml$/, /\.gcriva\.netlify\.com$/]
}));
app.use(responseError);
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(passport.initialize());
app.use(lusca.xframe('SAMEORIGIN'));
app.use(lusca.xssProtection(true));

app.use(authentication.authenticate);

/**
 * Primary app routes.
 */
app.get('/', homeController.index);
app.post('/login', userController.postLogin);
app.post('/forgot', userController.postForgot);
app.post('/reset/:token', userController.postReset);
app.post('/signup', authentication.authorizeAdmin, userController.signup);
app.post('/account/password', userController.postUpdatePassword);
app.post('/account/image', multer().single('picture'), userController.updatePicture);
app.post('/users/delete', authentication.authorizeAdmin, userController.delete);
app.get('/beneficiaries', beneficiariesController.index);
app.post('/beneficiaries', beneficiariesController.create);
app.delete('/beneficiaries/:id', beneficiariesController.delete);
app.put('/beneficiaries/:id', beneficiariesController.update);
app.get('/projects', projectsController.index);
app.post('/projects', authentication.authorizeAdmin, projectsController.create);
app.put('/projects/:id', authentication.authorizeAdmin, projectsController.update);
app.delete('/projects/:id', authentication.authorizeAdmin, projectsController.delete);
app.get('/events', eventsController.index);
app.post('/events', eventsController.create);
app.put('/events/:id', eventsController.update);
app.delete('/events/:id', eventsController.delete);
app.get('/courses', coursesController.index);
app.post('/courses', coursesController.create);
app.put('/courses/:id', coursesController.update);
app.delete('/courses/:id', coursesController.delete);

/**
 * OAuth authentication routes. (Sign in)
 */
app.get('/auth/google', passport.authenticate('google', { scope: 'profile email' }));
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), (req, res) => {
  res.redirect(req.session.returnTo || '/');
});

const isValidationError = is(ValidationError);
const isValidatorError = is(ValidatorError);

function handleModelErrors(error, req, res, next) {
  if (isValidationError(error) || isValidatorError(error)) {
    res.error(422, error);
  } else if (error.code === 404) {
    res.error(404, error.message);
  } else if (process.env.NODE_ENV === 'development') {
    // Show the entire error for debugging purposes
    console.error(error);
    res.error(500, error);
  } else {
    next(error);
  }
}
app.use(handleModelErrors);

module.exports = app;
<|endoftext|>