From: Bill Erickson Date: Thu, 12 Dec 2013 18:21:53 +0000 (-0500) Subject: web staff: unit test structure; sample tests X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=150f1dbef3f96cc5358f31cdd73657684c0dfe8b;p=working%2FEvergreen.git web staff: unit test structure; sample tests Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/tests/staffweb/LICENSE.angular-seed b/Open-ILS/tests/staffweb/LICENSE.angular-seed new file mode 100644 index 0000000000..f2d3ff7a20 --- /dev/null +++ b/Open-ILS/tests/staffweb/LICENSE.angular-seed @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +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. + diff --git a/Open-ILS/tests/staffweb/app/js b/Open-ILS/tests/staffweb/app/js new file mode 120000 index 0000000000..7f89b88806 --- /dev/null +++ b/Open-ILS/tests/staffweb/app/js @@ -0,0 +1 @@ +../../../web/js/ui/default/staff \ No newline at end of file diff --git a/Open-ILS/tests/staffweb/config/karma.conf.js b/Open-ILS/tests/staffweb/config/karma.conf.js new file mode 100644 index 0000000000..4c657f3258 --- /dev/null +++ b/Open-ILS/tests/staffweb/config/karma.conf.js @@ -0,0 +1,48 @@ +module.exports = function(config){ + config.set({ + basePath : '../', + //logLevel : config.LOG_DEBUG, + + files : [ + 'app/lib/angular/angular.js', + 'app/lib/angular/angular-*.js', + 'app/lib/angular-ui-bootstrap/angular-bootstrap-min.js', + 'test/lib/angular/angular-mocks.js', + 'app/lib/opensrf/JSON_v1.js', + 'app/lib/opensrf/md5.js', + 'app/lib/opensrf/opensrf.js', + 'app/lib/opensrf/opensrf_xhr.js', + 'app/js/services/core.js', + 'app/js/services/idl.js', + 'app/js/services/event.js', + 'app/js/services/net.js', + 'app/js/services/auth.js', + 'app/js/services/pcrud.js', + 'app/js/services/env.js', + 'app/js/services/org.js', + 'app/js/services/user.js', + 'app/js/services/startup.js', + 'app/js/services/ui.js', + 'app/js/**/*.js', + 'test/unit/**/*.js' + ], + + exclude : [ + 'app/lib/angular/angular-loader.js', + 'app/lib/angular/*.min.js', + 'app/lib/angular/angular-scenario.js' + ], + + autoWatch : true, + + frameworks: ['jasmine'], + + browsers : ['Chrome'], + + plugins : [ + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-jasmine' + ], + +})} diff --git a/Open-ILS/tests/staffweb/scripts/e2e-test.bat b/Open-ILS/tests/staffweb/scripts/e2e-test.bat new file mode 100644 index 0000000000..0b2aee60a3 --- /dev/null +++ b/Open-ILS/tests/staffweb/scripts/e2e-test.bat @@ -0,0 +1,11 @@ +@echo off + +REM Windows script for running e2e tests +REM You have to run server and capture some browser first +REM +REM Requirements: +REM - NodeJS (http://nodejs.org/) +REM - Karma (npm install -g karma) + +set BASE_DIR=%~dp0 +karma start "%BASE_DIR%\..\config\karma-e2e.conf.js" %* diff --git a/Open-ILS/tests/staffweb/scripts/e2e-test.sh b/Open-ILS/tests/staffweb/scripts/e2e-test.sh new file mode 100755 index 0000000000..47fe827592 --- /dev/null +++ b/Open-ILS/tests/staffweb/scripts/e2e-test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +BASE_DIR=`dirname $0` + +echo "" +echo "Starting Karma Server (http://karma-runner.github.io)" +echo $BASE_DIR +echo "-------------------------------------------------------------------" + +$BASE_DIR/../node_modules/karma/bin/karma start $BASE_DIR/../config/karma-e2e.conf.js $* diff --git a/Open-ILS/tests/staffweb/scripts/test.bat b/Open-ILS/tests/staffweb/scripts/test.bat new file mode 100644 index 0000000000..6571f8f2b0 --- /dev/null +++ b/Open-ILS/tests/staffweb/scripts/test.bat @@ -0,0 +1,11 @@ +@echo off + +REM Windows script for running unit tests +REM You have to run server and capture some browser first +REM +REM Requirements: +REM - NodeJS (http://nodejs.org/) +REM - Karma (npm install -g karma) + +set BASE_DIR=%~dp0 +karma start "%BASE_DIR%\..\config\karma.conf.js" %* diff --git a/Open-ILS/tests/staffweb/scripts/test.sh b/Open-ILS/tests/staffweb/scripts/test.sh new file mode 100755 index 0000000000..f6db7624c8 --- /dev/null +++ b/Open-ILS/tests/staffweb/scripts/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +BASE_DIR=`dirname $0` + +echo "" +echo "Starting Karma Server (http://karma-runner.github.io)" +echo "-------------------------------------------------------------------" + +#$BASE_DIR/../node_modules/karma/bin/karma start $BASE_DIR/../config/karma.conf.js $* +karma start $BASE_DIR/../config/karma.conf.js $* diff --git a/Open-ILS/tests/staffweb/scripts/watchr.rb b/Open-ILS/tests/staffweb/scripts/watchr.rb new file mode 100755 index 0000000000..89ef656d27 --- /dev/null +++ b/Open-ILS/tests/staffweb/scripts/watchr.rb @@ -0,0 +1,19 @@ +#!/usr/bin/env watchr + +# config file for watchr http://github.com/mynyml/watchr +# install: gem install watchr +# run: watch watchr.rb +# note: make sure that you have jstd server running (server.sh) and a browser captured + +log_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log') + +`cd ..` +`touch #{log_file}` + +puts "String watchr... log file: #{log_file}" + +watch( '(app/js|test/unit)' ) do + `echo "\n\ntest run started @ \`date\`" > #{log_file}` + `scripts/test.sh &> #{log_file}` +end + diff --git a/Open-ILS/tests/staffweb/scripts/web-server.js b/Open-ILS/tests/staffweb/scripts/web-server.js new file mode 100755 index 0000000000..3f74441e31 --- /dev/null +++ b/Open-ILS/tests/staffweb/scripts/web-server.js @@ -0,0 +1,244 @@ +#!/usr/bin/env node + +var util = require('util'), + http = require('http'), + fs = require('fs'), + url = require('url'), + events = require('events'); + +var DEFAULT_PORT = 8000; + +function main(argv) { + new HttpServer({ + 'GET': createServlet(StaticServlet), + 'HEAD': createServlet(StaticServlet) + }).start(Number(argv[2]) || DEFAULT_PORT); +} + +function escapeHtml(value) { + return value.toString(). + replace('<', '<'). + replace('>', '>'). + replace('"', '"'); +} + +function createServlet(Class) { + var servlet = new Class(); + return servlet.handleRequest.bind(servlet); +} + +/** + * An Http server implementation that uses a map of methods to decide + * action routing. + * + * @param {Object} Map of method => Handler function + */ +function HttpServer(handlers) { + this.handlers = handlers; + this.server = http.createServer(this.handleRequest_.bind(this)); +} + +HttpServer.prototype.start = function(port) { + this.port = port; + this.server.listen(port); + util.puts('Http Server running at http://localhost:' + port + '/'); +}; + +HttpServer.prototype.parseUrl_ = function(urlString) { + var parsed = url.parse(urlString); + parsed.pathname = url.resolve('/', parsed.pathname); + return url.parse(url.format(parsed), true); +}; + +HttpServer.prototype.handleRequest_ = function(req, res) { + var logEntry = req.method + ' ' + req.url; + if (req.headers['user-agent']) { + logEntry += ' ' + req.headers['user-agent']; + } + util.puts(logEntry); + req.url = this.parseUrl_(req.url); + var handler = this.handlers[req.method]; + if (!handler) { + res.writeHead(501); + res.end(); + } else { + handler.call(this, req, res); + } +}; + +/** + * Handles static content. + */ +function StaticServlet() {} + +StaticServlet.MimeMap = { + 'txt': 'text/plain', + 'html': 'text/html', + 'css': 'text/css', + 'xml': 'application/xml', + 'json': 'application/json', + 'js': 'application/javascript', + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'gif': 'image/gif', + 'png': 'image/png', +  'svg': 'image/svg+xml' +}; + +StaticServlet.prototype.handleRequest = function(req, res) { + var self = this; + var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){ + return String.fromCharCode(parseInt(hex, 16)); + }); + var parts = path.split('/'); + if (parts[parts.length-1].charAt(0) === '.') + return self.sendForbidden_(req, res, path); + fs.stat(path, function(err, stat) { + if (err) + return self.sendMissing_(req, res, path); + if (stat.isDirectory()) + return self.sendDirectory_(req, res, path); + return self.sendFile_(req, res, path); + }); +} + +StaticServlet.prototype.sendError_ = function(req, res, error) { + res.writeHead(500, { + 'Content-Type': 'text/html' + }); + res.write('\n'); + res.write('Internal Server Error\n'); + res.write('

Internal Server Error

'); + res.write('
' + escapeHtml(util.inspect(error)) + '
'); + util.puts('500 Internal Server Error'); + util.puts(util.inspect(error)); +}; + +StaticServlet.prototype.sendMissing_ = function(req, res, path) { + path = path.substring(1); + res.writeHead(404, { + 'Content-Type': 'text/html' + }); + res.write('\n'); + res.write('404 Not Found\n'); + res.write('

Not Found

'); + res.write( + '

The requested URL ' + + escapeHtml(path) + + ' was not found on this server.

' + ); + res.end(); + util.puts('404 Not Found: ' + path); +}; + +StaticServlet.prototype.sendForbidden_ = function(req, res, path) { + path = path.substring(1); + res.writeHead(403, { + 'Content-Type': 'text/html' + }); + res.write('\n'); + res.write('403 Forbidden\n'); + res.write('

Forbidden

'); + res.write( + '

You do not have permission to access ' + + escapeHtml(path) + ' on this server.

' + ); + res.end(); + util.puts('403 Forbidden: ' + path); +}; + +StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) { + res.writeHead(301, { + 'Content-Type': 'text/html', + 'Location': redirectUrl + }); + res.write('\n'); + res.write('301 Moved Permanently\n'); + res.write('

Moved Permanently

'); + res.write( + '

The document has moved here.

' + ); + res.end(); + util.puts('301 Moved Permanently: ' + redirectUrl); +}; + +StaticServlet.prototype.sendFile_ = function(req, res, path) { + var self = this; + var file = fs.createReadStream(path); + res.writeHead(200, { + 'Content-Type': StaticServlet. + MimeMap[path.split('.').pop()] || 'text/plain' + }); + if (req.method === 'HEAD') { + res.end(); + } else { + file.on('data', res.write.bind(res)); + file.on('close', function() { + res.end(); + }); + file.on('error', function(error) { + self.sendError_(req, res, error); + }); + } +}; + +StaticServlet.prototype.sendDirectory_ = function(req, res, path) { + var self = this; + if (path.match(/[^\/]$/)) { + req.url.pathname += '/'; + var redirectUrl = url.format(url.parse(url.format(req.url))); + return self.sendRedirect_(req, res, redirectUrl); + } + fs.readdir(path, function(err, files) { + if (err) + return self.sendError_(req, res, error); + + if (!files.length) + return self.writeDirectoryIndex_(req, res, path, []); + + var remaining = files.length; + files.forEach(function(fileName, index) { + fs.stat(path + '/' + fileName, function(err, stat) { + if (err) + return self.sendError_(req, res, err); + if (stat.isDirectory()) { + files[index] = fileName + '/'; + } + if (!(--remaining)) + return self.writeDirectoryIndex_(req, res, path, files); + }); + }); + }); +}; + +StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) { + path = path.substring(1); + res.writeHead(200, { + 'Content-Type': 'text/html' + }); + if (req.method === 'HEAD') { + res.end(); + return; + } + res.write('\n'); + res.write('' + escapeHtml(path) + '\n'); + res.write('\n'); + res.write('

Directory: ' + escapeHtml(path) + '

'); + res.write('
    '); + files.forEach(function(fileName) { + if (fileName.charAt(0) !== '.') { + res.write('
  1. ' + + escapeHtml(fileName) + '
  2. '); + } + }); + res.write('
'); + res.end(); +}; + +// Must be last, +main(process.argv); diff --git a/Open-ILS/tests/staffweb/test/unit/egHomeApp.js b/Open-ILS/tests/staffweb/test/unit/egHomeApp.js new file mode 100644 index 0000000000..31483e6d1b --- /dev/null +++ b/Open-ILS/tests/staffweb/test/unit/egHomeApp.js @@ -0,0 +1,25 @@ +'use strict'; + +describe('egHomeControllers', function(){ + beforeEach(module('egHome')); + + /* ---- LoginCtrl ---------------------------------- */ + + var loginCtrl, loginScope; + beforeEach(inject(function ($rootScope, $controller, $location) { + // pass the workstation name via (mock) URL param + $location.search({ws : 'TestWorkstation'}); + + loginScope = $rootScope.$new(); + loginCtrl = $controller('LoginCtrl', {$scope: loginScope}); + })); + + it('should focus the login controller', inject(function() { + expect(loginScope.focusMe).toBe(true); + })); + + it('should set the login workstation', inject(function() { + expect(loginScope.args.workstation).toEqual('TestWorkstation'); + })); + +}); diff --git a/Open-ILS/tests/staffweb/test/unit/egPatronApp.js b/Open-ILS/tests/staffweb/test/unit/egPatronApp.js new file mode 100644 index 0000000000..df9d829a87 --- /dev/null +++ b/Open-ILS/tests/staffweb/test/unit/egPatronApp.js @@ -0,0 +1,31 @@ +'use strict'; + +describe('egPatronAppTest', function(){ + beforeEach(module('egPatronApp')); + + // basic controller sanity checks + + var patronCtrl, patronScope; + beforeEach(inject(function ($rootScope, $controller, $location) { + patronScope = $rootScope.$new(); + patronCtrl = $controller('PatronCtrl', {$scope: patronScope}); + })); + + /** patronSvc tests **/ + describe('patronSvcTests', function() { + + it('patronSvc should start with empty lists', inject(function(patronSvc) { + expect(patronSvc.patrons.count()).toEqual(0); + })); + + it('patronSvc reset should clear data', inject(function(patronSvc) { + patronSvc.checkout_overrides.a = 1; + expect(Object.keys(patronSvc.checkout_overrides).length).toBe(1); + patronSvc.resetPatronLists(); + expect(Object.keys(patronSvc.checkout_overrides).length).toBe(0); + expect(patronSvc.holds.items.length).toBe(0); + })); + + }); + +}); diff --git a/Open-ILS/tests/staffweb/update-angular.sh b/Open-ILS/tests/staffweb/update-angular.sh new file mode 100755 index 0000000000..dd025895cf --- /dev/null +++ b/Open-ILS/tests/staffweb/update-angular.sh @@ -0,0 +1,34 @@ +#! /bin/sh + +# -------------------------------------- +# modified added by berick / 2013-12-12 +# * create needed dirs +# * udpate angular-ui-bootstrap code + +set -e; + +if [ -z "$1" ]; then + echo "$0 " + exit; +fi; + +mkdir -p tmp +mkdir -p app/lib; +mkdir -p test/lib/angular +mkdir -p test/lib/angular-ui-bootstrap + +curl https://raw.github.com/angular/code.angularjs.org/master/$1/angular-$1.zip -o tmp/angular.zip +rm -fr app/lib/angular +unzip tmp/angular.zip -d app/lib +mv app/lib/angular-$1 app/lib/angular +rm -fr app/lib/angular/docs +mv app/lib/angular/angular-mocks.js test/lib/angular +mv app/lib/angular/angular-scenario.js test/lib/angular +cp app/lib/angular/version.txt test/lib/angular + +if [ -n "$2" ]; then + mkdir -p app/lib/angular-ui-bootstrap/ + curl http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/$2/ui-bootstrap-tpls.min.js \ + -o app/lib/angular-ui-bootstrap/angular-bootstrap-min.js +fi; +