diff --git a/package.json b/package.json index 0d39eb52f8c..4a7bd218b09 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "vjlofvhjfgm", "version": "0.0.1", "devDependencies": { + "es6-shim": "^0.34.2", "istanbul": "^0.4.2", "jasmine": "^2.4.1", "jsdom": "^3.1.2" diff --git a/src/core.json b/src/core.json index 24a753a2fc8..c071a567f11 100644 --- a/src/core.json +++ b/src/core.json @@ -1,3 +1,5 @@ [ - "core/context.js" + "core/context.js", + "core/event.js", + "core/dynamic.js" ] diff --git a/src/core/event.js b/src/core/event.js index 5e5b11a10c0..c681ab1ddfc 100644 --- a/src/core/event.js +++ b/src/core/event.js @@ -15,11 +15,14 @@ * limitations under the License. */ +var GLOBAL = global || this; +var X = GLOBAL.X; + /** Publish and Subscribe Event Notification Service. **/ // MODEL({ // name: 'EventService', -var EventService = { + X.EventService = { // constants: { // /** Used as topic suffix to specify broadcast to all sub-topics. **/ @@ -30,7 +33,7 @@ var EventService = { // /** Create a "one-time" listener which unsubscribes itself after its first invocation. **/ oneTime: function(listener) { return function() { - listener.apply(this, EventService.argsToArray(arguments)); + listener.apply(this, X.EventService.argsToArray(arguments)); arguments[2](); // the unsubscribe fn }; }, @@ -38,7 +41,7 @@ var EventService = { /** Log all listener invocations to console. **/ consoleLog: function(listener) { return function() { - var args = EventService.argsToArray(arguments); + var args = X.EventService.argsToArray(arguments); console.log(args); listener.apply(this, args); @@ -53,7 +56,8 @@ var EventService = { * the smallest delay that humans aren't able to perceive. **/ merged: function(listener, opt_delay, opt_X) { - var setTimeoutX = ( opt_X && opt_X.setTimeout ) || setTimeout; + var X = opt_X || GLOBAL.X; + var setTimeoutX = X.setTimeout; var delay = opt_delay || 16; return function() { @@ -67,7 +71,7 @@ var EventService = { triggered = true; setTimeoutX(function() { triggered = false; - var args = EventService.argsToArray(lastArgs); + var args = X.EventService.argsToArray(lastArgs); lastArgs = null; listener.apply(this, args); }, delay); @@ -147,7 +151,7 @@ var EventService = { }, /** convenience method to turn 'arguments' into a real array */ argsToArray: function(args) { - return EventService.appendArguments([], args, 0); + return GLOBAL.X.EventService.appendArguments([], args, 0); }, // }); @@ -155,7 +159,7 @@ var EventService = { // MODEL({ // name: 'EventPublisher', -var EventPublisher = { +X.EventPublisher = { // properties: [ subs_: null, // inited to {} when first used @@ -176,7 +180,7 @@ var EventPublisher = { if ( ! map ) return false; // if nothing to check, fail if ( this.hasDirectListeners_(map) ) return true; // if any listeners at this level, we're good var topic = opt_topic[t]; - if ( topic == EventService.WILDCARD ) { + if ( topic == X.EventService.WILDCARD ) { // if a wildcard is specified, find any listener at all return this.hasAnyListeners_(map); } @@ -197,13 +201,13 @@ var EventPublisher = { this.subs_, 0, topic, - EventService.appendArguments([this, topic, null], arguments, 1)) : // null: to be replaced with the unsub object + X.EventService.appendArguments([this, topic, null], arguments, 1)) : // null: to be replaced with the unsub object 0; }, /** Publish asynchronously. **/ publishAsync: function(topic) { - var args = EventService.argsToArray(arguments); + var args = X.EventService.argsToArray(arguments); var self = this; setTimeout( function() { self.publish.apply(self, args); }, 0); }, @@ -269,7 +273,7 @@ var EventPublisher = { var t = topic[topicIndex]; // wildcard publish, so notify all sub-topics, instead of just one - if ( t == EventService.WILDCARD ) { + if ( t == X.EventService.WILDCARD ) { return this.notifyListeners_(topic, map, msg, topic.slice(0, topicIndex-1)); } if ( t ) count += this.pub_(map[t], topicIndex+1, topic, msg); @@ -367,15 +371,15 @@ var EventPublisher = { //}); -} +}; // /** Extend EventPublisher with support for dealing with property-change notification. **/ // MODEL({ // name: 'PropertyChangePublisher', -var PropertyChangePublisher = { +X.PropertyChangePublisher = { // extends: 'EventPublisher', - __proto__: EventPublisher, + __proto__: X.EventPublisher, // constants: { // /** Root for property topics. **/ @@ -412,7 +416,7 @@ var PropertyChangePublisher = { /** Indicates that one or more unspecified properties have changed. **/ globalChange: function() { - this.publish(this.propertyTopic(EventService.WILDCARD), null, null); + this.publish(this.propertyTopic(X.EventService.WILDCARD), null, null); }, /** Adds a listener for all property changes. **/ @@ -450,9 +454,4 @@ var PropertyChangePublisher = { // // } // } // }); -} - -exports.EventPublisher = EventPublisher; -exports.EventService = EventService; -exports.PropertyChangePublisher = PropertyChangePublisher; - +}; diff --git a/test/helpers/Help.js b/test/helpers/Help.js deleted file mode 100644 index 149a60b2035..00000000000 --- a/test/helpers/Help.js +++ /dev/null @@ -1,2 +0,0 @@ -var GLOBAL = global || this; -GLOBAL.Help = jasmine.Help = function() {}; diff --git a/test/helpers/interop.js b/test/helpers/interop.js new file mode 100644 index 00000000000..417a45fb3a7 --- /dev/null +++ b/test/helpers/interop.js @@ -0,0 +1,63 @@ +var GLOBAL = global || this; +var NODEJS = typeof module !== 'undefined' && module.exports; + +if (NODEJS) require('es6-shim'); + +// TODO(markdittmer): Make the non-NodeJS case match with wherever we expect +// Jasmine's SpecRunner.html. +var SRC_DIR = NODEJS ? process.cwd() + '/src' : 'src'; + +GLOBAL.loadSrcScript = function(path) { + return new Promise(function(resolve, reject) { + if (NODEJS) { + var requirePath = SRC_DIR + '/' + path; + var success = true; + try { + require(requirePath); + } catch (e) { + success = false; + reject(e); + } + if (success) resolve(); + } else { + var document = GLOBAL.document; + var script = document.createElement('script'); + script.addEventListener('load', function() { resolve(); }); + script.addEventListener('error', function() { reject(); }); + script.setAttribute('src', SRC_DIR + '/' + path + '.js'); + document.head.appendChild(script); + } + }); +}; + +GLOBAL.readSrcFile = function(path, callback) { + return new Promise(function(resolve, reject) { + if (NODEJS) { + var fileContents = require('fs').readFileSync(SRC_DIR + '/' + path); + resolve(fileContents); + } else { + var xhr = new XMLHttpRequest(); + xhr.open(SRC_DIR + '/' + path); + xhr.addEventListener('load', function() { resolve(xhr.responseText); }); + xhr.addEventListener('error', function(error) { reject(error); }); + xhr.send(); + } + }); +}; + +var coreFileNamesPromise = + GLOBAL.readSrcFile('core.json').then(function(coreFilesJSON) { + return JSON.parse(coreFilesJSON); + }); + +GLOBAL.loadCoreTo = function(lastCoreFileName) { + return coreFileNamesPromise.then(function(coreFileNames) { + var cont = true; + return coreFileNames.reduce(function(promise, coreFileName) { + if (!cont) return promise; + promise = promise.then(GLOBAL.loadSrcScript(coreFileName)); + if (coreFileName === lastCoreFileName) cont = false; + return promise; + }, Promise.resolve()); + }); +}; diff --git a/test/js/core/context.js b/test/js/core/context.js index bedcd71d81a..81586df7abb 100644 --- a/test/js/core/context.js +++ b/test/js/core/context.js @@ -1,7 +1,9 @@ var GLOBAL = global || this; -require('../../../src/core/context'); + +var corePromise = GLOBAL.loadCoreTo('core/context.js'); describe('ConteXt object', function() { + beforeEach(function(done) { corePromise.then(done); }); it('Expect global context to exist', function() { expect(GLOBAL.X).toBeTruthy(); diff --git a/test/js/core/event.js b/test/js/core/event.js index 6b1f6bb8bd5..633d34af29e 100644 --- a/test/js/core/event.js +++ b/test/js/core/event.js @@ -1,22 +1,27 @@ var GLOBAL = global || this; -var _events = require('../../../src/core/event.js'); -var EventPublisher = _events.EventPublisher; -var EventService = _events.EventService; -var PropertyChangePublisher = _events.PropertyChangePublisher; +var corePromise = GLOBAL.loadCoreTo('core/event.js'); +var beforeEachTest = function(callback) { + return beforeEach(function(done) { + corePromise.then(function() { + callback(); + done(); + }); + }); +}; describe('EventService.oneTime', function() { var ep; var listener; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener = function(publisher, topic, unsub) { listener.last_topic = topic; listener.last_unsub = unsub; listener.last_args = arguments; listener.count += 1; - } + }; listener.count = 0; }); afterEach(function() { @@ -25,7 +30,7 @@ describe('EventService.oneTime', function() { }); it('removes itself after one invokation', function() { - var one = EventService.oneTime(listener); + var one = GLOBAL.X.EventService.oneTime(listener); ep.subscribe(['simple'], one); @@ -44,8 +49,8 @@ describe('EventService.consoleLog', function() { var ep; var listener; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener = function(publisher, topic, unsub) { listener.last_topic = topic; listener.last_unsub = unsub; @@ -60,7 +65,7 @@ describe('EventService.consoleLog', function() { }); it('logs ok', function() { - var logger = EventService.consoleLog(listener); + var logger = GLOBAL.X.EventService.consoleLog(listener); ep.subscribe(['simple'], logger); @@ -76,8 +81,8 @@ describe('EventService.merged', function() { var ep; var listener; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener = function(publisher, topic, unsub) { listener.last_topic = topic; listener.last_unsub = unsub; @@ -94,7 +99,7 @@ describe('EventService.merged', function() { }); it('merges with default parameters', function() { - var merged = EventService.merged(listener); + var merged = GLOBAL.X.EventService.merged(listener); ep.subscribe(['simple'], merged); @@ -111,7 +116,7 @@ describe('EventService.merged', function() { }); it('merges with delay specified', function() { - var merged = EventService.merged(listener, 1300); + var merged = GLOBAL.X.EventService.merged(listener, 1300); ep.subscribe(['simple'], merged); @@ -129,8 +134,8 @@ describe('EventService.merged', function() { }); it('merges with opt_X specified', function() { - var X = { setTimeout: setTimeout }; - var merged = EventService.merged(listener, 1300, X); + var X = GLOBAL.X.sub(); + var merged = GLOBAL.X.EventService.merged(listener, 1300, X); ep.subscribe(['simple'], merged); @@ -146,6 +151,7 @@ describe('EventService.merged', function() { it('unsubscribes when requested', function() { + var EventService = GLOBAL.X.EventService; var merged = EventService.merged(EventService.oneTime(listener)); ep.subscribe(['simple'], merged); @@ -189,8 +195,8 @@ describe('EventService.merged', function() { describe('EventPublisher.hasListeners()', function() { var ep; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); }); afterEach(function() { ep = null; @@ -232,7 +238,7 @@ describe('EventPublisher.hasListeners()', function() { }); it('reports correctly for a multi-level topic with a partial-match listener', function() { - ep.subs_ = { 'the' : { 'cake': { 'is' : { null: [] }, } }, null: ['myFakeListener'] }; + ep.subs_ = { 'the' : { 'cake': { 'is' : { null: [] } } }, null: ['myFakeListener'] }; expect(ep.hasListeners(['the','cake'])).toBe(true); }); @@ -248,16 +254,16 @@ describe('EventPublisher.hasListeners()', function() { it('reports correctly for a multi-level topic with a wildcard', function() { ep.subs_ = { 'the' : { 'cake': { 'is' : { null: ['myFakeListener'] } } } }; - expect(ep.hasListeners(['the', EventService.WILDCARD])).toBe(true); + expect(ep.hasListeners(['the', GLOBAL.X.EventService.WILDCARD])).toBe(true); }); it('reports correctly for a root level wildcard', function() { ep.subs_ = { 'the' : { 'cake': { 'is' : { null: ['myFakeListener'] } } } }; - expect(ep.hasListeners([EventService.WILDCARD])).toBe(true); + expect(ep.hasListeners([GLOBAL.X.EventService.WILDCARD])).toBe(true); }); it('reports correctly for a given topic but no listeners', function() { - expect(ep.hasListeners([EventService.WILDCARD])).toBe(false); + expect(ep.hasListeners([GLOBAL.X.EventService.WILDCARD])).toBe(false); }); }); @@ -266,8 +272,8 @@ describe('EventPublisher.subscribe()/.sub_()', function() { var ep; var listener; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener = function(publisher, topic, unsub) { listener.last_topic = topic; listener.last_unsub = unsub; @@ -303,10 +309,10 @@ describe('EventPublisher.subscribe()/.sub_()', function() { expect(ep.hasListeners(['two'])).toBe(true); }); -// it('subscribes with a wildcard', function() { // not valid case TODO -// ep.subscribe([EventService.WILDCARD], listener); -// expect(ep.hasListeners()).toBe(true); -// }); + // it('subscribes with a wildcard', function() { // not valid case TODO + // ep.subscribe([EventService.WILDCARD], listener); + // expect(ep.hasListeners()).toBe(true); + // }); }); describe('EventPublisher.publish()/.pub_()', function() { @@ -314,8 +320,8 @@ describe('EventPublisher.publish()/.pub_()', function() { var listener1; var listener2; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener1 = function(publisher, topic, unsub) { listener1.last_publisher = publisher; listener1.last_topic = topic; @@ -384,8 +390,8 @@ describe('EventPublisher.lazyPublish()', function() { var listener1; var argFn; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener1 = function(publisher, topic, unsub) { listener1.last_publisher = publisher; listener1.last_topic = topic; @@ -422,8 +428,8 @@ describe('EventPublisher.unsubscribe()/unsub_()', function() { var listener1; var listener2; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener1 = function(publisher, topic, unsub) { listener1.last_publisher = publisher; listener1.last_topic = topic; @@ -501,8 +507,8 @@ describe('EventPublisher listener-unsubscribe', function() { var listener1; var listener2; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener1 = function(publisher, topic, unsub) { listener1.last_publisher = publisher; listener1.last_topic = topic; @@ -558,8 +564,8 @@ describe('EventPublisher async-publish', function() { var ep; var listener1; - beforeEach(function() { - ep = Object.create(EventPublisher); + beforeEachTest(function() { + ep = Object.create(GLOBAL.X.EventPublisher); listener1 = function(publisher, topic, unsub) { listener1.last_publisher = publisher; listener1.last_topic = topic; @@ -590,11 +596,11 @@ describe('EventPublisher async-publish', function() { describe('PropertyChangePublisher.add/removePropertyListener()', function() { - var ep; var listener; + var pcp; - beforeEach(function() { - pcp = Object.create(PropertyChangePublisher); + beforeEachTest(function() { + pcp = Object.create(GLOBAL.X.PropertyChangePublisher); listener = function(publisher, topic, unsub) { listener.last_topic = topic; listener.last_unsub = unsub; @@ -608,35 +614,35 @@ describe('PropertyChangePublisher.add/removePropertyListener()', function() { it('adds/removes a listener for a property', function() { pcp.addPropertyListener('myProp', listener); - expect(pcp.hasListeners([PropertyChangePublisher.PROPERTY_TOPIC, 'myProp'])).toBe(true); + expect(pcp.hasListeners([GLOBAL.X.PropertyChangePublisher.PROPERTY_TOPIC, 'myProp'])).toBe(true); pcp.removePropertyListener('myProp', listener); - expect(pcp.hasListeners([PropertyChangePublisher.PROPERTY_TOPIC, 'myProp'])).toBe(false); + expect(pcp.hasListeners([GLOBAL.X.PropertyChangePublisher.PROPERTY_TOPIC, 'myProp'])).toBe(false); }); it('adds/removes a listener for all property changes', function() { pcp.addPropertyListener(null, listener); - expect(pcp.hasListeners([PropertyChangePublisher.PROPERTY_TOPIC])).toBe(true); + expect(pcp.hasListeners([GLOBAL.X.PropertyChangePublisher.PROPERTY_TOPIC])).toBe(true); pcp.removePropertyListener(null, listener); - expect(pcp.hasListeners([PropertyChangePublisher.PROPERTY_TOPIC])).toBe(false); + expect(pcp.hasListeners([GLOBAL.X.PropertyChangePublisher.PROPERTY_TOPIC])).toBe(false); }); it('adds/removes a listener for all property changes with addListener/removeListener shortcuts', function() { pcp.addListener(listener); - expect(pcp.hasListeners([PropertyChangePublisher.PROPERTY_TOPIC])).toBe(true); + expect(pcp.hasListeners([GLOBAL.X.PropertyChangePublisher.PROPERTY_TOPIC])).toBe(true); pcp.removeListener(listener); - expect(pcp.hasListeners([PropertyChangePublisher.PROPERTY_TOPIC])).toBe(false); + expect(pcp.hasListeners([GLOBAL.X.PropertyChangePublisher.PROPERTY_TOPIC])).toBe(false); }); }); describe('PropertyChangePublisher.globalChange()', function() { - var ep; var listener; + var pcp; - beforeEach(function() { - pcp = Object.create(PropertyChangePublisher); + beforeEachTest(function() { + pcp = Object.create(GLOBAL.X.PropertyChangePublisher); listener = function(publisher, topic, unsub) { listener.count += 1; } @@ -662,11 +668,11 @@ describe('PropertyChangePublisher.globalChange()', function() { describe('PropertyChangePublisher.propertyChange()', function() { - var ep; var listener; + var pcp; - beforeEach(function() { - pcp = Object.create(PropertyChangePublisher); + beforeEachTest(function() { + pcp = Object.create(GLOBAL.X.PropertyChangePublisher); listener = function(publisher, topic, unsub, old, nu) { listener.last_topic = topic; listener.last_unsub = unsub; @@ -706,11 +712,3 @@ describe('PropertyChangePublisher.propertyChange()', function() { }); - - - - - - - - diff --git a/test/node/coreInclusion.js b/test/node/coreInclusion.js new file mode 100644 index 00000000000..9630174a43f --- /dev/null +++ b/test/node/coreInclusion.js @@ -0,0 +1,27 @@ +describe('Inclusion of all core files', function() { + it('Expect all src/core/*.js files to be listed in src/core.json', + function(done) { + var fs = require('fs'); + var includedJsFileNames = + JSON.parse(fs.readFileSync('src/core.json')); + fs.readdir('src/core', function(err, fileNames) { + expect(err).toBeFalsy(); + var coreJsFileNames = fileNames.filter(function(fileName) { + return !!fileName.match(/[.]js$/); + }); + + // Expectation: coreJsFileNames is a subset of includedJsFileNames. + var coreJsFileNamesMap = {}; + var i; + for (i = 0; i < coreJsFileNames.length; i++) { + coreJsFileNamesMap['core/' + coreJsFileNames[i]] = true; + } + for (i = 0; i < includedJsFileNames.length; i++) { + if (coreJsFileNamesMap[includedJsFileNames[i]]) + delete coreJsFileNamesMap[includedJsFileNames[i]]; + } + expect(coreJsFileNamesMap).toEqual({}); + done(); + }); + }); +});