-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tests and other tweaks to shared/settings.js #406
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,17 +12,22 @@ function assign(dest, src) { | |
} | ||
|
||
/** | ||
* Return application configuration information from the host page. | ||
* Return a parsed `js-hypothesis-config` object from the document, or `{}`. | ||
* | ||
* Exposes shared application settings, read from script tags with the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also misleading. It's a shared utility function, yes. But "shared application settings" is misleading. Not every setting read from a js-hypothesis-config is actually shared between the three legs of the app (annotator, boot and sidebar), nor is every setting that is shared read from this function. |
||
* class `js-hypothesis-config` which contain JSON content. | ||
* Find all `<script class="js-hypothesis-config">` tags in the given document, | ||
* parse them as JSON, and return the parsed object. | ||
* | ||
* If there are multiple such tags, the configuration from each is merged. | ||
* If there are no `js-hypothesis-config` tags in the document then return | ||
* `{}`. | ||
* | ||
* @param {Document|Element} document - The root element to search for | ||
* <script> settings tags. | ||
* If there are multiple `js-hypothesis-config` tags in the document then merge | ||
* them into a single returned object (when multiple scripts contain the same | ||
* setting names, scripts further down in the document override those further | ||
* up). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've left the exception that this function throws (on invalid JSON) still undocumented, as I intend to send a PR to stop iut from throwing the exception anyway |
||
* | ||
* @param {Document|Element} document - The root element to search. | ||
*/ | ||
function settings(document) { | ||
function jsonConfigsFrom(document) { | ||
var settingsElements = | ||
document.querySelectorAll('script.js-hypothesis-config'); | ||
|
||
|
@@ -33,4 +38,6 @@ function settings(document) { | |
return config; | ||
} | ||
|
||
module.exports = settings; | ||
module.exports = { | ||
jsonConfigsFrom: jsonConfigsFrom, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,33 +2,128 @@ | |
|
||
var settings = require('../settings'); | ||
|
||
function createConfigElement(obj) { | ||
var el = document.createElement('script'); | ||
el.type = 'application/json'; | ||
el.textContent = JSON.stringify(obj); | ||
el.classList.add('js-hypothesis-config'); | ||
el.classList.add('js-settings-test'); | ||
return el; | ||
} | ||
|
||
function removeJSONScriptTags() { | ||
var elements = document.querySelectorAll('.js-settings-test'); | ||
for (var i=0; i < elements.length; i++) { | ||
elements[i].parentNode.removeChild(elements[i]); | ||
} | ||
} | ||
|
||
describe('settings', function () { | ||
afterEach(removeJSONScriptTags); | ||
describe('#jsonConfigsFrom', function() { | ||
var jsonConfigsFrom = settings.jsonConfigsFrom; | ||
|
||
it('reads config from .js-hypothesis-config <script> tags', function () { | ||
document.body.appendChild(createConfigElement({key:'value'})); | ||
assert.deepEqual(settings(document), {key:'value'}); | ||
}); | ||
function appendJSHypothesisConfig(document_, jsonString) { | ||
var el = document_.createElement('script'); | ||
el.type = 'application/json'; | ||
el.textContent = jsonString; | ||
el.classList.add('js-hypothesis-config'); | ||
el.classList.add('js-settings-test'); | ||
document_.body.appendChild(el); | ||
} | ||
|
||
afterEach('remove js-hypothesis-config tags', function() { | ||
var elements = document.querySelectorAll('.js-settings-test'); | ||
for (var i=0; i < elements.length; i++) { | ||
elements[i].remove(); | ||
} | ||
}); | ||
|
||
context('when there are no JSON scripts', function() { | ||
it('returns {}', function() { | ||
assert.deepEqual(jsonConfigsFrom(document), {}); | ||
}); | ||
}); | ||
|
||
context("when there's JSON scripts with no top-level objects", function() { | ||
beforeEach('add JSON scripts with no top-level objects', function() { | ||
appendJSHypothesisConfig(document, 'null'); | ||
appendJSHypothesisConfig(document, '23'); | ||
appendJSHypothesisConfig(document, 'true'); | ||
}); | ||
|
||
it('ignores them', function() { | ||
assert.deepEqual(jsonConfigsFrom(document), {}); | ||
}); | ||
}); | ||
|
||
context("when there's a JSON script with a top-level array", function() { | ||
beforeEach('add a JSON script containing a top-level array', function() { | ||
appendJSHypothesisConfig(document, '["a", "b", "c"]'); | ||
}); | ||
|
||
it('returns the array, parsed into an object', function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should fix this in a separate pr, it should ignore top-level arrays (but log a warning) |
||
assert.deepEqual( | ||
jsonConfigsFrom(document), | ||
{0: 'a', 1: 'b', 2: 'c'} | ||
); | ||
}); | ||
}); | ||
|
||
context("when there's a JSON script with a top-level string", function() { | ||
beforeEach('add a JSON script with a top-level string', function() { | ||
appendJSHypothesisConfig(document, '"hi"'); | ||
}); | ||
|
||
it('returns the string, parsed into an object', function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should fix this in a separate pr, it should ignore top-level strings (but log a warning) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Heh. LOLJS :) |
||
assert.deepEqual(jsonConfigsFrom(document), {0: 'h', 1: 'i'}); | ||
}); | ||
}); | ||
|
||
context("when there's a JSON script containing invalid JSON", function() { | ||
beforeEach('add a JSON script containing invalid JSON', function() { | ||
appendJSHypothesisConfig(document, 'this is not valid json'); | ||
}); | ||
|
||
it('throws a SyntaxError', function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should fix this in a follow up pr: it should log a warning, and ignore the invalid json, not throw |
||
assert.throws( | ||
function() { jsonConfigsFrom(document); }, | ||
SyntaxError | ||
); | ||
}); | ||
}); | ||
|
||
context("when there's a JSON script with an empty object", function() { | ||
beforeEach('add a JSON script containing an empty object', function() { | ||
appendJSHypothesisConfig(document, '{}'); | ||
}); | ||
|
||
it('ignores it', function() { | ||
assert.deepEqual(jsonConfigsFrom(document), {}); | ||
}); | ||
}); | ||
|
||
context("when there's a JSON script containing some settings", function() { | ||
beforeEach('add a JSON script containing some settings', function() { | ||
appendJSHypothesisConfig(document, '{"foo": "FOO", "bar": "BAR"}'); | ||
}); | ||
|
||
it('returns the settings', function() { | ||
assert.deepEqual( | ||
jsonConfigsFrom(document), | ||
{foo: 'FOO', bar: 'BAR'} | ||
); | ||
}); | ||
}); | ||
|
||
context('when there are JSON scripts with different settings', function() { | ||
beforeEach('add some JSON scripts with different settings', function() { | ||
appendJSHypothesisConfig(document, '{"foo": "FOO"}'); | ||
appendJSHypothesisConfig(document, '{"bar": "BAR"}'); | ||
appendJSHypothesisConfig(document, '{"gar": "GAR"}'); | ||
}); | ||
|
||
it('merges them all into one returned object', function() { | ||
assert.deepEqual( | ||
jsonConfigsFrom(document), | ||
{foo: 'FOO', bar: 'BAR', gar: 'GAR'} | ||
); | ||
}); | ||
}); | ||
|
||
context('when multiple JSON scripts contain the same setting', function() { | ||
beforeEach('add some JSON scripts with different settings', function() { | ||
appendJSHypothesisConfig(document, '{"foo": "first"}'); | ||
appendJSHypothesisConfig(document, '{"foo": "second"}'); | ||
appendJSHypothesisConfig(document, '{"foo": "third"}'); | ||
}); | ||
|
||
it('merges settings from all config <script> tags', function () { | ||
document.body.appendChild(createConfigElement({a: 1})); | ||
document.body.appendChild(createConfigElement({b: 2})); | ||
assert.deepEqual(settings(document), {a: 1, b: 2}); | ||
specify('settings from later in the page override ones from earlier', function() { | ||
assert.equal(jsonConfigsFrom(document).foo, 'third'); | ||
}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was actually wrong - the function isn't always used to read settings from the host page