ST.context = {}; // namespace ST._screenshotCount = 0; (function () {var logger = ST.logger.forClass('context/Base'); ST.context.Base = ST.define({ /** * @cfg {Boolean} eventTranslation * `false` to disable event translation. If `false` events that are not supported by * the browser's event APIs will simply be skipped. * NOTE: inherited from Player */ eventTranslation: true, /** * @cfg {Boolean} visualFeedback * `false` to disable visual feedback during event playback (mouse cursor, and "gesture" * indicator) * NOTE: inherited from Player */ visualFeedback: true, /** * @param {Array} playables Either a config for a playable or a Playable * @param done */ play: function (playables, done) { var me = this, player = ST.player(), options = ST.options, length = playables.length, i, p, tail; logger.trace('.play', '[' + length + ']', 'done'); if (done) { tail = { type: 'tail', remoteable: false, fn: function () { player.un('error', tail); if (done) { done(); } } }; playables.push(tail); } for (i = 0; i < length; i++) { p = playables[i]; p.context = me; if (typeof p.futureClsName === 'undefined') { p.futureClsName = 'ST.future.Element'; } p.args = p.args || {}; } me.eventDelay = player.eventDelay = options.eventDelay; me.typingDelay = player.typingDelay = options.typingDelay; me.visualFeedback = player.visualFeedback = options.visualFeedback; me.eventTranslation = player.eventTranslation = options.eventTranslation; if (me.injector) { me.injector.translate = options.eventTranslation; } player.add(playables); if (done) { playables.pop(); player.on('error', tail.fn); } player.start(); // does nothing if already started return playables; }, screenshot: function (name, tolerance, done) { logger.trace('.screenshot'); var me = this; name = name || ST._screenshotCount++; tolerance = tolerance || 0; me._screenshot(name, function (err, comparison) { var expectation, passed; if (err) { expectation = { passed: false, message: err.stack || err.message || err }; } else if (comparison) { passed = comparison.diffCount <= tolerance; expectation = { passed: passed, message: 'Expected screenshot ' + name + ' to match baseline.', screenshot: comparison.path, baseline: comparison.baseline, diff: comparison.diff }; } else { expectation = { passed: true, message: 'Screenshot comparison unsupported for this session' }; } ST.status.addResult(expectation); done(comparison); }); }, _createInstance: function (className, config) { logger.trace('._createInstance', className, '{config}'); var fn = ST.clsFromString(className); if (!fn) { fn = ST.playable.Playable; } return new fn(config); }, createPlayable: function (event) { var me = this, type = event.type, playableClsName, playable; logger.trace('.createrPlayable <=', type); playableClsName = event.futureClsName + '.prototype.playables.' + ST.capitalize(type); playable = me._createInstance(playableClsName, event); // allows for custom events such as the expandX methods for tap/type... if (!playable) { playable = new ST.playable.Playable(event); } playable.context = playable.context || me; logger.trace('.createPlayable() =>', playable.type); return playable; }, checkGlobalLeaks: function (done) { logger.trace('._checkGlobalLeaks', 'done()'); this._checkGlobalLeaks(function (result) { result = result || {}; var results = result.results, addedGlobals = result.addedGlobals; if (results && results.length) { for (var i=0; i<results.length; i++) { ST.status.addResult(results[i]); } } if (addedGlobals && addedGlobals.length) { ST.addGlobals(addedGlobals); } done(); }); }}); }());