-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathsequence-builder.js
127 lines (121 loc) · 5.29 KB
/
sequence-builder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const fs = require('fs');
const chalk = require('chalk');
const consts = require("./consts");
const htcrawl = require('htcrawl');
const utils = require('./utils');
exports.SequenceBuilder = class {
constructor(url, options){
this.url = url;
this.options = options;
this.crawler = null;
this.targetUrl = null;
this._finished = false;
}
run(){
return new Promise((resolve, reject) => {
this.launch(resolve);
});
}
async launch(resolve){
this.crawler = await htcrawl.launch(this.url, {
...this.options,
headlessChrome: false,
customUI: {
extensionPath: __dirname + '/chrome-extension',
UIMethods: UI => {
UI.selectElement = async action => {
const e = await UI.utils.selectElement();
switch(action){
case "click":
case "clickToNavigate":
case "setTarget":
UI.dispatch('selectElement', {action: action, par1: e.selector});
break;
case "write":
case "select":
let inp = e.element;
if(!inp.matches("input, select, textarea")){
inp = inp.querySelector("input, select, textarea");
}
if(!inp){
UI.dispatch('selectElement', {error: "Cannot find an input element"});
}
const inpRect = inp.getBoundingClientRect();
const okBtn = UI.utils.createElement("button", {
position: 'absolute',
left: (inpRect.left + document.documentElement.scrollLeft + inpRect.width) + "px",
top: (inpRect.top + document.documentElement.scrollTop) + "px",
backgroundColor: '#9c27b0',
color: 'white',
border: 'none',
padding: '10px 20px',
borderRadius: '5px',
cursor: 'pointer',
zIndex: 2147483640
});
okBtn.textContent = "Apply";
inp.focus();
okBtn.onclick = function() {
this.parentNode.removeChild(this);
UI.dispatch('selectElement', {
action: action,
par1: UI.utils.getElementSelector(inp),
par2: inp.value
});
};
break;
}
};
UI.end = sequence => {
UI.dispatch("end", {sequence: sequence});
};
UI.scan = sequence => {
UI.dispatch("scan", {sequence: sequence});
};
UI.discart = () => {
UI.dispatch("discart");
};
},
events: {
selectElement: async e => {
this.crawler.sendToUI(e.params);
if(e.params.action == "click"){
await this.crawler.page().click(e.params.par1);
}
if(e.params.action == "clickToNavigate"){
try{
this.crawler.on("navigation", e => {
this.targetUrl = e.params.request.url;
});
await this.crawler.clickToNavigate(e.params.par1);
}catch(e){
this.crawler.sendToUI({error: "Navigation timeout"});
return;
}
}
},
end: async e => {
this.crawler.browser().close();
resolve({
sequence: e.params.sequence,
next: null
});
},
scan: async e => {
this.crawler.browser().close();
resolve({
sequence: e.params.sequence,
next: "scan",
targetUrl: this.targetUrl,
});
},
discart: async e => {
resolve({discart: true});
},
}
},
});
await this.crawler.load();
this.crawler.sendToUI({action: "navigate", par1: this.url});
}
};