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 options = {
app: jQuery('link[type="application/annotator+html"]').attr('href'),
......@@ -23,4 +68,4 @@ if (window.hasOwnProperty('hypothesisConfig')) {
}
window.annotator = new Klass(document.body, options);
window.Annotator.noConflict().$.noConflict(true);
Annotator.noConflict().$.noConflict(true);
angular = require('angular')
AUTH_SESSION_ACTIONS = [
'login'
'logout'
......@@ -124,3 +126,6 @@ angular.module('h')
.config(configure)
.controller('AuthAppController', AuthAppController)
.controller('AuthPageController', AuthPageController)
require('./account-controller')
require('./auth-controller')
Annotator = require('annotator')
# Save references to Range and Util (because we call Annotator.noConflict() when
# bootstrapping)
Range = Annotator.Range
......
Annotator = require('annotator')
$ = Annotator.$
class Annotator.Plugin.BucketBar extends Annotator.Plugin
......@@ -338,3 +340,5 @@ class Annotator.Plugin.BucketBar extends Annotator.Plugin
isUpper: (i) -> i == 1
isLower: (i) -> i == @index.length - 2
exports.BucketBar = Annotator.Plugin.BucketBar
Annotator = require('annotator')
$ = Annotator.$
# Extracts individual keys from an object and returns a new one.
......@@ -45,3 +47,5 @@ CrossFrame = class Annotator.Plugin.CrossFrame extends Annotator.Plugin
this.onConnect = (fn) ->
bridge.onConnect(fn)
exports.CrossFrame = CrossFrame
Annotator = @Annotator
Annotator = require('annotator')
$ = Annotator.$
# Fake two-phase / pagination support, used for HTML documents
......@@ -293,3 +293,5 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
selectors
exports.Anchor = Anchor
exports.EnhancedAnchoring = Annotator.Plugin.EnhancedAnchoring
require('../../vendor/jquery.scrollintoview')
$ = Annotator.$
# Public: Wraps the DOM Nodes within the provided range with a highlight
......@@ -125,3 +127,5 @@ class Annotator.Plugin.TextHighlights extends Annotator.Plugin
pluginInit: ->
# Export the text highlight class for other plugins
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 = [
'ngAnimate'
'ngRoute'
......@@ -92,3 +100,38 @@ module = angular.module('h', imports)
unless mocha? # Crude method of detecting test environment.
module.run(setupCrossFrame)
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
options:
# Scope identifier to distinguish this channel from any others
......
......@@ -22,13 +22,13 @@ class AppController
this.$inject = [
'$controller', '$document', '$location', '$route', '$scope', '$window',
'auth', 'drafts', 'identity',
'permissions', 'streamer', 'streamfilter', 'annotationUI',
'permissions', 'streamer', 'annotationUI',
'annotationMapper', 'threading'
]
constructor: (
$controller, $document, $location, $route, $scope, $window,
auth, drafts, identity,
permissions, streamer, streamfilter, annotationUI,
permissions, streamer, annotationUI,
annotationMapper, threading
) ->
$controller(AnnotationUIController, {$scope})
......@@ -176,11 +176,11 @@ class AnnotationViewerController
class ViewerController
this.$inject = [
'$scope', '$route', 'annotationUI', 'crossframe', 'annotationMapper',
'auth', 'flash', 'streamer', 'streamfilter', 'store'
'auth', 'streamer', 'streamfilter', 'store'
]
constructor: (
$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
$scope.isEmbedded = true
......
angular = require('angular')
Markdown = require('./vendor/Markdown.Converter')
class Converter extends Markdown.Converter
constructor: ->
super
......
Annotator = @Annotator
$ = Annotator.$
$ = require('jquery')
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'
# Events to be bound on Annotator#element.
......
angular = require('angular')
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
# For unicode normalization we use the unorm library
createStringHelpers = ->
......
Annotator = @Annotator
$ = Annotator.$
$ = require('jquery')
Annotator = require('annotator')
Guest = require('./guest')
class Annotator.Host extends Annotator.Guest
module.exports = class Annotator.Host extends Annotator.Guest
# Drag state variables
drag:
delta: 0
......
angular = require('angular')
angular.module('h.session', ['ngResource', 'h.helpers'])
require('./session-service')
angular = require('angular')
mail = require('./vendor/jwz')
class ThreadingService
# Mix in message thread properties into the prototype. The body of the
# class will overwrite any methods applied here. If you need inheritance
......
......@@ -10,52 +10,43 @@ module.exports = function(config) {
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],
frameworks: [
'browserify',
'mocha'
],
// list of files / patterns to load in the browser
files: [
'h/static/scripts/vendor/polyfills/bind.js',
'h/static/scripts/vendor/polyfills/url.js',
'h/static/scripts/vendor/polyfills/promise.js',
// Application external deps
'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-mocks.js',
'h/static/scripts/vendor/angular-animate.js',
'h/static/scripts/vendor/angular-bootstrap.js',
'h/static/scripts/vendor/angular-resource.js',
'h/static/scripts/vendor/angular-route.js',
'h/static/scripts/vendor/angular-sanitize.js',
'h/static/scripts/vendor/ng-tags-input.js',
'h/static/scripts/annotator/plugin/texthighlights.js',
'h/static/scripts/app.js',
'h/static/scripts/account.js',
'h/static/scripts/helpers.js',
'h/static/scripts/session.js',
'h/static/scripts/hypothesis.js',
'h/static/scripts/vendor/annotator.js',
'h/static/scripts/vendor/polyfills/autofill-event.js',
'h/static/scripts/vendor/polyfills/bind.js',
'h/static/scripts/vendor/katex/katex.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/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/chai.js',
'h/templates/client/*.html',
'tests/js/bootstrap.coffee',
'tests/js/**/*-test.coffee'
// Tests
'tests/js/**/*-test.coffee',
],
......@@ -72,10 +63,14 @@ module.exports = function(config) {
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'**/*.coffee': ['coffee'],
'**/*.coffee': ['browserify'],
'h/templates/client/*.html': ['ng-html2js'],
},
browserify: {
debug: true,
extensions: ['.coffee']
},
// test results reporter to use
// possible values: 'dots', 'progress'
......@@ -97,13 +92,13 @@ module.exports = function(config) {
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
browserNoActivityTimeout: 20000, // Travis is slow...
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
......
......@@ -4,14 +4,17 @@
"version": "0.0.0",
"description": "The Internet, peer reviewed.",
"dependencies": {
"coffee-script": "1.7.1",
"browserify": "^9.0.3",
"browserify-shim": "^3.8.3",
"clean-css": "2.2.2",
"coffee-script": "1.7.1",
"coffeeify": "^1.0.0",
"uglify-js": "2.4.14"
},
"devDependencies": {
"karma": "^0.12.17",
"karma-browserify": "^3.0.3",
"karma-cli": "0.0.4",
"karma-coffee-preprocessor": "^0.2.1",
"karma-mocha": "^0.1.4",
"karma-ng-html2js-preprocessor": "^0.1.0",
"karma-phantomjs-launcher": "^0.1.4",
......@@ -32,5 +35,29 @@
"bugs": {
"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
sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
describe 'AccountController', ->
describe 'h:AccountController', ->
$scope = null
fakeFlash = null
fakeSession = null
......@@ -13,10 +15,16 @@ describe 'AccountController', ->
disableUserPromise = null
profilePromise = null
createController = null
sandbox = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/account/account-controller')
beforeEach module('h')
beforeEach module ($provide, $filterProvider) ->
sandbox = sinon.sandbox.create()
fakeSession = {}
fakeFlash = sandbox.spy()
fakeIdentity =
......@@ -49,6 +57,9 @@ describe 'AccountController', ->
createController = ->
$controller('AccountController', {$scope: $scope})
afterEach ->
sandbox.restore()
describe '.submit', ->
createFakeForm = (overrides={}) ->
defaults =
......
{inject, module} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
......@@ -19,12 +21,16 @@ class MockSession
mockFlash = sandbox.spy()
mockFormHelpers = applyValidationErrors: sandbox.spy()
describe 'AuthController', ->
describe 'h:AuthController', ->
$scope = null
$timeout = null
auth = null
session = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/account/auth-controller')
beforeEach module('h')
beforeEach module('h.templates')
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'AnnotationMapperService', ->
sandbox = sinon.sandbox.create()
......@@ -9,6 +12,10 @@ describe 'AnnotationMapperService', ->
fakeThreading = null
annotationMapper = null
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-mapper-service')
beforeEach module('h')
beforeEach module ($provide) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'AnnotationSync', ->
sandbox = sinon.sandbox.create()
publish = null
......@@ -10,6 +13,10 @@ describe 'AnnotationSync', ->
options = null
PARENT_WINDOW = 'PARENT_WINDOW'
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-sync')
beforeEach module('h')
beforeEach inject (AnnotationSync, $rootScope) ->
listeners = {}
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'AnnotationUI', ->
annotationUI = null
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-ui-service')
beforeEach module('h')
beforeEach inject (_annotationUI_) ->
annotationUI = _annotationUI_
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'AnnotationUISync', ->
sandbox = sinon.sandbox.create()
$digest = null
......@@ -13,6 +16,10 @@ describe 'AnnotationUISync', ->
createChannel = -> {notify: sandbox.stub()}
PARENT_WINDOW = 'PARENT_WINDOW'
before ->
angular.module('h', [])
require('../../h/static/scripts/annotation-ui-sync')
beforeEach module('h')
beforeEach inject (AnnotationUISync, $rootScope) ->
$digest = sandbox.stub($rootScope, '$digest')
......
bb = require('../../../../h/static/scripts/annotator/plugin/bucket-bar')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'Annotator.BucketBar', ->
createBucketBar = (options) ->
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
# 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
sinon.assert.expose(assert, prefix: '')
describe 'Annotator.Plugin.CrossFrame', ->
CrossFrame = null
fakeDiscovery = null
fakeBridge = null
fakeAnnotationSync = null
......@@ -13,7 +15,7 @@ describe 'Annotator.Plugin.CrossFrame', ->
on: sandbox.stub()
emit: sandbox.stub()
element = document.createElement('div')
return new Annotator.Plugin.CrossFrame(element, $.extend({}, defaults, options))
return new cf.CrossFrame(element, $.extend({}, defaults, options))
beforeEach ->
fakeDiscovery =
......@@ -29,10 +31,9 @@ describe 'Annotator.Plugin.CrossFrame', ->
fakeAnnotationSync =
sync: sandbox.stub()
CrossFrame = Annotator.Plugin.CrossFrame
sandbox.stub(CrossFrame, 'AnnotationSync').returns(fakeAnnotationSync)
sandbox.stub(CrossFrame, 'Discovery').returns(fakeDiscovery)
sandbox.stub(CrossFrame, 'Bridge').returns(fakeBridge)
cf.CrossFrame.AnnotationSync = sandbox.stub().returns(fakeAnnotationSync)
cf.CrossFrame.Discovery = sandbox.stub().returns(fakeDiscovery)
cf.CrossFrame.Bridge = sandbox.stub().returns(fakeBridge)
afterEach ->
sandbox.restore()
......@@ -40,33 +41,28 @@ describe 'Annotator.Plugin.CrossFrame', ->
describe 'constructor', ->
it 'instantiates the Discovery component', ->
createCrossFrame()
assert.called(CrossFrame.Discovery)
assert.calledWith(CrossFrame.Discovery, window)
assert.calledWith(cf.CrossFrame.Discovery, window)
it 'passes the options along to the bridge', ->
createCrossFrame(server: true)
assert.called(CrossFrame.Discovery)
assert.calledWith(CrossFrame.Discovery, window, server: true)
assert.calledWith(cf.CrossFrame.Discovery, window, server: true)
it 'instantiates the CrossFrame component', ->
createCrossFrame()
assert.called(CrossFrame.Bridge)
assert.calledWith(CrossFrame.Discovery)
assert.calledWith(cf.CrossFrame.Discovery)
it 'passes the options along to the bridge', ->
createCrossFrame(scope: 'myscope')
assert.called(CrossFrame.Bridge)
assert.calledWith(CrossFrame.Bridge, scope: 'myscope')
assert.calledWith(cf.CrossFrame.Bridge, scope: 'myscope')
it 'instantiates the AnnotationSync component', ->
createCrossFrame()
assert.called(CrossFrame.AnnotationSync)
assert.called(cf.CrossFrame.AnnotationSync)
it 'passes along options to AnnotationSync', ->
formatter = (x) -> x
createCrossFrame(formatter: formatter)
assert.called(CrossFrame.AnnotationSync)
assert.calledWith(CrossFrame.AnnotationSync, fakeBridge, {
assert.calledWith(cf.CrossFrame.AnnotationSync, fakeBridge, {
on: sinon.match.func
emit: sinon.match.func
formatter: formatter
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'h', ->
fakeAnnotator = null
fakeIdentity = null
sandbox = null
before ->
angular.module('h', [])
require('../../h/static/scripts/auth-service')
beforeEach module('h')
beforeEach module ($provide) ->
......
{module, inject} = require('angular-mock')
Channel = require('../../h/static/scripts/vendor/jschannel.js')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'Bridge', ->
sandbox = sinon.sandbox.create()
createBridge = null
createChannel = null
before ->
angular.module('h', [])
require('../../h/static/scripts/bridge')
beforeEach module('h')
beforeEach inject (Bridge) ->
createBridge = (options) ->
......
This diff is collapsed.
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'CrossFrameService', ->
sandbox = sinon.sandbox.create()
crossframe = null
......@@ -14,6 +17,10 @@ describe 'CrossFrameService', ->
fakeAnnotationSync = null
fakeAnnotationUISync = null
before ->
angular.module('h', [])
require('../../h/static/scripts/cross-frame-service')
beforeEach module('h')
beforeEach module ($provide) ->
$fakeDocument = {}
......
assert = chai.assert
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'
})
{module, inject} = require('angular-mock')
$provide.value('$window', fakeWindow)
$provide.value('$document', fakeDocument)
assert = chai.assert
$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 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', ->
$compile = null
$element = null
$isolateScope = null
$scope = null
beforeEach inject (_$compile_, _$rootScope_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
beforeEach ->
$scope.model = {a: 1, b: 1}
......
{module, inject} = require('angular-mock')
assert = chai.assert
sandbox = sinon.sandbox.create()
describe 'h.directives.annotation', ->
$compile = null
......@@ -8,17 +10,28 @@ describe 'h.directives.annotation', ->
$timeout = null
annotation = null
createController = null
flash = null
fakeAuth = null
fakeStore = null
fakeUser = null
fakeAnnotationMapper = 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.templates')
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeAuth =
user: 'acct:bill@localhost'
fakeAnnotationMapper =
......@@ -30,11 +43,37 @@ describe 'h.directives.annotation', ->
admin: ['acct:bill@localhost']
deleteAnnotation: sandbox.stub()
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 '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
beforeEach inject (_$compile_, $controller, _$document_, $rootScope, _$timeout_) ->
......@@ -50,12 +89,10 @@ describe 'h.directives.annotation', ->
target: [{}]
uri: 'http://example.com'
user: 'acct:bill@localhost'
flash = sinon.spy()
createController = ->
$controller 'AnnotationController',
$scope: $scope
flash: flash
afterEach ->
sandbox.restore()
......@@ -82,7 +119,7 @@ describe 'h.directives.annotation', ->
delete annotation.id
controller = createController()
$scope.$digest()
assert controller.isPrivate()
assert.deepEqual annotation.permissions, {read: ['justme']}
describe '#reply', ->
controller = null
......@@ -102,26 +139,19 @@ describe 'h.directives.annotation', ->
match = sinon.match {references: [annotation.id], uri: annotation.uri}
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 = {}
fakeAnnotationMapper.createAnnotation.returns(reply)
annotation.permissions.read.push('group:__world__')
fakePermissions.isPublic.returns(true)
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', ->
reply = {}
fakeAnnotationMapper.createAnnotation.returns(reply)
fakePermissions.isPublic.returns(false)
controller.reply()
assert.notInclude(reply.permissions.read, 'group:__world__')
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')
assert.deepEqual(reply.permissions, {read: ['justme']})
describe '#render', ->
controller = null
......@@ -297,18 +327,15 @@ describe 'h.directives.annotation', ->
it 'is updated on first digest', ->
$scope.$digest()
assert.isNotNull(controller.timestamp)
assert.equal(controller.timestamp, 'a while ago')
it 'is updated after a timeout', ->
fakeTimeHelpers.nextFuzzyUpdate.returns(10)
$scope.$digest()
timestamp = controller.timestamp
clock.tick(30000)
$timeout.flush()
assert.notEqual(timestamp, controller.timestamp)
timestamp = controller.timestamp
clock.tick(30000)
clock.tick(11000)
fakeTimeHelpers.toFuzzyString.returns('ages ago')
$timeout.flush()
assert.notEqual(timestamp, controller.timestamp)
assert.equal(controller.timestamp, 'ages ago')
it 'is no longer updated after the scope is destroyed', ->
$scope.$digest()
......
{module, inject} = require('angular-mock')
assert = chai.assert
VISIBILITY_KEY ='hypothesis.visibility'
......@@ -5,104 +7,87 @@ VISIBILITY_PUBLIC = 'public'
VISIBILITY_PRIVATE = 'private'
describe 'h.directives.privacy', ->
$window = null
$scope = null
$compile = null
$injector = null
$element = null
$isolateScope = null
$scope = null
$window = null
fakeAuth = null
fakePermissions = null
sandbox = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/privacy')
beforeEach module('h')
beforeEach module('h.templates')
describe 'memory fallback', ->
fakeAuth = null
sandbox = null
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeAuth = {
user: 'acct:angry.joe@texas.com'
}
$provide.value 'auth', fakeAuth
return
afterEach ->
sandbox.restore()
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
describe 'has memory fallback', ->
$window = null
$scope2 = null
fakeAuth = {
user: 'acct:angry.joe@texas.com'
}
beforeEach inject (_$compile_, _$rootScope_, _$window_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
$scope2 = _$rootScope_.$new()
$window = _$window_
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']})
}
$window.localStorage = null
$provide.value 'auth', fakeAuth
$provide.value 'permissions', fakePermissions
return
it 'stores the default visibility level when it changes', ->
$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_, _$window_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
$window = _$window_
$scope2.permissions = {read: []}
$element = $compile('<privacy ng-model="permissions">')($scope2)
$scope2.$digest()
afterEach ->
sandbox.restore()
# Roundabout way: the storage works because the directive
# could read out the privacy level
readPermissions = $scope2.permissions.read[0]
assert.equal readPermissions, 'group:__world__'
describe 'has localStorage', ->
sandbox = null
fakeAuth = null
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
describe 'memory fallback', ->
$scope2 = null
fakeAuth = {
user: 'acct:angry.joe@texas.com'
}
beforeEach inject (_$rootScope_) ->
$scope2 = _$rootScope_.$new()
$provide.value 'auth', fakeAuth
return
$window.localStorage = null
afterEach ->
sandbox.restore()
it 'stores the default visibility level when it changes', ->
$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_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
$injector = _$injector_
$window = _$window_
$scope2.permissions = {read: []}
$element = $compile('<privacy ng-model="permissions">')($scope2)
$scope2.$digest()
describe 'storage', ->
store = null
# Roundabout way: the storage works because the directive
# could read out the privacy level
readPermissions = $scope2.permissions.read[0]
assert.equal readPermissions, 'everybody'
beforeEach ->
store = $window.localStorage
describe 'has localStorage', ->
it 'stores the default visibility level when it changes', ->
$scope.permissions = {read: ['acct:user@example.com']}
$element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest()
$isolateScope = $element.isolateScope()
$isolateScope.setLevel(name: VISIBILITY_PUBLIC)
it 'stores the default visibility level when it changes', ->
$scope.permissions = {read: ['acct:user@example.com']}
$element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest()
$isolateScope = $element.isolateScope()
$isolateScope.setLevel(name: VISIBILITY_PUBLIC)
expected = VISIBILITY_PUBLIC
stored = store.getItem VISIBILITY_KEY
assert.equal stored, expected
expected = VISIBILITY_PUBLIC
stored = $window.localStorage.getItem VISIBILITY_KEY
assert.equal stored, expected
describe 'setting permissions', ->
$element = null
store = null
modelCtrl = null
beforeEach ->
store = $window.localStorage
......@@ -125,17 +110,15 @@ describe 'h.directives.privacy', ->
$scope.permissions = {read: []}
$element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest()
$isolateScope = $element.isolateScope()
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', ->
modelCtrl = $element.controller('ngModel')
store.setItem VISIBILITY_KEY, VISIBILITY_PRIVATE
$scope.permissions.read = ['acct:user@example.com']
$scope.$digest()
assert.equal $isolateScope.level.name, VISIBILITY_PUBLIC
assert.equal $element.isolateScope().level.name, VISIBILITY_PUBLIC
describe 'when permissions.read is filled', ->
it 'does not alter the level', ->
......@@ -156,25 +139,11 @@ describe 'h.directives.privacy', ->
$element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest()
readPermissions = $scope.permissions.read[0]
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
assert.deepEqual $scope.permissions, fakePermissions.private()
it 'puts group_world into the read permissions for public visibility', ->
store.setItem VISIBILITY_KEY, VISIBILITY_PUBLIC
$element = $compile('<privacy ng-model="permissions">')($scope)
$scope.$digest()
readPermissions = $scope.permissions.read[0]
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
assert.deepEqual $scope.permissions, fakePermissions.public()
{module, inject} = require('angular-mock')
assert = chai.assert
describe 'h.directives', ->
$scope = null
describe 'h:directives.simple-search', ->
$compile = null
$element = null
$scope = null
fakeWindow = null
isolate = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/simple-search')
beforeEach module('h')
beforeEach inject (_$compile_, _$rootScope_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
describe '.simpleSearch', ->
$element = null
beforeEach ->
$scope.update = sinon.spy()
$scope.clear = sinon.spy()
template= '''
<div class="simpleSearch"
query="query"
on-search="update(query)"
on-clear="clear()">
</div>
'''
$element = $compile(angular.element(template))($scope)
$scope.$digest()
isolate = $element.isolateScope()
it 'updates the search-bar', ->
$scope.query = "Test query"
$scope.$digest()
assert.equal(isolate.searchtext, $scope.query)
it 'calls the given search function', ->
isolate.searchtext = "Test query"
isolate.$digest()
$element.find('form').triggerHandler('submit')
sinon.assert.calledWith($scope.update, "Test query")
it 'calls the given clear function', ->
$element.find('.simple-search-clear').click()
assert($scope.clear.called)
it 'clears the search-bar', ->
isolate.query = ''
isolate.$digest()
isolate.searchtext = "Test query"
isolate.$digest()
$element.find('.simple-search-clear').click()
assert.equal(isolate.searchtext, '')
it 'invokes callbacks when the input model changes', ->
$scope.query = "Test query"
$scope.$digest()
sinon.assert.calledOnce($scope.update)
$scope.query = ""
$scope.$digest()
sinon.assert.calledOnce($scope.clear)
it 'adds a class to the form when there is no input value', ->
$form = $element.find('.simple-search-form')
assert.include($form.prop('className'), 'simple-search-inactive')
it 'removes the class from the form when there is an input value', ->
$scope.query = "Test query"
$scope.$digest()
$form = $element.find('.simple-search-form')
assert.notInclude($form.prop('className'), 'simple-search-inactive')
$scope.update = sinon.spy()
$scope.clear = sinon.spy()
template= '''
<div class="simpleSearch"
query="query"
on-search="update(query)"
on-clear="clear()">
</div>
'''
$element = $compile(angular.element(template))($scope)
$scope.$digest()
isolate = $element.isolateScope()
it 'updates the search-bar', ->
$scope.query = "Test query"
$scope.$digest()
assert.equal(isolate.searchtext, $scope.query)
it 'calls the given search function', ->
isolate.searchtext = "Test query"
isolate.$digest()
$element.find('form').triggerHandler('submit')
sinon.assert.calledWith($scope.update, "Test query")
it 'calls the given clear function', ->
$element.find('.simple-search-clear').click()
assert($scope.clear.called)
it 'clears the search-bar', ->
isolate.query = ''
isolate.$digest()
isolate.searchtext = "Test query"
isolate.$digest()
$element.find('.simple-search-clear').click()
assert.equal(isolate.searchtext, '')
it 'invokes callbacks when the input model changes', ->
$scope.query = "Test query"
$scope.$digest()
sinon.assert.calledOnce($scope.update)
$scope.query = ""
$scope.$digest()
sinon.assert.calledOnce($scope.clear)
it 'adds a class to the form when there is no input value', ->
$form = $element.find('.simple-search-form')
assert.include($form.prop('className'), 'simple-search-inactive')
it 'removes the class from the form when there is an input value', ->
$scope.query = "Test query"
$scope.$digest()
$form = $element.find('.simple-search-form')
assert.notInclude($form.prop('className'), 'simple-search-inactive')
{module, inject} = require('angular-mock')
assert = chai.assert
describe 'h.directives.statusButton', ->
describe 'h:directives.status-button', ->
$scope = null
$compile = null
$element = null
before ->
angular.module('h', [])
require('../../../h/static/scripts/directives/status-button')
beforeEach module('h')
beforeEach inject (_$compile_, _$rootScope_) ->
......
This diff is collapsed.
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'Discovery', ->
sandbox = sinon.sandbox.create()
fakeTopWindow = null
fakeFrameWindow = null
createDiscovery = null
before ->
angular.module('h', [])
require('../../h/static/scripts/discovery')
beforeEach module('h')
beforeEach inject (Discovery) ->
createDiscovery = (win, options) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'persona', ->
filter = null
term = 'acct:hacker@example.com'
describe 'h:filters', ->
before ->
angular.module('h', [])
require('../../h/static/scripts/filters')
describe 'persona', ->
filter = null
term = 'acct:hacker@example.com'
beforeEach module('h')
beforeEach inject ($filter) ->
filter = $filter('persona')
beforeEach module('h')
beforeEach inject ($filter) ->
filter = $filter('persona')
it 'should return the whole term by request', ->
result = filter('acct:hacker@example.com', 'term')
assert.equal result, 'acct:hacker@example.com'
it 'should return the whole term by request', ->
result = filter('acct:hacker@example.com', 'term')
assert.equal result, 'acct:hacker@example.com'
it 'should return the requested part', ->
assert.equal filter(term), 'hacker'
assert.equal filter(term, 'term'), term,
assert.equal filter(term, 'username'), 'hacker'
assert.equal filter(term, 'provider'), 'example.com'
it 'should return the requested part', ->
assert.equal filter(term), 'hacker'
assert.equal filter(term, 'term'), term,
assert.equal filter(term, 'username'), 'hacker'
assert.equal filter(term, 'provider'), 'example.com'
it 'should pass through unrecognized terms as username or term', ->
assert.equal filter('bogus'), 'bogus'
assert.equal filter('bogus', 'username'), 'bogus'
it 'should pass through unrecognized terms as username or term', ->
assert.equal filter('bogus'), 'bogus'
assert.equal filter('bogus', 'username'), 'bogus'
it 'should handle error cases', ->
assert.notOk filter()
assert.notOk filter('bogus', 'provider')
it 'should handle error cases', ->
assert.notOk filter()
assert.notOk filter('bogus', 'provider')
describe 'urlencode', ->
filter = null
describe 'urlencode', ->
filter = null
beforeEach module('h')
beforeEach inject ($filter) ->
filter = $filter('urlencode')
beforeEach module('h')
beforeEach inject ($filter) ->
filter = $filter('urlencode')
it 'encodes reserved characters in the term', ->
assert.equal(filter('#hello world'), '%23hello%20world')
it 'encodes reserved characters in the term', ->
assert.equal(filter('#hello world'), '%23hello%20world')
Annotator = require('annotator')
Guest = require('../../h/static/scripts/guest')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'Annotator.Guest', ->
sandbox = sinon.sandbox.create()
sandbox = null
fakeCrossFrame = null
createGuest = (options) ->
element = document.createElement('div')
return new Annotator.Guest(element, options || {})
# Silence Annotator's sassy backchat
beforeEach -> sandbox.stub(console, 'log')
afterEach -> sandbox.restore()
return new Guest(element, options || {})
beforeEach ->
sandbox = sinon.sandbox.create()
fakeCrossFrame =
onConnect: 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', ->
it 'sets the scope for the cross frame bridge', ->
......@@ -177,7 +196,7 @@ describe 'Annotator.Guest', ->
{annotation: {$$tag: 'tag1'}, 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'])
assert.called(highlights[0].setFocused)
assert.calledWith(highlights[0].setFocused, true)
......@@ -188,7 +207,7 @@ describe 'Annotator.Guest', ->
{annotation: {$$tag: 'tag1'}, 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'])
assert.called(highlights[1].setFocused)
assert.calledWith(highlights[1].setFocused, false)
......@@ -199,7 +218,7 @@ describe 'Annotator.Guest', ->
anchors = [
{annotation: {$$tag: 'tag1'}, scrollToView: sandbox.stub()}
]
sandbox.stub(guest.anchoring, 'getAnchors').returns(anchors)
guest.anchoring.getAnchors.returns(anchors)
emitGuestEvent('scrollToAnnotation', 'ctx', 'tag1')
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
sinon.assert.expose(assert, prefix: '')
describe 'h.helpers.stringHelpers', ->
describe 'h.helpers:string-helpers', ->
stringHelpers = null
before ->
angular.module('h.helpers', [])
require('../../../h/static/scripts/helpers/string-helpers')
beforeEach module('h.helpers')
beforeEach inject (_stringHelpers_) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert
minute = 60
......@@ -36,11 +38,16 @@ FIXTURES_NEXT_FUZZY_UPDATE = [
[8 * year, 24 * day] # by setTimout
]
describe 'timeHelpers', ->
beforeEach module('h.helpers')
describe 'h.helpers:time-helpers', ->
timeHelpers = null
sandbox = null
before ->
angular.module('h.helpers', [])
require('../../../h/static/scripts/helpers/time-helpers')
beforeEach module('h.helpers')
beforeEach inject (_timeHelpers_) ->
timeHelpers = _timeHelpers_
sandbox = sinon.sandbox.create()
......
Annotator = require('annotator')
Host = require('../../h/static/scripts/host')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
......@@ -7,7 +10,7 @@ describe 'Annotator.Host', ->
createHost = (options={}) ->
element = document.createElement('div')
return new Annotator.Host(element, options)
return new Host(element, options)
beforeEach ->
# Disable Annotator's ridiculous logging.
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
describe 'identity', ->
describe 'h.identity', ->
provider = null
mockInjectable = {}
before ->
require('../../h/static/scripts/identity-service')
beforeEach module('h.identity')
beforeEach module ($provide, identityProvider) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'h', ->
describe 'h:permissions', ->
sandbox = null
fakeAuth = null
before ->
angular.module('h', [])
require('../../h/static/scripts/permissions-service')
beforeEach module('h')
beforeEach module ($provide) ->
......
Annotator = require('annotator')
ea = require('../../../h/static/scripts/annotator/plugin/enhancedanchoring')
assert = chai.assert
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.
# Every concrete implementation should have it's own class,
# encompassing a way to identify the given segment of the document.
#
# For testing, we will use the TestAnchor class,
# 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
......@@ -24,6 +20,7 @@ class TestAnchor extends Annotator.Anchor
@id = "fake anchor for " + target.id
describe 'Annotator.Plugin.EnhancedAnchoring', ->
sandbox = null
pendingTest = null
......@@ -33,13 +30,15 @@ describe 'Annotator.Plugin.EnhancedAnchoring', ->
beforeEach ->
sandbox = sinon.sandbox.create()
sandbox.stub Annotator.TextHighlight, 'createFrom',
(segment, anchor, page) ->
Annotator.TextHighlight = {
createFrom: (segment, anchor, page) ->
segment: segment
anchor: anchor
page: page
removeFromDocument: sinon.spy()
scrollToView: sinon.spy -> pendingTest?.resolve()
}
afterEach ->
sandbox.restore()
......@@ -59,7 +58,7 @@ describe 'Annotator.Plugin.EnhancedAnchoring', ->
annotator =
publish: sinon.spy()
am = new Annotator.Plugin.EnhancedAnchoring()
am = new ea.EnhancedAnchoring()
am.annotator = annotator
am.pluginInit()
......@@ -287,7 +286,7 @@ describe 'Annotator.Plugin.EnhancedAnchoring', ->
annotator =
publish: sinon.spy()
am = new Annotator.Plugin.EnhancedAnchoring()
am = new ea.EnhancedAnchoring()
am.annotator = annotator
am.pluginInit()
......
Annotator = require('annotator')
th = require('../../../h/static/scripts/annotator/plugin/texthighlights')
assert = chai.assert
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', ->
sandbox = null
......@@ -23,11 +20,11 @@ describe 'Annotator.Plugin.TextHighlight', ->
element:
delegate: sinon.spy()
new Annotator.TextHighlight anchor, "test page", "test range"
new th.TextHighlight anchor, "test page", "test range"
beforeEach ->
sandbox = sinon.sandbox.create()
sandbox.stub Annotator.TextHighlight, 'highlightRange',
sandbox.stub th.TextHighlight, 'highlightRange',
(normedRange, cssClass) ->
hl = document.createElement "hl"
hl.appendChild document.createTextNode "test highlight span"
......@@ -44,7 +41,7 @@ describe 'Annotator.Plugin.TextHighlight', ->
describe "constructor", ->
it 'wraps a highlight span around the given range', ->
hl = createTestHighlight()
assert.calledWith Annotator.TextHighlight.highlightRange, "test range"
assert.calledWith th.TextHighlight.highlightRange, "test range"
it 'stores the created highlight spans in _highlights', ->
hl = createTestHighlight()
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
......@@ -13,13 +15,25 @@ poem =
“’Tis some visitor,” I muttered, “tapping at my chamber door—
Only this and nothing more.”'
describe 'h', ->
describe 'h:services', ->
sandbox = null
fakeStringHelpers = null
before ->
angular.module('h', [])
require('../../h/static/scripts/services')
beforeEach module('h')
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeStringHelpers = {
uniFold: sinon.stub().returnsArg(0)
}
$provide.value('stringHelpers', fakeStringHelpers)
return
afterEach ->
......@@ -27,22 +41,19 @@ describe 'h', ->
describe 'viewFilter service', ->
viewFilter = null
stringHelpers = null
beforeEach inject (_stringHelpers_, _viewFilter_) ->
stringHelpers = _stringHelpers_
beforeEach inject (_viewFilter_) ->
viewFilter = _viewFilter_
describe 'filter', ->
it 'normalizes the filter terms', ->
stringHelpers.uniFold = sandbox.spy()
filters =
text:
terms: ['Tiger']
operator: 'and'
viewFilter.filter [], filters
assert.calledWith stringHelpers.uniFold, 'tiger'
assert.calledWith fakeStringHelpers.uniFold, 'tiger'
describe 'filter operators', ->
annotations = null
......
{module, inject} = require('angular-mock')
assert = chai.assert
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 ($provide, sessionProvider) ->
$provide.value '$document', mockDocument
$provide.value 'flash', mockFlash
sandbox = sinon.sandbox.create()
fakeFlash = sandbox.spy()
fakeDocument = {prop: -> '/session'}
fakeXsrf = {token: 'faketoken'}
$provide.value '$document', fakeDocument
$provide.value 'flash', fakeFlash
$provide.value 'xsrf', fakeXsrf
sessionProvider.actions =
login:
url: '/login'
method: 'POST'
return
afterEach ->
......@@ -23,12 +40,10 @@ describe 'session', ->
describe 'sessionService', ->
$httpBackend = null
session = null
xsrf = null
beforeEach inject (_$httpBackend_, _session_, _xsrf_) ->
beforeEach inject (_$httpBackend_, _session_) ->
$httpBackend = _$httpBackend_
session = _session_
xsrf = _xsrf_
describe '#<action>()', ->
url = '/login'
......@@ -45,7 +60,7 @@ describe 'session', ->
$httpBackend.expectPOST(url).respond(response)
result = session.login({})
$httpBackend.flush()
assert.calledWith mockFlash, 'error', 'fail'
assert.calledWith fakeFlash, 'error', 'fail'
it 'should assign errors and status reasons to the model', ->
response =
......@@ -71,7 +86,7 @@ describe 'session', ->
request = $httpBackend.expectPOST(url).respond({model})
result = session.login({})
$httpBackend.flush()
assert.equal xsrf.token, token
assert.equal fakeXsrf.token, token
$httpBackend.expectPOST(url, {}, headers).respond({})
session.login({})
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'store', ->
$httpBackend = null
sandbox = null
store = null
fakeDocument = null
before ->
angular.module('h', ['ngResource'])
require('../../h/static/scripts/store-service')
beforeEach module('h')
beforeEach module ($provide) ->
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create()
describe 'streamer', ->
WebSocket = null
fakeSock = null
streamer = null
url = 'wss://magicstreemz/giraffe'
sandbox = null
before ->
require('../../h/static/scripts/streamer-service')
beforeEach module('h.streamer')
beforeEach module ->
sandbox = sinon.sandbox.create()
fakeSock = {
send: sandbox.spy()
close: sandbox.spy()
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose(assert, prefix: '')
describe 'Threading', ->
instance = null
before ->
angular.module('h', [])
require('../../h/static/scripts/threading-service')
beforeEach module('h')
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