/* eslint-env es6, node */(function () { var logger = ST.logger.forClass('MagicCanvasRecorder'); /** * @class ST.event.MagicCanvasRecorder * @extend ST.event.Recorder * This class is not created by user code. It is created by the Sencha Test Event Recorder * in Sencha Studio via the injected {@link ST#startRecording} method call. */ST.event.MagicCanvasRecorder = ST.define({ extend: ST.event.Recorder, constructor: function (config) { var me = this, Event = ST.event.Event; me.eventMaps = [ Event.clickEvents, { // We intentionally do not record keypress so as to simplify the output. // When a keydown event is played back, a keypress will be simulated // immediately after. keydown: 1, keyup: 1 }, { mousedown: 1, mouseup: 1, pointerdown: 1, pointerup: 1, mousewheel: 1, wheel: 1 } // TODO any more events??? ]; ST.apply(me, config); me.previousEvent = {}; me.clear(); }, wrapEvent: function(e) { var me = this; return new Promise(function (resolve, reject) { return ST.defaultContext.STLoaded().then(function () { logger.trace('Wrapping', e.type); if (e.type === 'wheel' || ST.event.Event.mouseEvents[e.type] || ST.event.Event.clickEvents[e.type] || ST.event.Event.keyEvents[e.type]) { return ST.defaultContext.wrapEvent(e) .then(function (remoteEvent) { var event = remoteEvent.value, playable; // TODO: make the recorder UI use the targets array instead of forcing a target here if (event.targets.length) { event.target = event.targets[0].target; } // playback the event in the target browser because we are intercepting events in the canvas // this lets us check and make sure we recorded the right things // (locator, action, etc.) before adding it to the recorded stack playable = ST.defaultContext.initEvent(event); if (ST.event.Event.keyEvents[e.type]) { if (!playable.key) playable.key = e.key; } logger.tick('MagicCanvasRecorder.wrapEvent injecting playable ' + playable.type) ST.defaultContext.inject(playable, function () { me.previousEvent = event; resolve(event); }, function () { // If we fall in here, something happened to the element during injection. We want to go // ahead and send the event on to Studio for recording. resolve(event); }); }); } else if (e.type === 'focus' || e.type === 'blur') { // focus and blur on window have problems that need investigation... } else if (ST.event.Event.mouseEvents[e.type]) { // mouse events need to be handled by the webdriverrecorder context maybe? } else { // TODO What did we miss? Do we need to inject it? logger.error('Unsupported BrowserEvent occurred.', e); reject('Unsupported BrowserEvent occurred.' + e.type); } }).catch(function () { return ST.defaultContext._loadST().then(function () { // We got an event that couldn't properly resolve in the target. // This is usually as a result of navigation, in particular with keydown events // that trigger a navigation (Enter, space bar on a button/link, etc.) and their // closing keyup events. // Set the target according to the previous event for coalescing as a best guess. if (ST.event.Event.keyEvents[e.type]) { var event = new ST.event.Event(e, []); if (me.previousEvent) { event.target = me.previousEvent.target; event.targets = me.previousEvent.targets; resolve(event.serialize()); } } }) }); }); }, flush: function() { var me = this, recording = me.recording, eventOrder = me.eventOrder, length = recording.length, events = recording.slice(me.flushIndex, length), fixedEvents = [], len = eventOrder.length, i, x, id; // on the MagicCanvas, events can be processed out of the order in which they were originally detected // to bypass this mess, we'll simply fix up the order of the recordings based on the order of their ids // since we know the order in which they were originally detected, we can simply put them back into the right // sequence when the flush is ready for (i=0; i<len; i++) { id = eventOrder[i]; for (x=0; x<events.length; x++) { if (id === events[x].recorderId) { fixedEvents.push(events[x]); break; } } } me.fireEvent('add', me, fixedEvents); me.flushIndex = length; clearTimeout(me.flushTimeout); me.flushTimeout = null; }}); }());