Commit d3de090d authored by Randall Leeds's avatar Randall Leeds

Merge pull request #1972 from hypothesis/browserify

Browserify ALL THE THINGS
parents 3f59a55e 5d842b61
var Klass = window.Annotator.Host; var Annotator = require('annotator');
// Monkeypatch annotator!
require('./scripts/annotator/monkey');
// Cross-frame communication
require('./scripts/annotator/plugin/cross-frame');
require('./scripts/annotation-sync');
require('./scripts/bridge');
require('./scripts/discovery');
// Document plugin
require('./scripts/vendor/annotator.document');
// Bucket bar
require('./scripts/annotator/plugin/bucket-bar');
// Toolbar
require('./scripts/annotator/plugin/toolbar');
// Drawing highlights
require('./scripts/annotator/plugin/texthighlights');
// Creating selections
require('./scripts/annotator/plugin/textselection');
// URL fragments
require('./scripts/annotator/plugin/fragmentselector');
// Anchoring
require('./scripts/vendor/dom_text_mapper');
require('./scripts/annotator/plugin/enhancedanchoring');
require('./scripts/annotator/plugin/domtextmapper');
require('./scripts/annotator/plugin/textposition');
require('./scripts/annotator/plugin/textquote');
require('./scripts/annotator/plugin/textrange');
// PDF
require('./scripts/vendor/page_text_mapper_core');
require('./scripts/annotator/plugin/pdf');
// Fuzzy
require('./scripts/vendor/dom_text_matcher');
require('./scripts/annotator/plugin/fuzzytextanchors');
var Klass = require('./scripts/host');
var docs = 'https://github.com/hypothesis/h/blob/master/README.rst#customized-embedding'; var docs = 'https://github.com/hypothesis/h/blob/master/README.rst#customized-embedding';
var options = { var options = {
app: jQuery('link[type="application/annotator+html"]').attr('href'), app: jQuery('link[type="application/annotator+html"]').attr('href'),
...@@ -23,4 +68,4 @@ if (window.hasOwnProperty('hypothesisConfig')) { ...@@ -23,4 +68,4 @@ if (window.hasOwnProperty('hypothesisConfig')) {
} }
window.annotator = new Klass(document.body, options); window.annotator = new Klass(document.body, options);
window.Annotator.noConflict().$.noConflict(true); Annotator.noConflict().$.noConflict(true);
angular = require('angular')
AUTH_SESSION_ACTIONS = [ AUTH_SESSION_ACTIONS = [
'login' 'login'
'logout' 'logout'
...@@ -124,3 +126,6 @@ angular.module('h') ...@@ -124,3 +126,6 @@ angular.module('h')
.config(configure) .config(configure)
.controller('AuthAppController', AuthAppController) .controller('AuthAppController', AuthAppController)
.controller('AuthPageController', AuthPageController) .controller('AuthPageController', AuthPageController)
require('./account-controller')
require('./auth-controller')
Annotator = require('annotator')
# Save references to Range and Util (because we call Annotator.noConflict() when # Save references to Range and Util (because we call Annotator.noConflict() when
# bootstrapping) # bootstrapping)
Range = Annotator.Range Range = Annotator.Range
......
Annotator = require('annotator')
$ = Annotator.$ $ = Annotator.$
class Annotator.Plugin.BucketBar extends Annotator.Plugin class Annotator.Plugin.BucketBar extends Annotator.Plugin
...@@ -338,3 +340,5 @@ class Annotator.Plugin.BucketBar extends Annotator.Plugin ...@@ -338,3 +340,5 @@ class Annotator.Plugin.BucketBar extends Annotator.Plugin
isUpper: (i) -> i == 1 isUpper: (i) -> i == 1
isLower: (i) -> i == @index.length - 2 isLower: (i) -> i == @index.length - 2
exports.BucketBar = Annotator.Plugin.BucketBar
Annotator = require('annotator')
$ = Annotator.$ $ = Annotator.$
# Extracts individual keys from an object and returns a new one. # Extracts individual keys from an object and returns a new one.
...@@ -45,3 +47,5 @@ CrossFrame = class Annotator.Plugin.CrossFrame extends Annotator.Plugin ...@@ -45,3 +47,5 @@ CrossFrame = class Annotator.Plugin.CrossFrame extends Annotator.Plugin
this.onConnect = (fn) -> this.onConnect = (fn) ->
bridge.onConnect(fn) bridge.onConnect(fn)
exports.CrossFrame = CrossFrame
Annotator = @Annotator Annotator = require('annotator')
$ = Annotator.$ $ = Annotator.$
# Fake two-phase / pagination support, used for HTML documents # Fake two-phase / pagination support, used for HTML documents
...@@ -293,3 +293,5 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin ...@@ -293,3 +293,5 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
selectors selectors
exports.Anchor = Anchor
exports.EnhancedAnchoring = Annotator.Plugin.EnhancedAnchoring
require('../../vendor/jquery.scrollintoview')
$ = Annotator.$ $ = Annotator.$
# Public: Wraps the DOM Nodes within the provided range with a highlight # Public: Wraps the DOM Nodes within the provided range with a highlight
...@@ -125,3 +127,5 @@ class Annotator.Plugin.TextHighlights extends Annotator.Plugin ...@@ -125,3 +127,5 @@ class Annotator.Plugin.TextHighlights extends Annotator.Plugin
pluginInit: -> pluginInit: ->
# Export the text highlight class for other plugins # Export the text highlight class for other plugins
Annotator.TextHighlight = TextHighlight Annotator.TextHighlight = TextHighlight
exports.TextHighlight = TextHighlight
angular = require('angular')
uuid = require('./vendor/uuid')
# These services are provided in their own angular modules and thus must be
# loaded first.
require('./identity-service')
require('./streamer-service')
imports = [ imports = [
'ngAnimate' 'ngAnimate'
'ngRoute' 'ngRoute'
...@@ -92,3 +100,38 @@ module = angular.module('h', imports) ...@@ -92,3 +100,38 @@ module = angular.module('h', imports)
unless mocha? # Crude method of detecting test environment. unless mocha? # Crude method of detecting test environment.
module.run(setupCrossFrame) module.run(setupCrossFrame)
module.run(setupStreamer) module.run(setupStreamer)
require('./vendor/annotator.auth.js')
require('./annotator/monkey')
require('./controllers')
require('./directives')
require('./directives/annotation')
require('./directives/deep-count')
require('./directives/markdown')
require('./directives/privacy')
require('./directives/simple-search')
require('./directives/status-button')
require('./directives/thread-filter')
require('./directives/thread')
require('./filters')
require('./searchfilters')
require('./services')
require('./annotation-mapper-service')
require('./annotation-ui-service')
require('./auth-service')
require('./cross-frame-service')
require('./flash-service')
require('./permissions-service')
require('./store-service')
require('./threading-service')
require('./streamsearch')
require('./annotation-sync')
require('./annotation-ui-sync')
require('./bridge')
require('./discovery')
$ = require('jquery')
Channel = require('./vendor/jschannel')
class Bridge class Bridge
options: options:
# Scope identifier to distinguish this channel from any others # Scope identifier to distinguish this channel from any others
......
...@@ -22,13 +22,13 @@ class AppController ...@@ -22,13 +22,13 @@ class AppController
this.$inject = [ this.$inject = [
'$controller', '$document', '$location', '$route', '$scope', '$window', '$controller', '$document', '$location', '$route', '$scope', '$window',
'auth', 'drafts', 'identity', 'auth', 'drafts', 'identity',
'permissions', 'streamer', 'streamfilter', 'annotationUI', 'permissions', 'streamer', 'annotationUI',
'annotationMapper', 'threading' 'annotationMapper', 'threading'
] ]
constructor: ( constructor: (
$controller, $document, $location, $route, $scope, $window, $controller, $document, $location, $route, $scope, $window,
auth, drafts, identity, auth, drafts, identity,
permissions, streamer, streamfilter, annotationUI, permissions, streamer, annotationUI,
annotationMapper, threading annotationMapper, threading
) -> ) ->
$controller(AnnotationUIController, {$scope}) $controller(AnnotationUIController, {$scope})
...@@ -176,11 +176,11 @@ class AnnotationViewerController ...@@ -176,11 +176,11 @@ class AnnotationViewerController
class ViewerController class ViewerController
this.$inject = [ this.$inject = [
'$scope', '$route', 'annotationUI', 'crossframe', 'annotationMapper', '$scope', '$route', 'annotationUI', 'crossframe', 'annotationMapper',
'auth', 'flash', 'streamer', 'streamfilter', 'store' 'auth', 'streamer', 'streamfilter', 'store'
] ]
constructor: ( constructor: (
$scope, $route, annotationUI, crossframe, annotationMapper, $scope, $route, annotationUI, crossframe, annotationMapper,
auth, flash, streamer, streamfilter, store auth, streamer, streamfilter, store
) -> ) ->
# Tells the view that these annotations are embedded into the owner doc # Tells the view that these annotations are embedded into the owner doc
$scope.isEmbedded = true $scope.isEmbedded = true
......
angular = require('angular')
Markdown = require('./vendor/Markdown.Converter')
class Converter extends Markdown.Converter class Converter extends Markdown.Converter
constructor: -> constructor: ->
super super
......
Annotator = @Annotator $ = require('jquery')
$ = Annotator.$ Annotator = require('annotator')
Channel = require('./vendor/jschannel')
class Annotator.Guest extends Annotator module.exports = class Annotator.Guest extends Annotator
SHOW_HIGHLIGHTS_CLASS = 'annotator-highlights-always-on' SHOW_HIGHLIGHTS_CLASS = 'annotator-highlights-always-on'
# Events to be bound on Annotator#element. # Events to be bound on Annotator#element.
......
angular = require('angular')
angular.module('h.helpers', ['bootstrap']) angular.module('h.helpers', ['bootstrap'])
require('./form-helpers')
require('./string-helpers')
require('./time-helpers')
require('./ui-helpers')
require('./xsrf-service')
angular = require('angular')
unorm = require('../vendor/unorm')
# Shared helper methods for working with strings/unicode strings # Shared helper methods for working with strings/unicode strings
# For unicode normalization we use the unorm library # For unicode normalization we use the unorm library
createStringHelpers = -> createStringHelpers = ->
......
Annotator = @Annotator $ = require('jquery')
$ = Annotator.$ Annotator = require('annotator')
Guest = require('./guest')
class Annotator.Host extends Annotator.Guest module.exports = class Annotator.Host extends Annotator.Guest
# Drag state variables # Drag state variables
drag: drag:
delta: 0 delta: 0
......
angular = require('angular')
angular.module('h.session', ['ngResource', 'h.helpers']) angular.module('h.session', ['ngResource', 'h.helpers'])
require('./session-service')
angular = require('angular')
mail = require('./vendor/jwz')
class ThreadingService class ThreadingService
# Mix in message thread properties into the prototype. The body of the # Mix in message thread properties into the prototype. The body of the
# class will overwrite any methods applied here. If you need inheritance # class will overwrite any methods applied here. If you need inheritance
......
...@@ -10,52 +10,43 @@ module.exports = function(config) { ...@@ -10,52 +10,43 @@ module.exports = function(config) {
// frameworks to use // frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'], frameworks: [
'browserify',
'mocha'
],
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
'h/static/scripts/vendor/polyfills/bind.js', // Application external deps
'h/static/scripts/vendor/polyfills/url.js',
'h/static/scripts/vendor/polyfills/promise.js',
'h/static/scripts/vendor/jquery.js', 'h/static/scripts/vendor/jquery.js',
'h/static/scripts/vendor/jschannel.js',
'h/static/scripts/vendor/jwz.js',
'h/static/scripts/vendor/moment-with-langs.js',
'h/static/scripts/vendor/jstz.js',
'h/static/scripts/vendor/moment-timezone.js',
'h/static/scripts/vendor/moment-timezone-data.js',
'h/static/scripts/vendor/Markdown.Converter.js',
'h/static/scripts/vendor/unorm.js',
'h/static/scripts/vendor/uuid.js',
'h/static/scripts/vendor/annotator.js',
'h/static/scripts/annotator/monkey.js',
'h/static/scripts/vendor/annotator.auth.js',
'h/static/scripts/annotator/plugin/bridge.js',
'h/static/scripts/annotator/plugin/bucket-bar.js',
'h/static/scripts/vendor/dom_text_mapper.js',
'h/static/scripts/annotator/annotator.anchoring.js',
// Angular needs to be included after annotator to avoid the
// CrossFrame dependencies in Bridge picking up the angular object.
'h/static/scripts/vendor/angular.js', 'h/static/scripts/vendor/angular.js',
'h/static/scripts/vendor/angular-mocks.js',
'h/static/scripts/vendor/angular-animate.js', 'h/static/scripts/vendor/angular-animate.js',
'h/static/scripts/vendor/angular-bootstrap.js', 'h/static/scripts/vendor/angular-bootstrap.js',
'h/static/scripts/vendor/angular-resource.js', 'h/static/scripts/vendor/angular-resource.js',
'h/static/scripts/vendor/angular-route.js', 'h/static/scripts/vendor/angular-route.js',
'h/static/scripts/vendor/angular-sanitize.js', 'h/static/scripts/vendor/angular-sanitize.js',
'h/static/scripts/vendor/ng-tags-input.js', 'h/static/scripts/vendor/ng-tags-input.js',
'h/static/scripts/annotator/plugin/texthighlights.js', 'h/static/scripts/vendor/annotator.js',
'h/static/scripts/app.js', 'h/static/scripts/vendor/polyfills/autofill-event.js',
'h/static/scripts/account.js', 'h/static/scripts/vendor/polyfills/bind.js',
'h/static/scripts/helpers.js', 'h/static/scripts/vendor/katex/katex.js',
'h/static/scripts/session.js', 'h/static/scripts/vendor/moment-with-langs.js',
'h/static/scripts/hypothesis.js', 'h/static/scripts/vendor/jstz.js',
'h/static/scripts/vendor/moment-timezone.js',
'h/static/scripts/vendor/moment-timezone-data.js',
'h/static/scripts/vendor/polyfills/url.js',
// Test deps
'h/static/scripts/vendor/angular-mocks.js',
'h/static/scripts/vendor/polyfills/promise.js',
'h/static/scripts/vendor/sinon.js', 'h/static/scripts/vendor/sinon.js',
'h/static/scripts/vendor/chai.js', 'h/static/scripts/vendor/chai.js',
'h/templates/client/*.html', 'h/templates/client/*.html',
'tests/js/bootstrap.coffee', 'tests/js/bootstrap.coffee',
'tests/js/**/*-test.coffee'
// Tests
'tests/js/**/*-test.coffee',
], ],
...@@ -72,10 +63,14 @@ module.exports = function(config) { ...@@ -72,10 +63,14 @@ module.exports = function(config) {
// preprocess matching files before serving them to the browser // preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: { preprocessors: {
'**/*.coffee': ['coffee'], '**/*.coffee': ['browserify'],
'h/templates/client/*.html': ['ng-html2js'], 'h/templates/client/*.html': ['ng-html2js'],
}, },
browserify: {
debug: true,
extensions: ['.coffee']
},
// test results reporter to use // test results reporter to use
// possible values: 'dots', 'progress' // possible values: 'dots', 'progress'
...@@ -97,13 +92,13 @@ module.exports = function(config) { ...@@ -97,13 +92,13 @@ module.exports = function(config) {
// enable / disable watching file and executing tests whenever any file changes // enable / disable watching file and executing tests whenever any file changes
autoWatch: false, autoWatch: true,
// start these browsers // start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'], browsers: ['PhantomJS'],
browserNoActivityTimeout: 20000, // Travis is slow...
// Continuous Integration mode // Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits // if true, Karma captures browsers, runs the tests and exits
......
...@@ -4,14 +4,17 @@ ...@@ -4,14 +4,17 @@
"version": "0.0.0", "version": "0.0.0",
"description": "The Internet, peer reviewed.", "description": "The Internet, peer reviewed.",
"dependencies": { "dependencies": {
"coffee-script": "1.7.1", "browserify": "^9.0.3",
"browserify-shim": "^3.8.3",
"clean-css": "2.2.2", "clean-css": "2.2.2",
"coffee-script": "1.7.1",
"coffeeify": "^1.0.0",
"uglify-js": "2.4.14" "uglify-js": "2.4.14"
}, },
"devDependencies": { "devDependencies": {
"karma": "^0.12.17", "karma": "^0.12.17",
"karma-browserify": "^3.0.3",
"karma-cli": "0.0.4", "karma-cli": "0.0.4",
"karma-coffee-preprocessor": "^0.2.1",
"karma-mocha": "^0.1.4", "karma-mocha": "^0.1.4",
"karma-ng-html2js-preprocessor": "^0.1.0", "karma-ng-html2js-preprocessor": "^0.1.0",
"karma-phantomjs-launcher": "^0.1.4", "karma-phantomjs-launcher": "^0.1.4",
...@@ -32,5 +35,29 @@ ...@@ -32,5 +35,29 @@
"bugs": { "bugs": {
"url": "https://github.com/hypothesis/h/issues" "url": "https://github.com/hypothesis/h/issues"
}, },
"homepage": "https://github.com/hypothesis/h" "homepage": "https://github.com/hypothesis/h",
"browserify": {
"transform": ["coffeeify", "browserify-shim"]
},
"browser": {
"jquery": "./h/static/scripts/vendor/jquery.js",
"annotator": "./h/static/scripts/vendor/annotator.js",
"angular": "./h/static/scripts/vendor/angular.js",
"angular-mock": "./h/static/scripts/vendor/angular-mocks.js"
},
"browserify-shim": {
"jquery": "global:jQuery",
"annotator": "global:Annotator",
"angular": "global:angular",
"angular-mock": "global:angular.mock",
"./h/static/scripts/vendor/jschannel.js": "Channel",
"./h/static/scripts/vendor/page_text_mapper_core.js": "PageTextMapperCore",
"./h/static/scripts/vendor/dom_text_matcher.js": {
"exports": "DomTextMatcher",
"depends": [
"./h/static/scripts/vendor/diff_match_patch_uncompressed.js",
"./h/static/scripts/vendor/text_match_engines.js"
]
}
}
} }
{inject, module} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
describe 'AccountController', ->
describe 'h:AccountController', ->
$scope = null $scope = null
fakeFlash = null fakeFlash = null
fakeSession = null fakeSession = null
...@@ -13,10 +15,16 @@ describe 'AccountController', -> ...@@ -13,10 +15,16 @@ describe 'AccountController', ->
disableUserPromise = null disableUserPromise = null
profilePromise = null profilePromise = null
createController = null createController = null
sandbox = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/account/account-controller')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide, $filterProvider) -> beforeEach module ($provide, $filterProvider) ->
sandbox = sinon.sandbox.create()
fakeSession = {} fakeSession = {}
fakeFlash = sandbox.spy() fakeFlash = sandbox.spy()
fakeIdentity = fakeIdentity =
...@@ -49,6 +57,9 @@ describe 'AccountController', -> ...@@ -49,6 +57,9 @@ describe 'AccountController', ->
createController = -> createController = ->
$controller('AccountController', {$scope: $scope}) $controller('AccountController', {$scope: $scope})
afterEach ->
sandbox.restore()
describe '.submit', -> describe '.submit', ->
createFakeForm = (overrides={}) -> createFakeForm = (overrides={}) ->
defaults = defaults =
......
{inject, module} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
...@@ -19,12 +21,16 @@ class MockSession ...@@ -19,12 +21,16 @@ class MockSession
mockFlash = sandbox.spy() mockFlash = sandbox.spy()
mockFormHelpers = applyValidationErrors: sandbox.spy() mockFormHelpers = applyValidationErrors: sandbox.spy()
describe 'AuthController', -> describe 'h:AuthController', ->
$scope = null $scope = null
$timeout = null $timeout = null
auth = null auth = null
session = null session = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/account/auth-controller')
beforeEach module('h') beforeEach module('h')
beforeEach module('h.templates') beforeEach module('h.templates')
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'AnnotationMapperService', -> describe 'AnnotationMapperService', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
...@@ -9,6 +12,10 @@ describe 'AnnotationMapperService', -> ...@@ -9,6 +12,10 @@ describe 'AnnotationMapperService', ->
fakeThreading = null fakeThreading = null
annotationMapper = null annotationMapper = null
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-mapper-service')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide) -> beforeEach module ($provide) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'AnnotationSync', -> describe 'AnnotationSync', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
publish = null publish = null
...@@ -10,6 +13,10 @@ describe 'AnnotationSync', -> ...@@ -10,6 +13,10 @@ describe 'AnnotationSync', ->
options = null options = null
PARENT_WINDOW = 'PARENT_WINDOW' PARENT_WINDOW = 'PARENT_WINDOW'
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-sync')
beforeEach module('h') beforeEach module('h')
beforeEach inject (AnnotationSync, $rootScope) -> beforeEach inject (AnnotationSync, $rootScope) ->
listeners = {} listeners = {}
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'AnnotationUI', -> describe 'AnnotationUI', ->
annotationUI = null annotationUI = null
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-ui-service')
beforeEach module('h') beforeEach module('h')
beforeEach inject (_annotationUI_) -> beforeEach inject (_annotationUI_) ->
annotationUI = _annotationUI_ annotationUI = _annotationUI_
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'AnnotationUISync', -> describe 'AnnotationUISync', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
$digest = null $digest = null
...@@ -13,6 +16,10 @@ describe 'AnnotationUISync', -> ...@@ -13,6 +16,10 @@ describe 'AnnotationUISync', ->
createChannel = -> {notify: sandbox.stub()} createChannel = -> {notify: sandbox.stub()}
PARENT_WINDOW = 'PARENT_WINDOW' PARENT_WINDOW = 'PARENT_WINDOW'
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-ui-sync')
beforeEach module('h') beforeEach module('h')
beforeEach inject (AnnotationUISync, $rootScope) -> beforeEach inject (AnnotationUISync, $rootScope) ->
$digest = sandbox.stub($rootScope, '$digest') $digest = sandbox.stub($rootScope, '$digest')
......
bb = require('../../../../h/static/scripts/annotator/plugin/bucket-bar')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'Annotator.BucketBar', -> describe 'Annotator.BucketBar', ->
createBucketBar = (options) -> createBucketBar = (options) ->
element = document.createElement('div') element = document.createElement('div')
new Annotator.Plugin.BucketBar(element, options || {}) new bb.BucketBar(element, options || {})
# Yes this is testing a private method. Yes this is bad practice, but I'd # Yes this is testing a private method. Yes this is bad practice, but I'd
# rather test this functionality in a private method than not test it at all. # rather test this functionality in a private method than not test it at all.
......
cf = require('../../../../h/static/scripts/annotator/plugin/cross-frame')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'Annotator.Plugin.CrossFrame', -> describe 'Annotator.Plugin.CrossFrame', ->
CrossFrame = null
fakeDiscovery = null fakeDiscovery = null
fakeBridge = null fakeBridge = null
fakeAnnotationSync = null fakeAnnotationSync = null
...@@ -13,7 +15,7 @@ describe 'Annotator.Plugin.CrossFrame', -> ...@@ -13,7 +15,7 @@ describe 'Annotator.Plugin.CrossFrame', ->
on: sandbox.stub() on: sandbox.stub()
emit: sandbox.stub() emit: sandbox.stub()
element = document.createElement('div') element = document.createElement('div')
return new Annotator.Plugin.CrossFrame(element, $.extend({}, defaults, options)) return new cf.CrossFrame(element, $.extend({}, defaults, options))
beforeEach -> beforeEach ->
fakeDiscovery = fakeDiscovery =
...@@ -29,10 +31,9 @@ describe 'Annotator.Plugin.CrossFrame', -> ...@@ -29,10 +31,9 @@ describe 'Annotator.Plugin.CrossFrame', ->
fakeAnnotationSync = fakeAnnotationSync =
sync: sandbox.stub() sync: sandbox.stub()
CrossFrame = Annotator.Plugin.CrossFrame cf.CrossFrame.AnnotationSync = sandbox.stub().returns(fakeAnnotationSync)
sandbox.stub(CrossFrame, 'AnnotationSync').returns(fakeAnnotationSync) cf.CrossFrame.Discovery = sandbox.stub().returns(fakeDiscovery)
sandbox.stub(CrossFrame, 'Discovery').returns(fakeDiscovery) cf.CrossFrame.Bridge = sandbox.stub().returns(fakeBridge)
sandbox.stub(CrossFrame, 'Bridge').returns(fakeBridge)
afterEach -> afterEach ->
sandbox.restore() sandbox.restore()
...@@ -40,33 +41,28 @@ describe 'Annotator.Plugin.CrossFrame', -> ...@@ -40,33 +41,28 @@ describe 'Annotator.Plugin.CrossFrame', ->
describe 'constructor', -> describe 'constructor', ->
it 'instantiates the Discovery component', -> it 'instantiates the Discovery component', ->
createCrossFrame() createCrossFrame()
assert.called(CrossFrame.Discovery) assert.calledWith(cf.CrossFrame.Discovery, window)
assert.calledWith(CrossFrame.Discovery, window)
it 'passes the options along to the bridge', -> it 'passes the options along to the bridge', ->
createCrossFrame(server: true) createCrossFrame(server: true)
assert.called(CrossFrame.Discovery) assert.calledWith(cf.CrossFrame.Discovery, window, server: true)
assert.calledWith(CrossFrame.Discovery, window, server: true)
it 'instantiates the CrossFrame component', -> it 'instantiates the CrossFrame component', ->
createCrossFrame() createCrossFrame()
assert.called(CrossFrame.Bridge) assert.calledWith(cf.CrossFrame.Discovery)
assert.calledWith(CrossFrame.Discovery)
it 'passes the options along to the bridge', -> it 'passes the options along to the bridge', ->
createCrossFrame(scope: 'myscope') createCrossFrame(scope: 'myscope')
assert.called(CrossFrame.Bridge) assert.calledWith(cf.CrossFrame.Bridge, scope: 'myscope')
assert.calledWith(CrossFrame.Bridge, scope: 'myscope')
it 'instantiates the AnnotationSync component', -> it 'instantiates the AnnotationSync component', ->
createCrossFrame() createCrossFrame()
assert.called(CrossFrame.AnnotationSync) assert.called(cf.CrossFrame.AnnotationSync)
it 'passes along options to AnnotationSync', -> it 'passes along options to AnnotationSync', ->
formatter = (x) -> x formatter = (x) -> x
createCrossFrame(formatter: formatter) createCrossFrame(formatter: formatter)
assert.called(CrossFrame.AnnotationSync) assert.calledWith(cf.CrossFrame.AnnotationSync, fakeBridge, {
assert.calledWith(CrossFrame.AnnotationSync, fakeBridge, {
on: sinon.match.func on: sinon.match.func
emit: sinon.match.func emit: sinon.match.func
formatter: formatter formatter: formatter
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'h', -> describe 'h', ->
fakeAnnotator = null fakeAnnotator = null
fakeIdentity = null fakeIdentity = null
sandbox = null sandbox = null
before ->
angular.module('h', [])
require('../../h/static/scripts/auth-service')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide) -> beforeEach module ($provide) ->
......
{module, inject} = require('angular-mock')
Channel = require('../../h/static/scripts/vendor/jschannel.js')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'Bridge', -> describe 'Bridge', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
createBridge = null createBridge = null
createChannel = null createChannel = null
before ->
angular.module('h', [])
require('../../h/static/scripts/bridge')
beforeEach module('h') beforeEach module('h')
beforeEach inject (Bridge) -> beforeEach inject (Bridge) ->
createBridge = (options) -> createBridge = (options) ->
......
This diff is collapsed.
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'CrossFrameService', -> describe 'CrossFrameService', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
crossframe = null crossframe = null
...@@ -14,6 +17,10 @@ describe 'CrossFrameService', -> ...@@ -14,6 +17,10 @@ describe 'CrossFrameService', ->
fakeAnnotationSync = null fakeAnnotationSync = null
fakeAnnotationUISync = null fakeAnnotationUISync = null
before ->
angular.module('h', [])
require('../../h/static/scripts/cross-frame-service')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide) -> beforeEach module ($provide) ->
$fakeDocument = {} $fakeDocument = {}
......
assert = chai.assert {module, inject} = require('angular-mock')
describe 'h.directives', ->
$scope = null
$compile = null
$injector = null
fakeWindow = null
beforeEach module ($provide, $filterProvider) ->
fakeWindow = {open: sinon.spy()}
fakeDocument = angular.element({
createElement: (tag) -> document.createElement(tag)
baseURI: 'http://example.com'
})
$provide.value('$window', fakeWindow) assert = chai.assert
$provide.value('$document', fakeDocument)
$filterProvider.register 'persona', ->
(user, part) ->
parts = user.slice(5).split('@')
{username: parts[0], provider: parts[1]}[part]
return describe 'h:directives', ->
before ->
angular.module('h', [])
require('../../h/static/scripts/directives')
beforeEach module('h') beforeEach module('h')
beforeEach inject (_$compile_, _$rootScope_, _$injector_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
$injector = _$injector_
describe '.formValidate', ->
$element = null
beforeEach ->
$scope.model = {username: undefined}
template = '''
<form form-validate name="login" onsubmit="return false">
<div class="form-field">
<input type="text" class="form-input" name="username"
ng-model="model.username" name="username"
required ng-minlength="3" />
</div>
</form>
'''
$element = $compile(angular.element(template))($scope)
$scope.$digest()
it 'should remove an error class to an valid field on change', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]').addClass('form-field-error')
$input.controller('ngModel').$setViewValue('abc')
$scope.$digest()
assert.notInclude($field.prop('className'), 'form-field-error')
assert.notInclude($input.prop('className'), 'form-field-error')
it 'should apply an error class to an invalid field on submit', ->
$field = $element.find('.form-field')
$element.triggerHandler('submit')
assert.include($field.prop('className'), 'form-field-error')
it 'should remove an error class from a valid field on submit', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]')
$input.val('abc').triggerHandler('input')
$element.triggerHandler('submit')
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should apply an error class if the form recieves errors after a submit action', ->
$element.trigger('submit')
$element.controller('form').username.$setValidity('response', false)
$field = $element.find('.form-field')
assert.include $field.prop('className'), 'form-field-error'
it 'should remove an error class on valid input when the view model changes', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]')
$input.val('abc').triggerHandler('input')
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should not add an error class on invalid input on when the view changes', ->
$field = $element.find('.form-field')
$input = $element.find('[name=username]')
$input.val('ab').triggerHandler('input')
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should reset the "response" error when the view changes', ->
$field = $element.find('.form-field')
$input = $element.find('[name=username]')
controller = $input.controller('ngModel')
controller.$setViewValue('abc')
# Submit Event
$element.triggerHandler('submit')
controller.$setValidity('response', false)
controller.responseErrorMessage = 'fail'
$scope.$digest()
assert.include($field.prop('className'), 'form-field-error', 'Fail fast check')
controller.$setViewValue('abc')
$scope.$digest()
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should hide errors if the model is marked as pristine', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]')
controller = $input.controller('ngModel')
# Submit Event
$element.triggerHandler('submit')
controller.$setValidity('response', false)
controller.responseErrorMessage = 'fail'
$scope.$digest()
assert.include($field.prop('className'), 'form-field-error', 'Fail fast check')
# Then clear it out and mark it as pristine
controller.$setPristine()
$scope.$digest()
assert.notInclude($field.prop('className'), 'form-field-error')
describe '.match', -> describe '.match', ->
$compile = null
$element = null $element = null
$isolateScope = null $isolateScope = null
$scope = null
beforeEach inject (_$compile_, _$rootScope_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
beforeEach -> beforeEach ->
$scope.model = {a: 1, b: 1} $scope.model = {a: 1, b: 1}
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sandbox = sinon.sandbox.create()
describe 'h.directives.annotation', -> describe 'h.directives.annotation', ->
$compile = null $compile = null
...@@ -8,17 +10,28 @@ describe 'h.directives.annotation', -> ...@@ -8,17 +10,28 @@ describe 'h.directives.annotation', ->
$timeout = null $timeout = null
annotation = null annotation = null
createController = null createController = null
flash = null
fakeAuth = null
fakeStore = null
fakeUser = null
fakeAnnotationMapper = null fakeAnnotationMapper = null
fakeAnnotationUI = null fakeAnnotationUI = null
fakeAuth = null
fakeDrafts = null
fakeFlash = null
fakeMomentFilter = null
fakePermissions = null
fakePersonaFilter = null
fakeStore = null
fakeTimeHelpers = null
fakeUrlEncodeFilter = null
sandbox = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/annotation')
beforeEach module('h') beforeEach module('h')
beforeEach module('h.templates') beforeEach module('h.templates')
beforeEach module ($provide) -> beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeAuth = fakeAuth =
user: 'acct:bill@localhost' user: 'acct:bill@localhost'
fakeAnnotationMapper = fakeAnnotationMapper =
...@@ -30,11 +43,37 @@ describe 'h.directives.annotation', -> ...@@ -30,11 +43,37 @@ describe 'h.directives.annotation', ->
admin: ['acct:bill@localhost'] admin: ['acct:bill@localhost']
deleteAnnotation: sandbox.stub() deleteAnnotation: sandbox.stub()
fakeAnnotationUI = {} fakeAnnotationUI = {}
fakeDrafts = {
add: sandbox.stub()
remove: sandbox.stub()
}
fakeFlash = sandbox.stub()
fakeMomentFilter = sandbox.stub().returns('ages ago')
fakePermissions = {
isPublic: sandbox.stub().returns(true)
isPrivate: sandbox.stub().returns(false)
permits: sandbox.stub().returns(true)
public: sandbox.stub().returns({read: ['everybody']})
private: sandbox.stub().returns({read: ['justme']})
}
fakePersonaFilter = sandbox.stub().returnsArg(0)
fakeTimeHelpers = {
toFuzzyString: sandbox.stub().returns('a while ago')
nextFuzzyUpdate: sandbox.stub().returns(30)
}
fakeUrlEncodeFilter = (v) -> encodeURIComponent(v)
$provide.value 'auth', fakeAuth
$provide.value 'store', fakeStore
$provide.value 'annotationMapper', fakeAnnotationMapper $provide.value 'annotationMapper', fakeAnnotationMapper
$provide.value 'annotationUI', fakeAnnotationUI $provide.value 'annotationUI', fakeAnnotationUI
$provide.value 'auth', fakeAuth
$provide.value 'drafts', fakeDrafts
$provide.value 'flash', fakeFlash
$provide.value 'momentFilter', fakeMomentFilter
$provide.value 'permissions', fakePermissions
$provide.value 'personaFilter', fakePersonaFilter
$provide.value 'store', fakeStore
$provide.value 'timeHelpers', fakeTimeHelpers
$provide.value 'urlencodeFilter', fakeUrlEncodeFilter
return return
beforeEach inject (_$compile_, $controller, _$document_, $rootScope, _$timeout_) -> beforeEach inject (_$compile_, $controller, _$document_, $rootScope, _$timeout_) ->
...@@ -50,12 +89,10 @@ describe 'h.directives.annotation', -> ...@@ -50,12 +89,10 @@ describe 'h.directives.annotation', ->
target: [{}] target: [{}]
uri: 'http://example.com' uri: 'http://example.com'
user: 'acct:bill@localhost' user: 'acct:bill@localhost'
flash = sinon.spy()
createController = -> createController = ->
$controller 'AnnotationController', $controller 'AnnotationController',
$scope: $scope $scope: $scope
flash: flash
afterEach -> afterEach ->
sandbox.restore() sandbox.restore()
...@@ -82,7 +119,7 @@ describe 'h.directives.annotation', -> ...@@ -82,7 +119,7 @@ describe 'h.directives.annotation', ->
delete annotation.id delete annotation.id
controller = createController() controller = createController()
$scope.$digest() $scope.$digest()
assert controller.isPrivate() assert.deepEqual annotation.permissions, {read: ['justme']}
describe '#reply', -> describe '#reply', ->
controller = null controller = null
...@@ -102,26 +139,19 @@ describe 'h.directives.annotation', -> ...@@ -102,26 +139,19 @@ describe 'h.directives.annotation', ->
match = sinon.match {references: [annotation.id], uri: annotation.uri} match = sinon.match {references: [annotation.id], uri: annotation.uri}
assert.calledWith(fakeAnnotationMapper.createAnnotation, match) assert.calledWith(fakeAnnotationMapper.createAnnotation, match)
it 'adds the world readable principal if the parent is public', -> it 'makes the annotation public if the parent is public', ->
reply = {} reply = {}
fakeAnnotationMapper.createAnnotation.returns(reply) fakeAnnotationMapper.createAnnotation.returns(reply)
annotation.permissions.read.push('group:__world__') fakePermissions.isPublic.returns(true)
controller.reply() controller.reply()
assert.include(reply.permissions.read, 'group:__world__') assert.deepEqual(reply.permissions, {read: ['everybody']})
it 'does not add the world readable principal if the parent is private', -> it 'does not add the world readable principal if the parent is private', ->
reply = {} reply = {}
fakeAnnotationMapper.createAnnotation.returns(reply) fakeAnnotationMapper.createAnnotation.returns(reply)
fakePermissions.isPublic.returns(false)
controller.reply() controller.reply()
assert.notInclude(reply.permissions.read, 'group:__world__') assert.deepEqual(reply.permissions, {read: ['justme']})
it 'fills the other permissions too', ->
reply = {}
fakeAnnotationMapper.createAnnotation.returns(reply)
controller.reply()
assert.equal(reply.permissions.update[0], 'acct:bill@localhost')
assert.equal(reply.permissions.delete[0], 'acct:bill@localhost')
assert.equal(reply.permissions.admin[0], 'acct:bill@localhost')
describe '#render', -> describe '#render', ->
controller = null controller = null
...@@ -297,18 +327,15 @@ describe 'h.directives.annotation', -> ...@@ -297,18 +327,15 @@ describe 'h.directives.annotation', ->
it 'is updated on first digest', -> it 'is updated on first digest', ->
$scope.$digest() $scope.$digest()
assert.isNotNull(controller.timestamp) assert.equal(controller.timestamp, 'a while ago')
it 'is updated after a timeout', -> it 'is updated after a timeout', ->
fakeTimeHelpers.nextFuzzyUpdate.returns(10)
$scope.$digest() $scope.$digest()
timestamp = controller.timestamp clock.tick(11000)
clock.tick(30000) fakeTimeHelpers.toFuzzyString.returns('ages ago')
$timeout.flush()
assert.notEqual(timestamp, controller.timestamp)
timestamp = controller.timestamp
clock.tick(30000)
$timeout.flush() $timeout.flush()
assert.notEqual(timestamp, controller.timestamp) assert.equal(controller.timestamp, 'ages ago')
it 'is no longer updated after the scope is destroyed', -> it 'is no longer updated after the scope is destroyed', ->
$scope.$digest() $scope.$digest()
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
VISIBILITY_KEY ='hypothesis.visibility' VISIBILITY_KEY ='hypothesis.visibility'
...@@ -5,104 +7,87 @@ VISIBILITY_PUBLIC = 'public' ...@@ -5,104 +7,87 @@ VISIBILITY_PUBLIC = 'public'
VISIBILITY_PRIVATE = 'private' VISIBILITY_PRIVATE = 'private'
describe 'h.directives.privacy', -> describe 'h.directives.privacy', ->
$window = null
$scope = null
$compile = null $compile = null
$injector = null $scope = null
$element = null $window = null
$isolateScope = null fakeAuth = null
fakePermissions = null
sandbox = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/privacy')
beforeEach module('h') beforeEach module('h')
beforeEach module('h.templates') beforeEach module('h.templates')
describe 'memory fallback', -> beforeEach module ($provide) ->
fakeAuth = null sandbox = sinon.sandbox.create()
sandbox = null
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeAuth = {
user: 'acct:angry.joe@texas.com'
}
$provide.value 'auth', fakeAuth
return
afterEach ->
sandbox.restore()
describe 'has memory fallback', -> fakeAuth = {
$window = null user: 'acct:angry.joe@texas.com'
$scope2 = null }
beforeEach inject (_$compile_, _$rootScope_, _$window_) -> fakePermissions = {
$compile = _$compile_ isPublic: sandbox.stub().returns(true)
$scope = _$rootScope_.$new() isPrivate: sandbox.stub().returns(false)
$scope2 = _$rootScope_.$new() permits: sandbox.stub().returns(true)
$window = _$window_ public: sandbox.stub().returns({read: ['everybody']})
private: sandbox.stub().returns({read: ['justme']})
}
$window.localStorage = null $provide.value 'auth', fakeAuth
$provide.value 'permissions', fakePermissions
return
it 'stores the default visibility level when it changes', -> beforeEach inject (_$compile_, _$rootScope_, _$window_) ->
$scope.permissions = {read: ['acct:user@example.com']} $compile = _$compile_
$element = $compile('<privacy ng-model="permissions">')($scope) $scope = _$rootScope_.$new()
$scope.$digest() $window = _$window_
$isolateScope = $element.isolateScope()
$isolateScope.setLevel(name: VISIBILITY_PUBLIC)
$scope2.permissions = {read: []} afterEach ->
$element = $compile('<privacy ng-model="permissions">')($scope2) sandbox.restore()
$scope2.$digest()
# Roundabout way: the storage works because the directive describe 'memory fallback', ->
# could read out the privacy level $scope2 = null
readPermissions = $scope2.permissions.read[0]
assert.equal readPermissions, 'group:__world__'
describe 'has localStorage', ->
sandbox = null
fakeAuth = null
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeAuth = { beforeEach inject (_$rootScope_) ->
user: 'acct:angry.joe@texas.com' $scope2 = _$rootScope_.$new()
}
$provide.value 'auth', fakeAuth $window.localStorage = null
return
afterEach -> it 'stores the default visibility level when it changes', ->
sandbox.restore() $scope.permissions = {read: ['acct:user@example.com']}
$element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest()
$isolateScope = $element.isolateScope()
$isolateScope.setLevel(name: VISIBILITY_PUBLIC)
beforeEach inject (_$compile_, _$rootScope_, _$injector_, _$window_) -> $scope2.permissions = {read: []}
$compile = _$compile_ $element = $compile('<privacy ng-model="permissions">')($scope2)
$scope = _$rootScope_.$new() $scope2.$digest()
$injector = _$injector_
$window = _$window_
describe 'storage', -> # Roundabout way: the storage works because the directive
store = null # could read out the privacy level
readPermissions = $scope2.permissions.read[0]
assert.equal readPermissions, 'everybody'
beforeEach -> describe 'has localStorage', ->
store = $window.localStorage
it 'stores the default visibility level when it changes', -> it 'stores the default visibility level when it changes', ->
$scope.permissions = {read: ['acct:user@example.com']} $scope.permissions = {read: ['acct:user@example.com']}
$element = $compile('<privacy ng-model="permissions">')($scope) $element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest() $scope.$digest()
$isolateScope = $element.isolateScope() $isolateScope = $element.isolateScope()
$isolateScope.setLevel(name: VISIBILITY_PUBLIC) $isolateScope.setLevel(name: VISIBILITY_PUBLIC)
expected = VISIBILITY_PUBLIC expected = VISIBILITY_PUBLIC
stored = store.getItem VISIBILITY_KEY stored = $window.localStorage.getItem VISIBILITY_KEY
assert.equal stored, expected assert.equal stored, expected
describe 'setting permissions', -> describe 'setting permissions', ->
$element = null
store = null store = null
modelCtrl = null
beforeEach -> beforeEach ->
store = $window.localStorage store = $window.localStorage
...@@ -125,17 +110,15 @@ describe 'h.directives.privacy', -> ...@@ -125,17 +110,15 @@ describe 'h.directives.privacy', ->
$scope.permissions = {read: []} $scope.permissions = {read: []}
$element = $compile('<privacy ng-model="permissions">')($scope) $element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest() $scope.$digest()
$isolateScope = $element.isolateScope()
it 'sets the initial permissions based on the stored privacy level', -> it 'sets the initial permissions based on the stored privacy level', ->
assert.equal $isolateScope.level.name, VISIBILITY_PUBLIC assert.equal $element.isolateScope().level.name, VISIBILITY_PUBLIC
it 'does not alter the level on subsequent renderings', -> it 'does not alter the level on subsequent renderings', ->
modelCtrl = $element.controller('ngModel')
store.setItem VISIBILITY_KEY, VISIBILITY_PRIVATE store.setItem VISIBILITY_KEY, VISIBILITY_PRIVATE
$scope.permissions.read = ['acct:user@example.com'] $scope.permissions.read = ['acct:user@example.com']
$scope.$digest() $scope.$digest()
assert.equal $isolateScope.level.name, VISIBILITY_PUBLIC assert.equal $element.isolateScope().level.name, VISIBILITY_PUBLIC
describe 'when permissions.read is filled', -> describe 'when permissions.read is filled', ->
it 'does not alter the level', -> it 'does not alter the level', ->
...@@ -156,25 +139,11 @@ describe 'h.directives.privacy', -> ...@@ -156,25 +139,11 @@ describe 'h.directives.privacy', ->
$element = $compile('<privacy ng-model="permissions">')($scope) $element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest() $scope.$digest()
readPermissions = $scope.permissions.read[0] assert.deepEqual $scope.permissions, fakePermissions.private()
updatePermissions = $scope.permissions.update[0]
deletePermissions = $scope.permissions.delete[0]
adminPermissions = $scope.permissions.admin[0]
assert.equal readPermissions, fakeAuth.user
assert.equal updatePermissions, fakeAuth.user
assert.equal deletePermissions, fakeAuth.user
assert.equal adminPermissions, fakeAuth.user
it 'puts group_world into the read permissions for public visibility', -> it 'puts group_world into the read permissions for public visibility', ->
store.setItem VISIBILITY_KEY, VISIBILITY_PUBLIC store.setItem VISIBILITY_KEY, VISIBILITY_PUBLIC
$element = $compile('<privacy ng-model="permissions">')($scope) $element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest() $scope.$digest()
readPermissions = $scope.permissions.read[0] assert.deepEqual $scope.permissions, fakePermissions.public()
updatePermissions = $scope.permissions.update[0]
deletePermissions = $scope.permissions.delete[0]
adminPermissions = $scope.permissions.admin[0]
assert.equal readPermissions, 'group:__world__'
assert.equal updatePermissions, fakeAuth.user
assert.equal deletePermissions, fakeAuth.user
assert.equal adminPermissions, fakeAuth.user
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
describe 'h.directives', ->
$scope = null describe 'h:directives.simple-search', ->
$compile = null $compile = null
$element = null
$scope = null
fakeWindow = null fakeWindow = null
isolate = null isolate = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/simple-search')
beforeEach module('h') beforeEach module('h')
beforeEach inject (_$compile_, _$rootScope_) -> beforeEach inject (_$compile_, _$rootScope_) ->
$compile = _$compile_ $compile = _$compile_
$scope = _$rootScope_.$new() $scope = _$rootScope_.$new()
describe '.simpleSearch', -> $scope.update = sinon.spy()
$element = null $scope.clear = sinon.spy()
beforeEach ->
$scope.update = sinon.spy() template= '''
$scope.clear = sinon.spy() <div class="simpleSearch"
query="query"
template= ''' on-search="update(query)"
<div class="simpleSearch" on-clear="clear()">
query="query" </div>
on-search="update(query)" '''
on-clear="clear()">
</div> $element = $compile(angular.element(template))($scope)
''' $scope.$digest()
isolate = $element.isolateScope()
$element = $compile(angular.element(template))($scope)
$scope.$digest() it 'updates the search-bar', ->
isolate = $element.isolateScope() $scope.query = "Test query"
$scope.$digest()
it 'updates the search-bar', -> assert.equal(isolate.searchtext, $scope.query)
$scope.query = "Test query"
$scope.$digest() it 'calls the given search function', ->
assert.equal(isolate.searchtext, $scope.query) isolate.searchtext = "Test query"
isolate.$digest()
it 'calls the given search function', -> $element.find('form').triggerHandler('submit')
isolate.searchtext = "Test query" sinon.assert.calledWith($scope.update, "Test query")
isolate.$digest()
$element.find('form').triggerHandler('submit') it 'calls the given clear function', ->
sinon.assert.calledWith($scope.update, "Test query") $element.find('.simple-search-clear').click()
assert($scope.clear.called)
it 'calls the given clear function', ->
$element.find('.simple-search-clear').click() it 'clears the search-bar', ->
assert($scope.clear.called) isolate.query = ''
isolate.$digest()
it 'clears the search-bar', -> isolate.searchtext = "Test query"
isolate.query = '' isolate.$digest()
isolate.$digest() $element.find('.simple-search-clear').click()
isolate.searchtext = "Test query" assert.equal(isolate.searchtext, '')
isolate.$digest()
$element.find('.simple-search-clear').click() it 'invokes callbacks when the input model changes', ->
assert.equal(isolate.searchtext, '') $scope.query = "Test query"
$scope.$digest()
it 'invokes callbacks when the input model changes', -> sinon.assert.calledOnce($scope.update)
$scope.query = "Test query" $scope.query = ""
$scope.$digest() $scope.$digest()
sinon.assert.calledOnce($scope.update) sinon.assert.calledOnce($scope.clear)
$scope.query = ""
$scope.$digest() it 'adds a class to the form when there is no input value', ->
sinon.assert.calledOnce($scope.clear) $form = $element.find('.simple-search-form')
assert.include($form.prop('className'), 'simple-search-inactive')
it 'adds a class to the form when there is no input value', ->
$form = $element.find('.simple-search-form') it 'removes the class from the form when there is an input value', ->
assert.include($form.prop('className'), 'simple-search-inactive') $scope.query = "Test query"
$scope.$digest()
it 'removes the class from the form when there is an input value', ->
$scope.query = "Test query" $form = $element.find('.simple-search-form')
$scope.$digest() assert.notInclude($form.prop('className'), 'simple-search-inactive')
$form = $element.find('.simple-search-form')
assert.notInclude($form.prop('className'), 'simple-search-inactive')
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
describe 'h.directives.statusButton', ->
describe 'h:directives.status-button', ->
$scope = null $scope = null
$compile = null $compile = null
$element = null $element = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/status-button')
beforeEach module('h') beforeEach module('h')
beforeEach inject (_$compile_, _$rootScope_) -> beforeEach inject (_$compile_, _$rootScope_) ->
......
This diff is collapsed.
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'Discovery', -> describe 'Discovery', ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
fakeTopWindow = null fakeTopWindow = null
fakeFrameWindow = null fakeFrameWindow = null
createDiscovery = null createDiscovery = null
before ->
angular.module('h', [])
require('../../h/static/scripts/discovery')
beforeEach module('h') beforeEach module('h')
beforeEach inject (Discovery) -> beforeEach inject (Discovery) ->
createDiscovery = (win, options) -> createDiscovery = (win, options) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'persona', -> describe 'h:filters', ->
filter = null
term = 'acct:hacker@example.com' before ->
angular.module('h', [])
require('../../h/static/scripts/filters')
describe 'persona', ->
filter = null
term = 'acct:hacker@example.com'
beforeEach module('h') beforeEach module('h')
beforeEach inject ($filter) -> beforeEach inject ($filter) ->
filter = $filter('persona') filter = $filter('persona')
it 'should return the whole term by request', -> it 'should return the whole term by request', ->
result = filter('acct:hacker@example.com', 'term') result = filter('acct:hacker@example.com', 'term')
assert.equal result, 'acct:hacker@example.com' assert.equal result, 'acct:hacker@example.com'
it 'should return the requested part', -> it 'should return the requested part', ->
assert.equal filter(term), 'hacker' assert.equal filter(term), 'hacker'
assert.equal filter(term, 'term'), term, assert.equal filter(term, 'term'), term,
assert.equal filter(term, 'username'), 'hacker' assert.equal filter(term, 'username'), 'hacker'
assert.equal filter(term, 'provider'), 'example.com' assert.equal filter(term, 'provider'), 'example.com'
it 'should pass through unrecognized terms as username or term', -> it 'should pass through unrecognized terms as username or term', ->
assert.equal filter('bogus'), 'bogus' assert.equal filter('bogus'), 'bogus'
assert.equal filter('bogus', 'username'), 'bogus' assert.equal filter('bogus', 'username'), 'bogus'
it 'should handle error cases', -> it 'should handle error cases', ->
assert.notOk filter() assert.notOk filter()
assert.notOk filter('bogus', 'provider') assert.notOk filter('bogus', 'provider')
describe 'urlencode', -> describe 'urlencode', ->
filter = null filter = null
beforeEach module('h') beforeEach module('h')
beforeEach inject ($filter) -> beforeEach inject ($filter) ->
filter = $filter('urlencode') filter = $filter('urlencode')
it 'encodes reserved characters in the term', -> it 'encodes reserved characters in the term', ->
assert.equal(filter('#hello world'), '%23hello%20world') assert.equal(filter('#hello world'), '%23hello%20world')
Annotator = require('annotator')
Guest = require('../../h/static/scripts/guest')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'Annotator.Guest', -> describe 'Annotator.Guest', ->
sandbox = sinon.sandbox.create() sandbox = null
fakeCrossFrame = null fakeCrossFrame = null
createGuest = (options) -> createGuest = (options) ->
element = document.createElement('div') element = document.createElement('div')
return new Annotator.Guest(element, options || {}) return new Guest(element, options || {})
# Silence Annotator's sassy backchat
beforeEach -> sandbox.stub(console, 'log')
afterEach -> sandbox.restore()
beforeEach -> beforeEach ->
sandbox = sinon.sandbox.create()
fakeCrossFrame = fakeCrossFrame =
onConnect: sandbox.stub() onConnect: sandbox.stub()
on: sandbox.stub() on: sandbox.stub()
sandbox.stub(Annotator.Plugin, 'CrossFrame').returns(fakeCrossFrame) # Mock out the anchoring plugin. Oh how I wish I didn't have to do crazy
# shit like this.
Annotator.Plugin.EnhancedAnchoring = -> {
pluginInit: ->
@annotator.anchoring = this
_scan: sandbox.stub()
getHighlights: sandbox.stub().returns([])
getAnchors: sandbox.stub().returns([])
}
Annotator.Plugin.CrossFrame = -> fakeCrossFrame
sandbox.spy(Annotator.Plugin, 'CrossFrame')
afterEach ->
sandbox.restore()
describe 'setting up the bridge', -> describe 'setting up the bridge', ->
it 'sets the scope for the cross frame bridge', -> it 'sets the scope for the cross frame bridge', ->
...@@ -177,7 +196,7 @@ describe 'Annotator.Guest', -> ...@@ -177,7 +196,7 @@ describe 'Annotator.Guest', ->
{annotation: {$$tag: 'tag1'}, setFocused: sandbox.stub()} {annotation: {$$tag: 'tag1'}, setFocused: sandbox.stub()}
{annotation: {$$tag: 'tag2'}, setFocused: sandbox.stub()} {annotation: {$$tag: 'tag2'}, setFocused: sandbox.stub()}
] ]
sandbox.stub(guest.anchoring, 'getHighlights').returns(highlights) guest.anchoring.getHighlights.returns(highlights)
emitGuestEvent('focusAnnotations', 'ctx', ['tag1']) emitGuestEvent('focusAnnotations', 'ctx', ['tag1'])
assert.called(highlights[0].setFocused) assert.called(highlights[0].setFocused)
assert.calledWith(highlights[0].setFocused, true) assert.calledWith(highlights[0].setFocused, true)
...@@ -188,7 +207,7 @@ describe 'Annotator.Guest', -> ...@@ -188,7 +207,7 @@ describe 'Annotator.Guest', ->
{annotation: {$$tag: 'tag1'}, setFocused: sandbox.stub()} {annotation: {$$tag: 'tag1'}, setFocused: sandbox.stub()}
{annotation: {$$tag: 'tag2'}, setFocused: sandbox.stub()} {annotation: {$$tag: 'tag2'}, setFocused: sandbox.stub()}
] ]
sandbox.stub(guest.anchoring, 'getHighlights').returns(highlights) guest.anchoring.getHighlights.returns(highlights)
emitGuestEvent('focusAnnotations', 'ctx', ['tag1']) emitGuestEvent('focusAnnotations', 'ctx', ['tag1'])
assert.called(highlights[1].setFocused) assert.called(highlights[1].setFocused)
assert.calledWith(highlights[1].setFocused, false) assert.calledWith(highlights[1].setFocused, false)
...@@ -199,7 +218,7 @@ describe 'Annotator.Guest', -> ...@@ -199,7 +218,7 @@ describe 'Annotator.Guest', ->
anchors = [ anchors = [
{annotation: {$$tag: 'tag1'}, scrollToView: sandbox.stub()} {annotation: {$$tag: 'tag1'}, scrollToView: sandbox.stub()}
] ]
sandbox.stub(guest.anchoring, 'getAnchors').returns(anchors) guest.anchoring.getAnchors.returns(anchors)
emitGuestEvent('scrollToAnnotation', 'ctx', 'tag1') emitGuestEvent('scrollToAnnotation', 'ctx', 'tag1')
assert.called(anchors[0].scrollToView) assert.called(anchors[0].scrollToView)
......
{module, inject} = require('angular-mock')
assert = chai.assert
angular = require('angular')
describe 'h.helpers:form-helpers', ->
$compile = null
$scope = null
formHelpers = null
before ->
angular.module('h.helpers', [])
require('../../../h/static/scripts/helpers/form-helpers')
beforeEach module('h.helpers')
beforeEach inject (_$compile_, _$rootScope_, _formHelpers_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
formHelpers = _formHelpers_
describe '.formValidate', ->
$element = null
beforeEach ->
$scope.model = {username: undefined}
template = '''
<form form-validate name="login" onsubmit="return false">
<div class="form-field">
<input type="text" class="form-input" name="username"
ng-model="model.username" name="username"
required ng-minlength="3" />
</div>
</form>
'''
$element = $compile(angular.element(template))($scope)
$scope.$digest()
it 'should remove an error class to an valid field on change', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]').addClass('form-field-error')
$input.controller('ngModel').$setViewValue('abc')
$scope.$digest()
assert.notInclude($field.prop('className'), 'form-field-error')
assert.notInclude($input.prop('className'), 'form-field-error')
it 'should apply an error class to an invalid field on submit', ->
$field = $element.find('.form-field')
$element.triggerHandler('submit')
assert.include($field.prop('className'), 'form-field-error')
it 'should remove an error class from a valid field on submit', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]')
$input.val('abc').triggerHandler('input')
$element.triggerHandler('submit')
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should apply an error class if the form recieves errors after a submit action', ->
$element.trigger('submit')
$element.controller('form').username.$setValidity('response', false)
$field = $element.find('.form-field')
assert.include $field.prop('className'), 'form-field-error'
it 'should remove an error class on valid input when the view model changes', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]')
$input.val('abc').triggerHandler('input')
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should not add an error class on invalid input on when the view changes', ->
$field = $element.find('.form-field')
$input = $element.find('[name=username]')
$input.val('ab').triggerHandler('input')
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should reset the "response" error when the view changes', ->
$field = $element.find('.form-field')
$input = $element.find('[name=username]')
controller = $input.controller('ngModel')
controller.$setViewValue('abc')
# Submit Event
$element.triggerHandler('submit')
controller.$setValidity('response', false)
controller.responseErrorMessage = 'fail'
$scope.$digest()
assert.include($field.prop('className'), 'form-field-error', 'Fail fast check')
controller.$setViewValue('abc')
$scope.$digest()
assert.notInclude($field.prop('className'), 'form-field-error')
it 'should hide errors if the model is marked as pristine', ->
$field = $element.find('.form-field').addClass('form-field-error')
$input = $element.find('[name=username]')
controller = $input.controller('ngModel')
# Submit Event
$element.triggerHandler('submit')
controller.$setValidity('response', false)
controller.responseErrorMessage = 'fail'
$scope.$digest()
assert.include($field.prop('className'), 'form-field-error', 'Fail fast check')
# Then clear it out and mark it as pristine
controller.$setPristine()
$scope.$digest()
assert.notInclude($field.prop('className'), 'form-field-error')
describe '.applyValidationErrors', ->
form = null
beforeEach ->
form =
$setValidity: sinon.spy()
username: {$setValidity: sinon.spy()}
password: {$setValidity: sinon.spy()}
it 'sets the "response" error key for each field with errors', ->
formHelpers.applyValidationErrors form,
username: 'must be at least 3 characters'
password: 'must be present'
assert.calledWith(form.username.$setValidity, 'response', false)
assert.calledWith(form.password.$setValidity, 'response', false)
it 'adds an error message to each input controller', ->
formHelpers.applyValidationErrors form,
username: 'must be at least 3 characters'
password: 'must be present'
assert.equal(form.username.responseErrorMessage, 'must be at least 3 characters')
assert.equal(form.password.responseErrorMessage, 'must be present')
it 'sets the "response" error key if the form has a failure reason', ->
formHelpers.applyValidationErrors form, null, 'fail'
assert.calledWith(form.$setValidity, 'response', false)
it 'adds an reason message as the response error', ->
formHelpers.applyValidationErrors form, null, 'fail'
assert.equal(form.responseErrorMessage, 'fail')
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'h.helpers.stringHelpers', ->
describe 'h.helpers:string-helpers', ->
stringHelpers = null stringHelpers = null
before ->
angular.module('h.helpers', [])
require('../../../h/static/scripts/helpers/string-helpers')
beforeEach module('h.helpers') beforeEach module('h.helpers')
beforeEach inject (_stringHelpers_) -> beforeEach inject (_stringHelpers_) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
minute = 60 minute = 60
...@@ -36,11 +38,16 @@ FIXTURES_NEXT_FUZZY_UPDATE = [ ...@@ -36,11 +38,16 @@ FIXTURES_NEXT_FUZZY_UPDATE = [
[8 * year, 24 * day] # by setTimout [8 * year, 24 * day] # by setTimout
] ]
describe 'timeHelpers', -> describe 'h.helpers:time-helpers', ->
beforeEach module('h.helpers')
timeHelpers = null timeHelpers = null
sandbox = null sandbox = null
before ->
angular.module('h.helpers', [])
require('../../../h/static/scripts/helpers/time-helpers')
beforeEach module('h.helpers')
beforeEach inject (_timeHelpers_) -> beforeEach inject (_timeHelpers_) ->
timeHelpers = _timeHelpers_ timeHelpers = _timeHelpers_
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
......
Annotator = require('annotator')
Host = require('../../h/static/scripts/host')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
...@@ -7,7 +10,7 @@ describe 'Annotator.Host', -> ...@@ -7,7 +10,7 @@ describe 'Annotator.Host', ->
createHost = (options={}) -> createHost = (options={}) ->
element = document.createElement('div') element = document.createElement('div')
return new Annotator.Host(element, options) return new Host(element, options)
beforeEach -> beforeEach ->
# Disable Annotator's ridiculous logging. # Disable Annotator's ridiculous logging.
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
describe 'identity', ->
describe 'h.identity', ->
provider = null provider = null
mockInjectable = {} mockInjectable = {}
before ->
require('../../h/static/scripts/identity-service')
beforeEach module('h.identity') beforeEach module('h.identity')
beforeEach module ($provide, identityProvider) -> beforeEach module ($provide, identityProvider) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'h', ->
describe 'h:permissions', ->
sandbox = null sandbox = null
fakeAuth = null fakeAuth = null
before ->
angular.module('h', [])
require('../../h/static/scripts/permissions-service')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide) -> beforeEach module ($provide) ->
......
Annotator = require('annotator')
ea = require('../../../h/static/scripts/annotator/plugin/enhancedanchoring')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
# In order to be able to create highlights,
# the Annotator.TextHighlight class must exist.
# This class is registered then the TextHighlights plugin
# is initialized, so we will do that.
th = new Annotator.Plugin.TextHighlights()
th.pluginInit()
# Then Anchor class is not supposed to be used directly. # Then Anchor class is not supposed to be used directly.
# Every concrete implementation should have it's own class, # Every concrete implementation should have it's own class,
# encompassing a way to identify the given segment of the document. # encompassing a way to identify the given segment of the document.
# #
# For testing, we will use the TestAnchor class, # For testing, we will use the TestAnchor class,
# which does not actually identify a real segment of the HTML document. # which does not actually identify a real segment of the HTML document.
class TestAnchor extends Annotator.Anchor class TestAnchor extends ea.Anchor
_getSegment: -> "html segment for " + @id _getSegment: -> "html segment for " + @id
...@@ -24,6 +20,7 @@ class TestAnchor extends Annotator.Anchor ...@@ -24,6 +20,7 @@ class TestAnchor extends Annotator.Anchor
@id = "fake anchor for " + target.id @id = "fake anchor for " + target.id
describe 'Annotator.Plugin.EnhancedAnchoring', -> describe 'Annotator.Plugin.EnhancedAnchoring', ->
sandbox = null sandbox = null
pendingTest = null pendingTest = null
...@@ -33,13 +30,15 @@ describe 'Annotator.Plugin.EnhancedAnchoring', -> ...@@ -33,13 +30,15 @@ describe 'Annotator.Plugin.EnhancedAnchoring', ->
beforeEach -> beforeEach ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
sandbox.stub Annotator.TextHighlight, 'createFrom',
(segment, anchor, page) -> Annotator.TextHighlight = {
createFrom: (segment, anchor, page) ->
segment: segment segment: segment
anchor: anchor anchor: anchor
page: page page: page
removeFromDocument: sinon.spy() removeFromDocument: sinon.spy()
scrollToView: sinon.spy -> pendingTest?.resolve() scrollToView: sinon.spy -> pendingTest?.resolve()
}
afterEach -> afterEach ->
sandbox.restore() sandbox.restore()
...@@ -59,7 +58,7 @@ describe 'Annotator.Plugin.EnhancedAnchoring', -> ...@@ -59,7 +58,7 @@ describe 'Annotator.Plugin.EnhancedAnchoring', ->
annotator = annotator =
publish: sinon.spy() publish: sinon.spy()
am = new Annotator.Plugin.EnhancedAnchoring() am = new ea.EnhancedAnchoring()
am.annotator = annotator am.annotator = annotator
am.pluginInit() am.pluginInit()
...@@ -287,7 +286,7 @@ describe 'Annotator.Plugin.EnhancedAnchoring', -> ...@@ -287,7 +286,7 @@ describe 'Annotator.Plugin.EnhancedAnchoring', ->
annotator = annotator =
publish: sinon.spy() publish: sinon.spy()
am = new Annotator.Plugin.EnhancedAnchoring() am = new ea.EnhancedAnchoring()
am.annotator = annotator am.annotator = annotator
am.pluginInit() am.pluginInit()
......
Annotator = require('annotator')
th = require('../../../h/static/scripts/annotator/plugin/texthighlights')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
# In order to be able to create highlights,
# the Annotator.TextHighlight class must exist.
# This class is registered then the TextHighlights plugin
# is initialized, so we will do that.
th = new Annotator.Plugin.TextHighlights()
th.pluginInit()
describe 'Annotator.Plugin.TextHighlight', -> describe 'Annotator.Plugin.TextHighlight', ->
sandbox = null sandbox = null
...@@ -23,11 +20,11 @@ describe 'Annotator.Plugin.TextHighlight', -> ...@@ -23,11 +20,11 @@ describe 'Annotator.Plugin.TextHighlight', ->
element: element:
delegate: sinon.spy() delegate: sinon.spy()
new Annotator.TextHighlight anchor, "test page", "test range" new th.TextHighlight anchor, "test page", "test range"
beforeEach -> beforeEach ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
sandbox.stub Annotator.TextHighlight, 'highlightRange', sandbox.stub th.TextHighlight, 'highlightRange',
(normedRange, cssClass) -> (normedRange, cssClass) ->
hl = document.createElement "hl" hl = document.createElement "hl"
hl.appendChild document.createTextNode "test highlight span" hl.appendChild document.createTextNode "test highlight span"
...@@ -44,7 +41,7 @@ describe 'Annotator.Plugin.TextHighlight', -> ...@@ -44,7 +41,7 @@ describe 'Annotator.Plugin.TextHighlight', ->
describe "constructor", -> describe "constructor", ->
it 'wraps a highlight span around the given range', -> it 'wraps a highlight span around the given range', ->
hl = createTestHighlight() hl = createTestHighlight()
assert.calledWith Annotator.TextHighlight.highlightRange, "test range" assert.calledWith th.TextHighlight.highlightRange, "test range"
it 'stores the created highlight spans in _highlights', -> it 'stores the created highlight spans in _highlights', ->
hl = createTestHighlight() hl = createTestHighlight()
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
...@@ -13,13 +15,25 @@ poem = ...@@ -13,13 +15,25 @@ poem =
“’Tis some visitor,” I muttered, “tapping at my chamber door— “’Tis some visitor,” I muttered, “tapping at my chamber door—
Only this and nothing more.”' Only this and nothing more.”'
describe 'h', ->
describe 'h:services', ->
sandbox = null sandbox = null
fakeStringHelpers = null
before ->
angular.module('h', [])
require('../../h/static/scripts/services')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide) -> beforeEach module ($provide) ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
fakeStringHelpers = {
uniFold: sinon.stub().returnsArg(0)
}
$provide.value('stringHelpers', fakeStringHelpers)
return return
afterEach -> afterEach ->
...@@ -27,22 +41,19 @@ describe 'h', -> ...@@ -27,22 +41,19 @@ describe 'h', ->
describe 'viewFilter service', -> describe 'viewFilter service', ->
viewFilter = null viewFilter = null
stringHelpers = null
beforeEach inject (_stringHelpers_, _viewFilter_) -> beforeEach inject (_viewFilter_) ->
stringHelpers = _stringHelpers_
viewFilter = _viewFilter_ viewFilter = _viewFilter_
describe 'filter', -> describe 'filter', ->
it 'normalizes the filter terms', -> it 'normalizes the filter terms', ->
stringHelpers.uniFold = sandbox.spy()
filters = filters =
text: text:
terms: ['Tiger'] terms: ['Tiger']
operator: 'and' operator: 'and'
viewFilter.filter [], filters viewFilter.filter [], filters
assert.calledWith stringHelpers.uniFold, 'tiger' assert.calledWith fakeStringHelpers.uniFold, 'tiger'
describe 'filter operators', -> describe 'filter operators', ->
annotations = null annotations = null
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
mockFlash = sandbox.spy()
mockDocument = {prop: -> '/session'}
describe 'session', -> describe 'h.session', ->
fakeFlash = null
fakeDocument = null
fakeXsrf = null
sandbox = null
before ->
angular.module('h.session', ['ngResource'])
require('../../h/static/scripts/session/session-service')
beforeEach module('h.session') beforeEach module('h.session')
beforeEach module ($provide, sessionProvider) -> beforeEach module ($provide, sessionProvider) ->
$provide.value '$document', mockDocument sandbox = sinon.sandbox.create()
$provide.value 'flash', mockFlash
fakeFlash = sandbox.spy()
fakeDocument = {prop: -> '/session'}
fakeXsrf = {token: 'faketoken'}
$provide.value '$document', fakeDocument
$provide.value 'flash', fakeFlash
$provide.value 'xsrf', fakeXsrf
sessionProvider.actions = sessionProvider.actions =
login: login:
url: '/login' url: '/login'
method: 'POST' method: 'POST'
return return
afterEach -> afterEach ->
...@@ -23,12 +40,10 @@ describe 'session', -> ...@@ -23,12 +40,10 @@ describe 'session', ->
describe 'sessionService', -> describe 'sessionService', ->
$httpBackend = null $httpBackend = null
session = null session = null
xsrf = null
beforeEach inject (_$httpBackend_, _session_, _xsrf_) -> beforeEach inject (_$httpBackend_, _session_) ->
$httpBackend = _$httpBackend_ $httpBackend = _$httpBackend_
session = _session_ session = _session_
xsrf = _xsrf_
describe '#<action>()', -> describe '#<action>()', ->
url = '/login' url = '/login'
...@@ -45,7 +60,7 @@ describe 'session', -> ...@@ -45,7 +60,7 @@ describe 'session', ->
$httpBackend.expectPOST(url).respond(response) $httpBackend.expectPOST(url).respond(response)
result = session.login({}) result = session.login({})
$httpBackend.flush() $httpBackend.flush()
assert.calledWith mockFlash, 'error', 'fail' assert.calledWith fakeFlash, 'error', 'fail'
it 'should assign errors and status reasons to the model', -> it 'should assign errors and status reasons to the model', ->
response = response =
...@@ -71,7 +86,7 @@ describe 'session', -> ...@@ -71,7 +86,7 @@ describe 'session', ->
request = $httpBackend.expectPOST(url).respond({model}) request = $httpBackend.expectPOST(url).respond({model})
result = session.login({}) result = session.login({})
$httpBackend.flush() $httpBackend.flush()
assert.equal xsrf.token, token assert.equal fakeXsrf.token, token
$httpBackend.expectPOST(url, {}, headers).respond({}) $httpBackend.expectPOST(url, {}, headers).respond({})
session.login({}) session.login({})
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
describe 'store', -> describe 'store', ->
$httpBackend = null $httpBackend = null
sandbox = null sandbox = null
store = null store = null
fakeDocument = null fakeDocument = null
before ->
angular.module('h', ['ngResource'])
require('../../h/static/scripts/store-service')
beforeEach module('h') beforeEach module('h')
beforeEach module ($provide) -> beforeEach module ($provide) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
describe 'streamer', -> describe 'streamer', ->
WebSocket = null WebSocket = null
fakeSock = null fakeSock = null
streamer = null streamer = null
url = 'wss://magicstreemz/giraffe' url = 'wss://magicstreemz/giraffe'
sandbox = null
before ->
require('../../h/static/scripts/streamer-service')
beforeEach module('h.streamer') beforeEach module('h.streamer')
beforeEach module -> beforeEach module ->
sandbox = sinon.sandbox.create()
fakeSock = { fakeSock = {
send: sandbox.spy() send: sandbox.spy()
close: sandbox.spy() close: sandbox.spy()
......
{module, inject} = require('angular-mock')
assert = chai.assert assert = chai.assert
sinon.assert.expose(assert, prefix: '') sinon.assert.expose(assert, prefix: '')
describe 'Threading', -> describe 'Threading', ->
instance = null instance = null
before ->
angular.module('h', [])
require('../../h/static/scripts/threading-service')
beforeEach module('h') beforeEach module('h')
beforeEach inject (_threading_) -> beforeEach inject (_threading_) ->
......
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'h.helpers.formHelpers', ->
formHelpers = null
beforeEach module('h.helpers')
beforeEach inject (_formHelpers_) ->
formHelpers = _formHelpers_
describe '.applyValidationErrors', ->
form = null
beforeEach ->
form =
$setValidity: sinon.spy()
username: {$setValidity: sinon.spy()}
password: {$setValidity: sinon.spy()}
it 'sets the "response" error key for each field with errors', ->
formHelpers.applyValidationErrors form,
username: 'must be at least 3 characters'
password: 'must be present'
assert.calledWith(form.username.$setValidity, 'response', false)
assert.calledWith(form.password.$setValidity, 'response', false)
it 'adds an error message to each input controller', ->
formHelpers.applyValidationErrors form,
username: 'must be at least 3 characters'
password: 'must be present'
assert.equal(form.username.responseErrorMessage, 'must be at least 3 characters')
assert.equal(form.password.responseErrorMessage, 'must be present')
it 'sets the "response" error key if the form has a failure reason', ->
formHelpers.applyValidationErrors form, null, 'fail'
assert.calledWith(form.$setValidity, 'response', false)
it 'adds an reason message as the response error', ->
formHelpers.applyValidationErrors form, null, 'fail'
assert.equal(form.responseErrorMessage, 'fail')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment