@qawolf/build-workflow
Advanced tools
Comparing version 0.5.11 to 0.5.12
@@ -9,2 +9,5 @@ "use strict"; | ||
continue; | ||
const tagName = (event.target.tagName || "").toLowerCase(); | ||
if (tagName !== "select") | ||
continue; | ||
steps.push({ | ||
@@ -11,0 +14,0 @@ action: "select", |
import { Event, Step } from "@qawolf/types"; | ||
export declare const buildSteps: (originalEvents: Event[]) => Step[]; | ||
export declare const buildSteps: (events: Event[]) => Step[]; |
@@ -8,5 +8,3 @@ "use strict"; | ||
const buildTypeSteps_1 = require("./buildTypeSteps"); | ||
const replacePasteEvents_1 = require("./replacePasteEvents"); | ||
exports.buildSteps = (originalEvents) => { | ||
const events = replacePasteEvents_1.replacePasteEvents(originalEvents); | ||
exports.buildSteps = (events) => { | ||
const unorderedSteps = lodash_1.concat(buildClickSteps_1.buildClickSteps(events), buildScrollSteps_1.buildScrollSteps(events), buildSelectSteps_1.buildSelectSteps(events), buildTypeSteps_1.buildTypeSteps(events)); | ||
@@ -13,0 +11,0 @@ const steps = lodash_1.sortBy(unorderedSteps, step => step.index).map((step, index) => (Object.assign(Object.assign({}, step), { index }))); |
@@ -1,4 +0,14 @@ | ||
import { Press } from "@qawolf/browser"; | ||
import { Event, Step } from "@qawolf/types"; | ||
export declare const convertEventsToPresses: (events: Event[]) => Press[]; | ||
import { Event, Step, KeyEvent, PasteEvent } from "@qawolf/types"; | ||
export declare class TypeStepFactory { | ||
private events; | ||
private steps; | ||
private pendingEvent; | ||
private pendingStrokes; | ||
constructor(events: Event[]); | ||
buildPendingStrokesStep(): void; | ||
buildSeparateStep(event: KeyEvent, index: number): void; | ||
buildKeyStroke(event: KeyEvent, index: number): void; | ||
buildPasteStrokes(event: PasteEvent, index: number): void; | ||
buildSteps(): Step[]; | ||
} | ||
export declare const buildTypeSteps: (events: Event[]) => Step[]; |
@@ -5,53 +5,91 @@ "use strict"; | ||
const web_1 = require("@qawolf/web"); | ||
exports.convertEventsToPresses = (events) => { | ||
const presses = []; | ||
events.forEach((e, index) => { | ||
if (!web_1.isKeyEvent(e)) | ||
const removePasteKeyEvents_1 = require("./removePasteKeyEvents"); | ||
const SEPARATE_KEYS = ["Enter", "Tab"]; | ||
class TypeStepFactory { | ||
constructor(events) { | ||
this.steps = []; | ||
this.pendingEvent = null; | ||
this.pendingStrokes = []; | ||
this.events = events; | ||
} | ||
buildPendingStrokesStep() { | ||
if (!this.pendingStrokes.length) | ||
return; | ||
const event = e; | ||
if (event.name === "keydown") { | ||
presses.push({ | ||
code: event.value, | ||
downEvent: event, | ||
downEventIndex: index, | ||
upEventIndex: null, | ||
xpath: e.target.xpath | ||
}); | ||
if (!this.pendingEvent) | ||
throw new Error("pendingEvent not set"); | ||
const event = this.pendingEvent; | ||
this.steps.push({ | ||
action: "type", | ||
index: this.events.indexOf(event), | ||
pageId: event.pageId, | ||
target: event.target, | ||
value: browser_1.serializeStrokes(this.pendingStrokes) | ||
}); | ||
this.pendingEvent = null; | ||
this.pendingStrokes = []; | ||
} | ||
buildSeparateStep(event, index) { | ||
if (event.name === "keyup") | ||
return; | ||
this.buildPendingStrokesStep(); | ||
this.pendingEvent = event; | ||
this.pendingStrokes = ["↓", "↑"].map((type) => ({ | ||
index, | ||
type, | ||
value: event.value | ||
})); | ||
this.buildPendingStrokesStep(); | ||
} | ||
buildKeyStroke(event, index) { | ||
if (SEPARATE_KEYS.some(special => event.value === special)) { | ||
this.buildSeparateStep(event, index); | ||
return; | ||
} | ||
else { | ||
const press = presses.find(s => s.code === event.value && s.upEventIndex === null); | ||
press.upEventIndex = index; | ||
const code = browser_1.characterToCode(event.value); | ||
let type = event.name === "keydown" ? "↓" : "↑"; | ||
if (!code) { | ||
type = "→"; | ||
} | ||
}); | ||
return presses; | ||
}; | ||
if (!this.pendingEvent) | ||
this.pendingEvent = event; | ||
this.pendingStrokes.push({ | ||
index, | ||
type, | ||
value: code ? code : event.value | ||
}); | ||
} | ||
buildPasteStrokes(event, index) { | ||
const strokes = browser_1.stringToStrokes(event.value); | ||
if (!this.pendingEvent) | ||
this.pendingEvent = event; | ||
strokes.forEach(stroke => { | ||
this.pendingStrokes.push(Object.assign(Object.assign({}, stroke), { index })); | ||
}); | ||
} | ||
buildSteps() { | ||
const filteredEvents = removePasteKeyEvents_1.removePasteKeyEvents(this.events); | ||
filteredEvents.forEach(event => { | ||
const index = this.events.indexOf(event); | ||
if (this.pendingEvent && event.pageId !== this.pendingEvent.pageId) { | ||
this.buildPendingStrokesStep(); | ||
} | ||
if (web_1.isPasteEvent(event)) { | ||
this.buildPasteStrokes(event, index); | ||
} | ||
else if (web_1.isKeyEvent(event)) { | ||
this.buildKeyStroke(event, index); | ||
} | ||
else { | ||
this.buildPendingStrokesStep(); | ||
} | ||
}); | ||
this.buildPendingStrokesStep(); | ||
return this.steps; | ||
} | ||
} | ||
exports.TypeStepFactory = TypeStepFactory; | ||
exports.buildTypeSteps = (events) => { | ||
const presses = exports.convertEventsToPresses(events); | ||
const steps = []; | ||
let stepPresses = []; | ||
for (let i = 0; i < presses.length; i++) { | ||
const press = presses[i]; | ||
stepPresses.push(press); | ||
const nextPress = i + 1 < presses.length ? presses[i + 1] : null; | ||
const nextPressIsConsecutive = nextPress && web_1.isKeyEvent(events[nextPress.downEventIndex - 1]); | ||
const shouldBuildStep = !nextPressIsConsecutive || | ||
press.code === "Enter" || | ||
press.code === "Tab" || | ||
nextPress.code === "Enter" || | ||
nextPress.code === "Tab"; | ||
if (shouldBuildStep) { | ||
const event = stepPresses[0].downEvent; | ||
const strokes = browser_1.convertPressesToStrokes(stepPresses); | ||
steps.push({ | ||
action: "type", | ||
index: stepPresses[0].downEventIndex, | ||
pageId: event.pageId, | ||
target: event.target, | ||
value: browser_1.serializeStrokes(strokes) | ||
}); | ||
stepPresses = []; | ||
} | ||
} | ||
return steps; | ||
const factory = new TypeStepFactory(events); | ||
return factory.buildSteps(); | ||
}; | ||
//# sourceMappingURL=buildTypeSteps.js.map |
{ | ||
"name": "@qawolf/build-workflow", | ||
"description": "build qawolf workflow from events", | ||
"version": "0.5.11", | ||
"version": "0.5.12", | ||
"license": "BSD-3.0", | ||
@@ -26,13 +26,13 @@ "main": "./lib/index.js", | ||
"dependencies": { | ||
"@qawolf/browser": "^0.5.11", | ||
"@qawolf/logger": "^0.5.10", | ||
"@qawolf/browser": "^0.5.12", | ||
"@qawolf/logger": "^0.5.12", | ||
"lodash": "^4.17.15" | ||
}, | ||
"devDependencies": { | ||
"@qawolf/fixtures": "1.11.0", | ||
"@qawolf/fixtures": "1.12.0", | ||
"@qawolf/types": "^0.5.6", | ||
"@qawolf/web": "^0.5.10", | ||
"@qawolf/web": "^0.5.12", | ||
"jest": "^24.9.0" | ||
}, | ||
"gitHead": "7cf067ca3b1cb314ac662d9190fe67768772d584" | ||
"gitHead": "f4ac1245b88c32309fa357e627185b33cfd861d3" | ||
} |
@@ -12,2 +12,6 @@ import { Event, InputEvent, Step } from "@qawolf/types"; | ||
// ignore input events not on selects | ||
const tagName = (event.target.tagName || "").toLowerCase(); | ||
if (tagName !== "select") continue; | ||
steps.push({ | ||
@@ -14,0 +18,0 @@ action: "select", |
@@ -7,7 +7,4 @@ import { Event, Step } from "@qawolf/types"; | ||
import { buildTypeSteps } from "./buildTypeSteps"; | ||
import { replacePasteEvents } from "./replacePasteEvents"; | ||
export const buildSteps = (originalEvents: Event[]): Step[] => { | ||
const events = replacePasteEvents(originalEvents); | ||
export const buildSteps = (events: Event[]): Step[] => { | ||
const unorderedSteps = concat( | ||
@@ -14,0 +11,0 @@ buildClickSteps(events), |
import { | ||
convertPressesToStrokes, | ||
Press, | ||
serializeStrokes | ||
characterToCode, | ||
serializeStrokes, | ||
stringToStrokes, | ||
Stroke, | ||
StrokeType | ||
} from "@qawolf/browser"; | ||
import { Event, KeyEvent, Step } from "@qawolf/types"; | ||
import { isKeyEvent } from "@qawolf/web"; | ||
import { Event, Step, KeyEvent, PasteEvent } from "@qawolf/types"; | ||
import { isKeyEvent, isPasteEvent } from "@qawolf/web"; | ||
import { removePasteKeyEvents } from "./removePasteKeyEvents"; | ||
export const convertEventsToPresses = (events: Event[]): Press[] => { | ||
const presses: Press[] = []; | ||
const SEPARATE_KEYS = ["Enter", "Tab"]; | ||
events.forEach((e, index) => { | ||
if (!isKeyEvent(e)) return; | ||
export class TypeStepFactory { | ||
private events: Event[]; | ||
const event = e as KeyEvent; | ||
if (event.name === "keydown") { | ||
// create a new press per keydown | ||
presses.push({ | ||
code: event.value, | ||
downEvent: event, | ||
downEventIndex: index, | ||
upEventIndex: null, | ||
xpath: e.target.xpath! | ||
}); | ||
} else { | ||
// match keyup with it's corresponding press | ||
const press = presses.find( | ||
s => s.code === event.value && s.upEventIndex === null | ||
)!; | ||
press.upEventIndex = index; | ||
} | ||
}); | ||
private steps: Step[] = []; | ||
return presses; | ||
}; | ||
// the event of the first pending Stroke | ||
private pendingEvent: Event | null = null; | ||
private pendingStrokes: Stroke[] = []; | ||
export const buildTypeSteps = (events: Event[]) => { | ||
const presses = convertEventsToPresses(events); | ||
constructor(events: Event[]) { | ||
this.events = events; | ||
} | ||
const steps: Step[] = []; | ||
buildPendingStrokesStep() { | ||
/** | ||
* Build a type step for pending strokes. | ||
*/ | ||
if (!this.pendingStrokes.length) return; | ||
if (!this.pendingEvent) throw new Error("pendingEvent not set"); | ||
// group consecutive presses per action | ||
let stepPresses: Press[] = []; | ||
const event = this.pendingEvent; | ||
for (let i = 0; i < presses.length; i++) { | ||
const press = presses[i]; | ||
stepPresses.push(press); | ||
this.steps.push({ | ||
action: "type", | ||
// include event index so we can sort in buildSteps | ||
index: this.events.indexOf(event), | ||
pageId: event.pageId, | ||
target: event.target, | ||
value: serializeStrokes(this.pendingStrokes) | ||
}); | ||
const nextPress = i + 1 < presses.length ? presses[i + 1] : null; | ||
this.pendingEvent = null; | ||
this.pendingStrokes = []; | ||
} | ||
// check the next press does not have another action in-between | ||
const nextPressIsConsecutive = | ||
nextPress && isKeyEvent(events[nextPress.downEventIndex - 1]); | ||
buildSeparateStep(event: KeyEvent, index: number) { | ||
// ignore keyup event we build the separate step for the keydown | ||
// and include the up stroke as part of it | ||
if (event.name === "keyup") return; | ||
const shouldBuildStep = | ||
!nextPressIsConsecutive || | ||
// separate Enter and Tab to their own steps | ||
press!.code === "Enter" || | ||
press!.code === "Tab" || | ||
nextPress!.code === "Enter" || | ||
nextPress!.code === "Tab"; | ||
this.buildPendingStrokesStep(); | ||
if (shouldBuildStep) { | ||
const event = stepPresses[0].downEvent; | ||
const strokes = convertPressesToStrokes(stepPresses); | ||
this.pendingEvent = event; | ||
this.pendingStrokes = ["↓", "↑"].map((type: StrokeType) => ({ | ||
index, | ||
type, | ||
value: event.value | ||
})); | ||
this.buildPendingStrokesStep(); | ||
} | ||
steps.push({ | ||
action: "type", | ||
// include event index so we can sort in buildSteps | ||
index: stepPresses[0].downEventIndex, | ||
pageId: event.pageId, | ||
target: event.target, | ||
value: serializeStrokes(strokes) | ||
}); | ||
buildKeyStroke(event: KeyEvent, index: number) { | ||
if (SEPARATE_KEYS.some(special => event.value === special)) { | ||
this.buildSeparateStep(event, index); | ||
return; | ||
} | ||
stepPresses = []; | ||
const code = characterToCode(event.value); | ||
let type: StrokeType = event.name === "keydown" ? "↓" : "↑"; | ||
if (!code) { | ||
// sendCharacter if we cannot find the key's code | ||
type = "→"; | ||
} | ||
if (!this.pendingEvent) this.pendingEvent = event; | ||
this.pendingStrokes.push({ | ||
index, | ||
type, | ||
value: code ? code : event.value | ||
}); | ||
} | ||
return steps; | ||
buildPasteStrokes(event: PasteEvent, index: number) { | ||
const strokes = stringToStrokes(event.value); | ||
if (!this.pendingEvent) this.pendingEvent = event; | ||
strokes.forEach(stroke => { | ||
this.pendingStrokes.push({ | ||
...stroke, | ||
index | ||
}); | ||
}); | ||
} | ||
buildSteps() { | ||
const filteredEvents = removePasteKeyEvents(this.events); | ||
filteredEvents.forEach(event => { | ||
// find the index from the unfiltered list | ||
const index = this.events.indexOf(event); | ||
if (this.pendingEvent && event.pageId !== this.pendingEvent.pageId) { | ||
// build the step when the page changes | ||
this.buildPendingStrokesStep(); | ||
} | ||
if (isPasteEvent(event)) { | ||
this.buildPasteStrokes(event as PasteEvent, index); | ||
} else if (isKeyEvent(event)) { | ||
this.buildKeyStroke(event as KeyEvent, index); | ||
} else { | ||
// build the step when typing is interrupted | ||
this.buildPendingStrokesStep(); | ||
} | ||
}); | ||
// build steps at the end | ||
this.buildPendingStrokesStep(); | ||
return this.steps; | ||
} | ||
} | ||
export const buildTypeSteps = (events: Event[]) => { | ||
const factory = new TypeStepFactory(events); | ||
return factory.buildSteps(); | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
42591
43
743
Updated@qawolf/browser@^0.5.12
Updated@qawolf/logger@^0.5.12