UNPKG

axe-core

Version:

Accessibility engine for automated Web UI testing

471 lines (406 loc) • 12.2 kB
describe('axe.utils.respondable', function () { 'use strict'; var mockUUID; var originalUUID; var getMockUUID = function () { return mockUUID; }; var version; var fixture = document.querySelector('#fixture'); beforeEach(function () { version = axe.version; originalUUID = window.uuid.v1; window.uuid.v1 = getMockUUID; mockUUID = originalUUID(); }); afterEach(function () { window.uuid.v1 = originalUUID; axe.version = version; fixture.innerHTML = ''; }); it('should be a function', function () { assert.isFunction(axe.utils.respondable); }); it('should accept 5 parameters', function () { assert.lengthOf(axe.utils.respondable, 5); }); it('should call `postMessage` on first parameter', function () { var success = false; var win = { postMessage: function () { success = true; } }; axe.utils.respondable(win, 'batman', 'nananana'); assert.isTrue(success); }); it('should stringify message', function (done) { var win = { postMessage: function (msg) { assert.isString(msg); done(); } }; axe.utils.respondable(win, 'batman', { derp: true }); }); it('should add the `topic` and `message` the message', function (done) { var win = { postMessage: function (msg) { msg = JSON.parse(msg); assert.equal(msg.topic, 'batman'); assert.isTrue(msg._respondable); done(); } }; axe.utils.respondable(win, 'batman', 'nananana'); }); it('should add the `keepalive`', function (done) { var win = { postMessage: function (msg) { msg = JSON.parse(msg); assert.equal(msg._keepalive, 'batman'); done(); } }; axe.utils.respondable(win, 'superman', 'spidey', 'batman'); }); it('should add `_respondable` to the message', function (done) { var win = { postMessage: function (msg) { msg = JSON.parse(msg); assert.equal(msg._respondable, true); done(); } }; axe.utils.respondable(win, 'batman', 'nananana'); }); it('should create a uuid.v1 (time-based uuid)', function () { var UUID = 'heheeh im a uuid'; var win = { postMessage: function (msg) { msg = JSON.parse(msg); assert.equal(msg.uuid, UUID); } }; var orig = window.uuid.v1; var success = false; window.uuid.v1 = function () { success = true; return UUID; }; axe.utils.respondable(win, 'batman', 'nananana'); assert.isTrue(success); window.uuid.v1 = orig; }); it('should pass messages that have all required properties', function () { var success = false; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, _source: 'axeAPI.' + axe.version, topic: 'Death star', message: 'Help us Obi-Wan', uuid: mockUUID }); event.source = window; axe.utils.respondable(window, 'Death star', null, true, function (data) { success = true; assert.equal(data, 'Help us Obi-Wan'); }); document.dispatchEvent(event); assert.isTrue(success); }); it('should reject messages if the axe version is different', function () { var success = true; var event = document.createEvent('Event'); axe.version = '1.0.0'; // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, _source: 'axeAPI.2.0.0', topic: 'Death star', message: 'Help us Obi-Wan', uuid: mockUUID }); event.source = window; axe.utils.respondable(window, 'Death star', null, true, function () { success = false; }); document.dispatchEvent(event); assert.isTrue(success); }); it('should reject messages that are that are not strings', function () { var success = true; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = { _respondable: true, topic: 'batman', uuid: mockUUID }; event.source = window; axe.utils.respondable(window, 'batman', 'nananana', true, function () { success = false; }); document.dispatchEvent(event); assert.isTrue(success); }); it('should reject messages that are invalid stringified objects', function () { var success = true; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, topic: 'batman', uuid: mockUUID }) + 'joker tricks!'; event.source = window; axe.utils.respondable(window, 'batman', 'nananana', true, function () { success = false; }); document.dispatchEvent(event); assert.isTrue(success); }); it('should reject messages that do not have a uuid', function () { var success = true; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = '{ "_respondable": true, "topic": "batman" }'; event.data = JSON.stringify({ _respondable: true, topic: 'batman' }); event.source = window; axe.utils.respondable(window, 'batman', 'nananana', true, function () { success = false; }); document.dispatchEvent(event); assert.isTrue(success); }); it('should reject messages that do not have a matching uuid', function () { var success = true; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = '{ "_respondable": true, "topic": "batman", "uuid": "12" }'; event.data = JSON.stringify({ _respondable: true, topic: 'batman', uuid: 'not-' + mockUUID }); event.source = window; axe.utils.respondable(window, 'batman', 'nananana', true, function () { success = false; }); document.dispatchEvent(event); assert.isTrue(success); }); it('should reject messages that do not have `_respondable: true`', function () { var success = true; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = '{ "uuid": "48", "topic": "batman" }'; event.data = JSON.stringify({ topic: 'batman', uuid: mockUUID }); event.source = window; axe.utils.respondable(window, 'batman', 'nananana', true, function () { success = false; }); document.dispatchEvent(event); assert.isTrue(success); }); it('should throw if an error message was send', function () { var success = false; var event = document.createEvent('Event'); // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, _source: 'axeAPI.' + axe.version, topic: 'Death star', error: { name: 'ReferenceError', message: 'The exhaust port is open!', trail: '... boom' }, uuid: mockUUID }); event.source = window; axe.utils.respondable(window, 'Death star', null, true, function (data) { success = true; assert.instanceOf(data, ReferenceError); assert.equal(data.message, 'The exhaust port is open!'); }); document.dispatchEvent(event); assert.isTrue(success); }); it('should create an Error if an invalid error type is passed', function () { var success = false; var event = document.createEvent('Event'); window.evil = function () {}; // Define that the event name is 'build'. event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, _source: 'axeAPI.' + axe.version, topic: 'Death star', error: { name: 'evil', message: 'The exhaust port is open!', trail: '... boom' }, uuid: mockUUID }); event.source = window; axe.utils.respondable(window, 'Death star', null, true, function (data) { success = true; assert.instanceOf(data, Error); assert.equal(data.message, 'The exhaust port is open!'); }); document.dispatchEvent(event); assert.isTrue(success); window.evil = undefined; }); it('uses respondable.isInFrame() to check if the page is in a frame or not', function() { assert.equal(axe.utils.respondable.isInFrame(), !!window.frameElement); assert.isFalse(axe.utils.respondable.isInFrame({ frameElement: null })); assert.isTrue(axe.utils.respondable.isInFrame({ frameElement: document.createElement('iframe') })); }); describe('subscribe', function () { it('should be a function', function () { assert.isFunction(axe.utils.respondable.subscribe); }); it('should receive messages', function (done) { var expected = null; axe.utils.respondable.subscribe('catman', function (data) { assert.equal(data, expected); if (data === 'yay') { done(); } }); axe.utils.respondable(window, 'catman', null, undefined, function (data, keepalive, respond) { assert.isNull(data); setTimeout(function () { respond('yay'); expected = 'yay'; }, 0); }); }); it('should propagate the keepalive setting', function (done) { var expected = null; axe.utils.respondable.subscribe('catman', function (data, keepalive) { assert.equal(keepalive, expected); if (data === 'yayyay') { done(); } }); axe.utils.respondable(window, 'catman', null, undefined, function (data, keepalive, respond) { assert.isNull(data); setTimeout(function () { expected = 'keepy'; respond('yayyay', expected); }, 0); }); }); it('should allow multiple responses when keepalive', function (done) { var expected = 2; var called = 0; axe.utils.respondable.subscribe('catman', function (data) { if (data === 'yayyayyay') { called += 1; if (called === expected) { done(); } } }); axe.utils.respondable(window, 'catman', null, undefined, function (data, keepalive, respond) { assert.isNull(data); setTimeout(function () { respond('yayyayyay', true); }, 0); setTimeout(function () { respond('yayyayyay', true); }, 100); }); }); it('does not trigger for error messages', function (done) { var published = false; axe.utils.respondable.subscribe('catman', function () { published = true; }); var err = new ReferenceError('whoopsy'); axe.utils.respondable(window, 'catman', err); setTimeout(function () { assert.ok(!published, 'Error events should not trigger'); done(); }, 10); }); it('returns an error if the subscribe method responds with an error', function (done) { var expected = 'Expected owlman to be batman'; var wait = true; axe.utils.respondable.subscribe('owlman', function (data, keepalive, respond) { wait = false; respond(new TypeError(expected)); }); axe.utils.respondable(window, 'owlman', 'help!', true, function (data) { if (!wait) { assert.instanceOf(data, TypeError); assert.equal(data.message.split(/\n/)[0], expected); done(); } } ); }); it('returns an error if the subscribe method throws', function (done) { var wait = true; var expected = 'Expected owlman to be batman'; axe.utils.respondable.subscribe('owlman', function () { wait = false; throw new TypeError(expected); }); // use keepalive, because we're running on the same window, // otherwise it would delete the response before subscribe // gets to react axe.utils.respondable(window, 'owlman', null, true, function (data) { if (!wait) { assert.instanceOf(data, TypeError); assert.equal(data.message.split(/\n/)[0], expected); done(); } } ); }); it('does not run if the command did not come from the parent iframe', function(done) { var published = false; axe.utils.respondable.subscribe('catman', function () { published = true; }); var frame = document.createElement('iframe'); frame.addEventListener('load', function () { axe._tree = axe.utils.getFlattenedTree(document.documentElement); setTimeout(function () { assert.ok(!published, 'Subscriber should not be called'); done(); }, 10); }); frame.id = 'level0'; frame.src = '../mock/frames/send-command-to-parent.html'; fixture.appendChild(frame); }); }); });