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';
*/
function configFrom(window_) {
var config = {
app: window_.
document.querySelector('link[type="application/annotator+html"]').href,
app: settings.app(window_.document),
};
var chromeExt = 'chrome-extension://';
var mozExt = 'moz-extension://';
var edgeExt = 'ms-browser-extension://';
......
'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.
*
......@@ -42,6 +71,7 @@ function query(url) {
}
module.exports = {
app: app,
annotations: annotations,
query: query,
};
'use strict';
var proxyquire = require('proxyquire');
var util = require('../../../shared/test/util');
var fakeSharedSettings = {};
var fakeSettings = {};
var configFrom = proxyquire('../index', {
var configFrom = proxyquire('../index', util.noCallThru({
'./settings': fakeSettings,
'../../shared/settings': fakeSharedSettings,
});
}));
var sandbox = sinon.sandbox.create();
function fakeWindow(someHref) {
var href = someHref || 'LINK_HREF';
function fakeWindow() {
return {
document: {
querySelector: sinon.stub().returns({href: href}),
},
document: 'THE_DOCUMENT',
location: {href: 'LOCATION_HREF'},
};
}
......@@ -32,6 +29,7 @@ describe('annotator.config', function() {
});
beforeEach('reset fakeSettings', function() {
fakeSettings.app = sinon.stub().returns('IFRAME_URL');
fakeSettings.annotations = sinon.stub();
fakeSettings.query = sinon.stub();
});
......@@ -40,31 +38,31 @@ describe('annotator.config', function() {
sandbox.restore();
});
context("when there's an application/annotator+html <link>", function() {
var link;
it('gets the config.app setting', function() {
var window_ = fakeWindow();
beforeEach('add an application/annotator+html <link>', function() {
link = document.createElement('link');
link.type = 'application/annotator+html';
link.href = 'http://example.com/link';
document.head.appendChild(link);
});
configFrom(window_);
afterEach('tidy up the link', function() {
document.head.removeChild(link);
});
assert.calledOnce(fakeSettings.app);
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() {
assert.equal(configFrom(window).app, link.href);
assert.equal(configFrom(fakeWindow()).app, 'IFRAME_URL');
});
});
context("when there's no application/annotator+html <link>", function() {
it('throws a TypeError', function() {
var window_ = fakeWindow();
window_.document.querySelector.returns(null);
beforeEach('remove the application/annotator+html <link>', function() {
fakeSettings.app.throws(new Error("there's no link"));
});
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() {
});
it('ignores the host page config on chrome', function() {
var window_ = fakeWindow('chrome-extension://abcdef');
var currConfig = configFrom(window_);
fakeSettings.app.returns('chrome-extension://abcdef');
assert.equal(currConfig.app, 'chrome-extension://abcdef');
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(currConfig.foo);
var config = configFrom(fakeWindow());
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() {
var window_ = fakeWindow('moz-extension://abcdef');
var currConfig = configFrom(window_);
fakeSettings.app.returns('moz-extension://abcdef');
var config = configFrom(fakeWindow());
assert.equal(currConfig.app, 'moz-extension://abcdef');
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(currConfig.foo);
assert.equal(config.app, 'moz-extension://abcdef');
assert.equal(config.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(config.foo);
});
it('ignores the host page config on edge', function() {
var window_ = fakeWindow('ms-browser-extension://abcdef');
var currConfig = configFrom(window_);
fakeSettings.app.returns('ms-browser-extension://abcdef');
assert.equal(currConfig.app, 'ms-browser-extension://abcdef');
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.isUndefined(currConfig.foo);
var config = configFrom(fakeWindow());
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() {
beforeEach(function() {
fakeSettings.annotations.returns('SOME_ANNOTATION_ID');
fakeSharedSettings.jsonConfigsFrom.returns({foo: 'bar'});
beforeEach('configure an embedded client', function() {
fakeSettings.app.returns('https://hypothes.is/app.html');
});
it('does not ignore the host page config', function() {
var window_ = fakeWindow('SOME_HREF');
var currConfig = configFrom(window_);
fakeSettings.annotations.returns('SOME_ANNOTATION_ID');
fakeSharedSettings.jsonConfigsFrom.returns({foo: 'bar'});
assert.equal(currConfig.app, 'SOME_HREF');
assert.equal(currConfig.annotations, 'SOME_ANNOTATION_ID');
assert.equal(currConfig.foo, 'bar');
var config = configFrom(fakeWindow());
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 @@
var settings = require('../settings');
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() {
[
{
......
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