Extract a new configFuncSettingsFrom() function

Extract some code for reading config settings from a
window.hypothesisConfig() function out of
annotator.config.config#configFrom() and into a new, separate function
annotator.config.settings#configFuncSettingsFrom().

This function can now be unit-tested separately and the long
configFrom() function gets a bit shorter.
parent a133df50
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
var settings = require('./settings'); var settings = require('./settings');
var sharedSettings = require('../../shared/settings'); var sharedSettings = require('../../shared/settings');
var docs = 'https://h.readthedocs.io/en/latest/embedding.html';
/** /**
* Reads the Hypothesis configuration from the environment. * Reads the Hypothesis configuration from the environment.
* *
...@@ -53,14 +51,7 @@ function configFrom(window_) { ...@@ -53,14 +51,7 @@ function configFrom(window_) {
err); err);
} }
// Parse config from `window.hypothesisConfig` function Object.assign(config, settings.configFuncSettingsFrom(window_));
if (window_.hasOwnProperty('hypothesisConfig')) {
if (typeof window_.hypothesisConfig === 'function') {
Object.assign(config, window_.hypothesisConfig());
} else {
throw new TypeError('hypothesisConfig must be a function, see: ' + docs);
}
}
// Convert legacy keys/values in config to corresponding current // Convert legacy keys/values in config to corresponding current
// configuration. // configuration.
......
...@@ -41,7 +41,44 @@ function query(url) { ...@@ -41,7 +41,44 @@ function query(url) {
return null; return null;
} }
/**
* Return an object containing config settings from window.hypothesisConfig().
*
* Return an object containing config settings returned by the
* window.hypothesisConfig() function provided by the host page:
*
* {
* fooSetting: 'fooValue',
* barSetting: 'barValue',
* ...
* }
*
* If there's no window.hypothesisConfig() function then return {}.
*
* If there is a window.hypothesisConfig but it isn't a function then throw an
* error.
*
* @param {Window} window_ - The window to search for a hypothesisConfig() function
* @return {Object} - Any config settings returned by hypothesisConfig()
*
* @throws {TypeError} - If window.hypothesisConfig() isn't a function
*
*/
function configFuncSettingsFrom(window_) {
if (!window_.hasOwnProperty('hypothesisConfig')) {
return {};
}
if (typeof window_.hypothesisConfig !== 'function') {
var docs = 'https://h.readthedocs.io/en/latest/embedding.html';
throw new TypeError('hypothesisConfig must be a function, see: ' + docs);
}
return window_.hypothesisConfig();
}
module.exports = { module.exports = {
annotations: annotations, annotations: annotations,
query: query, query: query,
configFuncSettingsFrom: configFuncSettingsFrom,
}; };
...@@ -37,6 +37,7 @@ describe('annotator.config', function() { ...@@ -37,6 +37,7 @@ describe('annotator.config', function() {
beforeEach('reset fakeSettings', function() { beforeEach('reset fakeSettings', function() {
fakeSettings.annotations = sinon.stub(); fakeSettings.annotations = sinon.stub();
fakeSettings.query = sinon.stub(); fakeSettings.query = sinon.stub();
fakeSettings.configFuncSettingsFrom = sinon.stub().returns({});
}); });
afterEach('reset the sandbox', function() { afterEach('reset the sandbox', function() {
...@@ -109,51 +110,42 @@ describe('annotator.config', function() { ...@@ -109,51 +110,42 @@ describe('annotator.config', function() {
}); });
}); });
context("when there's a window.hypothesisConfig() function", function() { it('gets config settings from window.hypothesisConfig()', function() {
it('reads arbitrary settings from hypothesisConfig() into config', function() {
var window_ = fakeWindow(); var window_ = fakeWindow();
window_.hypothesisConfig = sinon.stub().returns({foo: 'bar'});
var config = configFrom(window_); configFrom(window_);
assert.calledOnce(fakeSettings.configFuncSettingsFrom);
assert.calledWithExactly(fakeSettings.configFuncSettingsFrom, window_);
});
context('when configFuncSettingsFrom() returns an object', function() {
it('reads arbitrary settings from configFuncSettingsFrom() into config', function() {
fakeSettings.configFuncSettingsFrom.returns({foo: 'bar'});
var config = configFrom(fakeWindow());
assert.equal(config.foo, 'bar'); assert.equal(config.foo, 'bar');
}); });
specify('hypothesisConfig() settings override js-hypothesis-config ones', function() { specify('hypothesisConfig() settings override js-hypothesis-config ones', function() {
var window_ = fakeWindow(); fakeSettings.configFuncSettingsFrom.returns({
window_.hypothesisConfig = sinon.stub().returns({
foo: 'fooFromHypothesisConfigFunc'}); foo: 'fooFromHypothesisConfigFunc'});
fakeSharedSettings.jsonConfigsFrom.returns({ fakeSharedSettings.jsonConfigsFrom.returns({
foo: 'fooFromJSHypothesisConfigObj', foo: 'fooFromJSHypothesisConfigObj',
}); });
var config = configFrom(window_); var config = configFrom(fakeWindow());
assert.equal(config.foo, 'fooFromHypothesisConfigFunc'); assert.equal(config.foo, 'fooFromHypothesisConfigFunc');
}); });
context('if hypothesisConfig() returns a non-object value', function() {
it("doesn't add anything into the config", function() {
var window_ = fakeWindow();
window_.hypothesisConfig = sinon.stub().returns(42);
var config = configFrom(window_);
delete config.app; // We don't care about config.app for this test.
assert.deepEqual({}, config);
});
});
}); });
context("when window.hypothesisConfig() isn't a function", function() { context('when configFuncSettingsFrom() throws an error', function() {
it('throws a TypeError', function() { it('throws the same error', function() {
var window_ = fakeWindow(); fakeSettings.configFuncSettingsFrom.throws(new TypeError());
window_.hypothesisConfig = 'notAFunction';
assert.throws( assert.throws(function() { configFrom(fakeWindow()); }, TypeError);
function() { configFrom(window_); }, TypeError,
'hypothesisConfig must be a function, see: https://h.readthedocs.io/en/latest/embedding.html'
);
}); });
}); });
......
...@@ -111,4 +111,35 @@ describe('annotation.config.settings', function() { ...@@ -111,4 +111,35 @@ describe('annotation.config.settings', function() {
}); });
}); });
}); });
describe('#configFuncSettingsFrom', function() {
context("when there's no window.hypothesisConfig() function", function() {
it('returns {}', function() {
var fakeWindow = {};
assert.deepEqual(settings.configFuncSettingsFrom(fakeWindow), {});
});
});
context("when window.hypothesisConfig() isn't a function", function() {
it('throws an error', function() {
var fakeWindow = { hypothesisConfig: 42 };
assert.throws(
function() { settings.configFuncSettingsFrom(fakeWindow); },
TypeError
);
});
});
context('when window.hypothesisConfig() is a function', function() {
it('returns whatever window.hypothesisConfig() returns', function () {
// It just blindly returns whatever hypothesisConfig() returns
// (even if it's not an object).
var fakeWindow = { hypothesisConfig: sinon.stub().returns(42) };
assert.equal(settings.configFuncSettingsFrom(fakeWindow), 42);
});
});
});
}); });
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