-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
commands_tab_helpers.js
253 lines (240 loc) · 8.69 KB
/
commands_tab_helpers.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
let active_tab_index = 0;
let myTabs = [];
if(window.top.myTabs){
window.top.myTabs.forEach((tab,i)=>{
if(i===0 || !tab){
return;
}
try{
tab.close()
window.top.myTabs[i] = null
}catch(e){
}
})
}
window.top.myTabs = myTabs;
let myTabNames = [];
window.top.myTabNames = myTabNames;
// TODO: make this a nice collapsing table
function debugTabState() {
// comment this out to silence it
console.warn('-----debugTabState: active_tab:',active_tab_index + ' ' + myTabNames[active_tab_index])
myTabs.forEach((_win, k) => {
console.warn(k, {
active_tab_index,
name: myTabNames[k],
win: _win,
winATABNAME: _win? _win.ATABNAME : null,
app_name: _win? _win.APP_NAME: null // something i use for debugging
})
})
}
Cypress.Commands.add('debugTabHelper',()=>{
debugTabState();
return {
active_tab_index,
myTabNames,
myTabs,
}
})
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
// support for keying the first window with a tab_name like our child windows to simplify switching windows and making it readable
// instead of keeping track of array indexes
// can pass options as first param too
let tab_name = null;
if (url && url.tab_name) {
tab_name = url.tab_name
}
if (options && options.tab_name) {
tab_name = options.tab_name
}
if(tab_name){
myTabNames[0] = tab_name
}else{
myTabNames[0] = 'root'
}
myTabs[0] = cy.state('window')
// originalFn is the existing `visit` command that you need to call
// and it will receive whatever you pass in here.
//
// make sure to add a return here!
return originalFn(url, options)
})
// note: cy.reload win.location.reload, etc break our context aware popups
// use this special visit function that maintains our context awareness when navigating on the currently active context
Cypress.Commands.add('tabVisit', (url, tab_name) => {
if(typeof(tab_name)==="undefined"){
tab_name = myTabNames[myTabNames.indexOf(active_tab_index)]
}
let window_index = myTabNames.indexOf(tab_name)
console.warn('tabVisit', {
tab_name,
window_index
})
if (window_index === 0) {
// for root window, reattach after iframe onload
return new Cypress.Promise((resolve) => {
active_tab_index = 0
let base_window = myTabs[0] || cy.state('window')
let aut = base_window.top.document.getElementsByClassName('aut-iframe')[0]
// console.warn('aut?', aut, originalWindow.document.getElementsByClassName('aut-iframe')[0])
aut.onload = function () {
aut.onload = null;
active_tab_index = 0
setTimeout(() => {
active_tab_index = 0
myTabs[0] = aut.contentWindow
cy.state('document', aut.contentWindow.document)
cy.state('window', aut.contentWindow)
console.log('>>> after iframe loaded')
debugTabState()
resolve()
}, 500)
}
aut.contentWindow.location.href = url
active_tab_index = 0
})
} else {
// for popupwindows, just call openTab
active_tab_index = window_index
return cy.openTab(url, {window_index, tab_name}).then(() => {
console.log('AFTER OPENTAB')
active_tab_index = window_index
})
}
})
let popupcounter = 0;
Cypress.Commands.add('openTab', (url, opts) => {
opts = Object.assign({
timeout: null,
// window_index: null,
tab_name: null,
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open
windowFeatures: null
},opts)
if(!opts.tab_name){
throw new Error('please give your tab a name');
}
if (!myTabs[0]) {
myTabs[0] = cy.state('window'); // capture the root window if we haven't already
myTabs[0].ATABNAME = myTabNames[0]
}
const w = Cypress.config('viewportWidth')
const h = Cypress.config('viewportHeight')
if (!opts.windowFeatures) {
opts.windowFeatures = `width=${w}, height=${h}`
}
let indexNext = myTabs.length
let name_index = myTabNames.indexOf(opts.tab_name)
console.warn('openTab',{name_index,indexNext,active_tab_index})
if (name_index > -1) {
indexNext = name_index
}
myTabNames[indexNext] = opts.tab_name;
function finalize(){
// let windowName = 'popup' + performance.now();
// let windowName = 'popup' + popupcounter;
let windowName = 'popup' + opts.tab_name;
let promise = new Cypress.Promise(resolve => {
console.warn('>>>> openTab %s "%s %s"', url, opts.windowFeatures, indexNext, opts.tab_name);
// https://developer.mozilla.org/en-US/docs/Web/API/Window/open
popupcounter++;
let popup = myTabs[indexNext] ? myTabs[indexNext] : window.top.open(url, windowName, opts.windowFeatures)
myTabs[indexNext] = popup
myTabs[indexNext].ATABNAME = myTabNames[indexNext]
// letting page enough time to load and set "document.domain = localhost"
// so we can access it
function checkReady(){
// thought checking document.domain would work but it never seems to update
// if(popup.document.domain !== "localhost"){
// checking body length is important for chrome tho, otherwise it will try and execute tests on about:blank
if(!popup.document.body || popup.document.body.innerHTML.length===0){
setTimeout(()=>{
checkReady()
},32); // arbitrary delay
}else{
cy.state('document', popup.document)
cy.state('window', popup)
console.warn('>>>> after openTab')
debugTabState()
resolve();
}
}
checkReady();
})
return promise
}
active_tab_index = indexNext;
if(myTabs[indexNext]){
cy.closeTab(indexNext).then(finalize)
// return finalize()
}else{
return finalize()
}
})
Cypress.Commands.add('switchToTab', (index_or_name) => {
return new Cypress.Promise((resolve) => {
let index = resolve_index_or_name_to_index(index_or_name)
console.warn('switchToTab',{index,index_or_name})
active_tab_index = index;
let winNext = myTabs[active_tab_index]
if(!winNext){
throw new Error('tab missing')
}
cy.state('document', winNext.document)
cy.state('window', winNext)
debugTabState()
resolve()
})
})
/* close all popup windows */
Cypress.Commands.add('closeAllTabs', () => {
if (!myTabs.length) {
return;
}
myTabs.forEach((v, k) => {
if (k > 0) {
try {
myTabs[k].close()
} catch (e) {
console.error(e)
}
myTabs[k] = null;
}
})
myTabNames.splice(1)
myTabs.splice(1) // keep first one only
// return to state 0 (main / root / original window)
active_tab_index = 0;
cy.state('document', myTabs[0].document)
cy.state('window', myTabs[0])
})
function resolve_index_or_name_to_index(index_or_name){
let index = parseInt(index_or_name) >= 0 ? index_or_name : active_tab_index || 0
let name_index = myTabNames.indexOf(index_or_name)
if(name_index>-1){
index = name_index
}
return index;
}
/* pass an index to close a specific window, otherwise, pass nothing to delete the most recently open window in the stack */
Cypress.Commands.add('closeTab', (index_or_name) => {
let index = resolve_index_or_name_to_index(index_or_name)
console.warn('closeTab',{index_or_name,index})
if (index === 0) {
console.error('cant close root window')
return //new Cypress.Promise.resolve(true);
}
myTabs[index].close()
myTabs[index] = null;
// NOTE we leave the null in the array so that other window index references aren't thrown off
// NOTE we don't refocus any window here, that's up to you to call switchToTab() after close
// unless there's no windows left, in which case we return you to window 0
let filteredList = myTabs.filter(tab => tab)
if(filteredList.length === 1){
cy.switchToTab(0)
}
// TODO if there are trailing squential trailing nulls, we could probably safely drop them from
// myTabs and myTabNames
//cy.switchToTab(active_tab_index)
})