Commit a7454216 authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #422 from hypothesis/extract-app-function

Extract app() into separate function
parents 58e214a2 0ddcf899
...@@ -12,9 +12,9 @@ var docs = 'https://h.readthedocs.io/en/latest/embedding.html'; ...@@ -12,9 +12,9 @@ var docs = 'https://h.readthedocs.io/en/latest/embedding.html';
*/ */
function configFrom(window_) { function configFrom(window_) {
var config = { var config = {
app: window_. app: settings.app(window_.document),
document.querySelector('link[type="application/annotator+html"]').href,
}; };
var chromeExt = 'chrome-extension://'; var chromeExt = 'chrome-extension://';
var mozExt = 'moz-extension://'; var mozExt = 'moz-extension://';
var edgeExt = 'ms-browser-extension://'; var edgeExt = 'ms-browser-extension://';
......
'use strict'; 'use strict';
/**
* Return the href URL of the first annotator link in the given document.
*
* Return the value of the href attribute of the first
* `<link type="application/annotator+html">` element in the given document.
*
* This URL is used as the src of the sidebar's iframe.
*
* @param {Document} - The document to search.
* @return {string} - The URL to use for the sidebar's iframe.
*
* @throws {Error} - If there's no annotator link or the first annotator has
* no href.
*
*/
function app(document_) {
var link = document_.querySelector('link[type="application/annotator+html"]');
if (!link) {
throw new Error('No application/annotator+html link in the document');
}
if (!link.href) {
throw new Error('application/annotator+html link has no href');
}
return link.href;
}
/** /**
* Return the `#annotations:*` ID from the given URL's fragment. * Return the `#annotations:*` ID from the given URL's fragment.
* *
...@@ -42,6 +71,7 @@ function query(url) { ...@@ -42,6 +71,7 @@ function query(url) {
} }
module.exports = { module.exports = {
app: app,
annotations: annotations, annotations: annotations,
query: query, query: query,
}; };
'use strict'; 'use strict';
var proxyquire = require('proxyquire'); var proxyquire = require('proxyquire');
var util = require('../../../shared/test/util');
var fakeSharedSettings = {}; var fakeSharedSettings = {};
var fakeSettings = {}; var fakeSettings = {};
var configFrom = proxyquire('../index', { var configFrom = proxyquire('../index', util.noCallThru({
'./settings': fakeSettings, './settings': fakeSettings,
'../../shared/settings': fakeSharedSettings, '../../shared/settings': fakeSharedSettings,
}); }));
var sandbox = sinon.sandbox.create(); var sandbox = sinon.sandbox.create();
function fakeWindow(someHref) { function fakeWindow() {
var href = someHref || 'LINK_HREF';
return { return {
document: { document: 'THE_DOCUMENT',
querySelector: sinon.stub().returns({href: href}),
},
location: {href: 'LOCATION_HREF'}, location: {href: 'LOCATION_HREF'},
}; };
} }
...@@ -32,6 +29,7 @@ describe('annotator.config', function() { ...@@ -32,6 +29,7 @@ describe('annotator.config', function() {
}); });
beforeEach('reset fakeSettings', function() { beforeEach('reset fakeSettings', function() {
fakeSettings.app = sinon.stub().returns('IFRAME_URL');
fakeSettings.annotations = sinon.stub(); fakeSettings.annotations = sinon.stub();
fakeSettings.query = sinon.stub(); fakeSettings.query = sinon.stub();
}); });
...@@ -40,31 +38,31 @@ describe('annotator.config', function() { ...@@ -40,31 +38,31 @@ describe('annotator.config', function() {
sandbox.restore(); sandbox.restore();
}); });
context("when there's an application/annotator+html <link>", function() { it('gets the config.app setting', function() {
var link; var window_ = fakeWindow();
beforeEach('add an application/annotator+html <link>', function() { configFrom(window_);
link = document.createElement('link');
link.type = 'application/annotator+html';
link.href = 'http://example.com/link';
document.head.appendChild(link);
});
afterEach('tidy up the link', function() { assert.calledOnce(fakeSettings.app);
document.head.removeChild(link); assert.calledWith(fakeSettings.app, window_.document);
}); });
context("when there's an application/annotator+html <link>", function() {
it("returns the <link>'s href as config.app", function() { it("returns the <link>'s href as config.app", function() {
assert.equal(configFrom(window).app, link.href); assert.equal(configFrom(fakeWindow()).app, 'IFRAME_URL');
}); });
}); });
context("when there's no application/annotator+html <link>", function() { context("when there's no application/annotator+html <link>", function() {
it('throws a TypeError', function() { beforeEach('remove the application/annotator+html <link>', function() {
var window_ = fakeWindow(); fakeSettings.app.throws(new Error("there's no link"));
window_.document.querySelector.returns(null); });
assert.throws(function() { configFrom(window_); }, TypeError); it('throws an error', function() {
assert.throws(
function() { configFrom(fakeWindow()); },
"there's no link"
);
}); });
}); });
...@@ -231,46 +229,50 @@ describe('annotator.config', function() { ...@@ -231,46 +229,50 @@ describe('annotator.config', function() {
}); });
it('ignores the host page config on chrome', function() { it('ignores the host page config on chrome', function() {
var window_ = fakeWindow('chrome-extension://abcdef'); fakeSettings.app.returns('chrome-extension://abcdef');
var currConfig = configFrom(window_);
assert.equal(currConfig.app, 'chrome-extension://abcdef'); var config = configFrom(fakeWindow());
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(currConfig.foo); assert.equal(config.app, 'chrome-extension://abcdef');
assert.equal(config.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(config.foo);
}); });
it('ignores the host page config on firefox', function() { it('ignores the host page config on firefox', function() {
var window_ = fakeWindow('moz-extension://abcdef'); fakeSettings.app.returns('moz-extension://abcdef');
var currConfig = configFrom(window_);
var config = configFrom(fakeWindow());
assert.equal(currConfig.app, 'moz-extension://abcdef'); assert.equal(config.app, 'moz-extension://abcdef');
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID'); assert.equal(config.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(currConfig.foo); assert.isUndefined(config.foo);
}); });
it('ignores the host page config on edge', function() { it('ignores the host page config on edge', function() {
var window_ = fakeWindow('ms-browser-extension://abcdef'); fakeSettings.app.returns('ms-browser-extension://abcdef');
var currConfig = configFrom(window_);
assert.equal(currConfig.app, 'ms-browser-extension://abcdef'); var config = configFrom(fakeWindow());
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(currConfig.foo); assert.equal(config.app, 'ms-browser-extension://abcdef');
assert.equal(config.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(config.foo);
}); });
}); });
context('when the client is not injected by the browser extension', function() { context('when the client is not injected by the browser extension', function() {
beforeEach(function() { beforeEach('configure an embedded client', function() {
fakeSettings.annotations.returns('SOME_ANNOTATION_ID'); fakeSettings.app.returns('https://hypothes.is/app.html');
fakeSharedSettings.jsonConfigsFrom.returns({foo: 'bar'});
}); });
it('does not ignore the host page config', function() { it('does not ignore the host page config', function() {
var window_ = fakeWindow('SOME_HREF'); fakeSettings.annotations.returns('SOME_ANNOTATION_ID');
var currConfig = configFrom(window_); fakeSharedSettings.jsonConfigsFrom.returns({foo: 'bar'});
assert.equal(currConfig.app, 'SOME_HREF'); var config = configFrom(fakeWindow());
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.equal(currConfig.foo, 'bar'); assert.equal(config.app, 'https://hypothes.is/app.html');
assert.equal(config.annotations, 'SOME_ANNOTATION_ID');
assert.equal(config.foo, 'bar');
}); });
}); });
}); });
...@@ -3,6 +3,81 @@ ...@@ -3,6 +3,81 @@
var settings = require('../settings'); var settings = require('../settings');
describe('annotation.config.settings', function() { describe('annotation.config.settings', function() {
describe('#app', function() {
function appendLinkToDocument(href) {
var link = document.createElement('link');
link.type = 'application/annotator+html';
if (href) {
link.href = href;
}
document.head.appendChild(link);
return link;
}
context("when there's an application/annotator+html link", function() {
var link;
beforeEach('add an application/annotator+html <link>', function() {
link = appendLinkToDocument('http://example.com/app.html');
});
afterEach('tidy up the link', function() {
document.head.removeChild(link);
});
it('returns the href from the link', function() {
assert.equal(settings.app(document), 'http://example.com/app.html');
});
});
context('when there are multiple annotator+html links', function() {
var link1;
var link2;
beforeEach('add two links to the document', function() {
link1 = appendLinkToDocument('http://example.com/app1');
link2 = appendLinkToDocument('http://example.com/app2');
});
afterEach('tidy up the links', function() {
document.head.removeChild(link1);
document.head.removeChild(link2);
});
it('returns the href from the first one', function() {
assert.equal(settings.app(document), 'http://example.com/app1');
});
});
context('when the annotator+html link has no href', function() {
var link;
beforeEach('add an application/annotator+html <link> with no href', function() {
link = appendLinkToDocument();
});
afterEach('tidy up the link', function() {
document.head.removeChild(link);
});
it('throws an error', function() {
assert.throws(
function() { settings.app(document); },
'application/annotator+html link has no href'
);
});
});
context("when there's no annotator+html link", function() {
it('throws an error', function() {
assert.throws(
function() { settings.app(document); },
'No application/annotator+html link in the document'
);
});
});
});
describe('#annotations', function() { describe('#annotations', function() {
[ [
{ {
......
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