Skip to content

Commit eb0322b

Browse files
author
David Haeffner
committed
Added code export support for commands that open a new window
1 parent f5d2994 commit eb0322b

File tree

11 files changed

+358
-68
lines changed

11 files changed

+358
-68
lines changed

packages/code-export-java-junit/__test__/src/__snapshots__/index.spec.js.snap

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ import org.openqa.selenium.support.ui.WebDriverWait;
1919
import org.openqa.selenium.JavascriptExecutor;
2020
import org.openqa.selenium.Alert;
2121
import org.openqa.selenium.Keys;
22-
import java.util.HashMap;
23-
import java.util.List;
24-
import java.util.ArrayList;
25-
import java.util.Map;
22+
import java.util.*;
2623
public class LoginTest {
2724
private WebDriver driver;
2825
private Map<String, Object> vars;
@@ -78,10 +75,7 @@ import org.openqa.selenium.support.ui.WebDriverWait;
7875
import org.openqa.selenium.JavascriptExecutor;
7976
import org.openqa.selenium.Alert;
8077
import org.openqa.selenium.Keys;
81-
import java.util.HashMap;
82-
import java.util.List;
83-
import java.util.ArrayList;
84-
import java.util.Map;
78+
import java.util.*;
8579
public class ControlflowTest {
8680
private WebDriver driver;
8781
private Map<String, Object> vars;
@@ -180,10 +174,7 @@ import org.openqa.selenium.support.ui.WebDriverWait;
180174
import org.openqa.selenium.JavascriptExecutor;
181175
import org.openqa.selenium.Alert;
182176
import org.openqa.selenium.Keys;
183-
import java.util.HashMap;
184-
import java.util.List;
185-
import java.util.ArrayList;
186-
import java.util.Map;
177+
import java.util.*;
187178
public class LoginTest {
188179
private WebDriver driver;
189180
private Map<String, Object> vars;
@@ -240,10 +231,7 @@ import org.openqa.selenium.support.ui.WebDriverWait;
240231
import org.openqa.selenium.JavascriptExecutor;
241232
import org.openqa.selenium.Alert;
242233
import org.openqa.selenium.Keys;
243-
import java.util.HashMap;
244-
import java.util.List;
245-
import java.util.ArrayList;
246-
import java.util.Map;
234+
import java.util.*;
247235
public class LoginTest {
248236
private WebDriver driver;
249237
private Map<String, Object> vars;
@@ -271,6 +259,71 @@ public class LoginTest {
271259
"
272260
`;
273261

262+
exports[`Code Export Java Selenium should export a test to JUnit code with commands that open a new window 1`] = `
263+
"// Generated by Selenium IDE
264+
import org.junit.Test;
265+
import org.junit.Before;
266+
import org.junit.After;
267+
import static org.junit.Assert.*;
268+
import static org.hamcrest.CoreMatchers.is;
269+
import static org.hamcrest.core.IsNot.not;
270+
import org.openqa.selenium.By;
271+
import org.openqa.selenium.WebDriver;
272+
import org.openqa.selenium.firefox.FirefoxDriver;
273+
import org.openqa.selenium.Dimension;
274+
import org.openqa.selenium.WebElement;
275+
import org.openqa.selenium.interactions.Actions;
276+
import org.openqa.selenium.support.ui.ExpectedConditions;
277+
import org.openqa.selenium.support.ui.WebDriverWait;
278+
import org.openqa.selenium.JavascriptExecutor;
279+
import org.openqa.selenium.Alert;
280+
import org.openqa.selenium.Keys;
281+
import java.util.*;
282+
public class SelectwindowTest {
283+
private WebDriver driver;
284+
private Map<String, Object> vars;
285+
JavascriptExecutor js;
286+
@Before
287+
public void setUp() {
288+
driver = new FirefoxDriver();
289+
js = (JavascriptExecutor) driver;
290+
vars = new HashMap<String, Object>();
291+
}
292+
@After
293+
public void tearDown() {
294+
driver.quit();
295+
}
296+
public String waitForWindow(int timeout) {
297+
try {
298+
Thread.sleep(timeout);
299+
} catch (InterruptedException e) {
300+
e.printStackTrace();
301+
}
302+
Set<String> whNow = driver.getWindowHandles();
303+
Set<String> whThen = (Set<String>) vars.get(\\"window_handles\\");
304+
if (whNow.size() > whThen.size()) {
305+
whNow.removeAll(whThen);
306+
}
307+
return whNow.iterator().next();
308+
}
309+
@Test
310+
public void selectwindow() {
311+
driver.get(\\"http://the-internet.herokuapp.com/\\");
312+
driver.manage().window().setSize(new Dimension(1260, 1027));
313+
driver.findElement(By.linkText(\\"Multiple Windows\\")).click();
314+
vars.put(\\"window_handles\\", driver.getWindowHandles());
315+
driver.findElement(By.linkText(\\"Click Here\\")).click();
316+
vars.put(\\"win9625\\", waitForWindow(2000));
317+
vars.put(\\"root\\", driver.getWindowHandle());
318+
driver.switchTo().window(vars.get(\\"win9625\\").toString());
319+
assertThat(driver.getTitle(), is(\\"New Window\\"));
320+
driver.switchTo().window(vars.get(\\"root\\").toString());
321+
assertThat(driver.getTitle(), is(\\"The Internet\\"));
322+
}
323+
}
324+
"
325+
`;
326+
274327
exports[`Code Export Java Selenium should export a test to JUnit code with reused test method 1`] = `
275328
"// Generated by Selenium IDE
276329
import org.junit.Test;
@@ -290,10 +343,7 @@ import org.openqa.selenium.support.ui.WebDriverWait;
290343
import org.openqa.selenium.JavascriptExecutor;
291344
import org.openqa.selenium.Alert;
292345
import org.openqa.selenium.Keys;
293-
import java.util.HashMap;
294-
import java.util.List;
295-
import java.util.ArrayList;
296-
import java.util.Map;
346+
import java.util.*;
297347
public class ValidcredentialsTest {
298348
private WebDriver driver;
299349
private Map<String, Object> vars;

packages/code-export-java-junit/__test__/src/command.spec.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ describe('command code emitter', () => {
506506
value: '',
507507
}
508508
return expect(prettify(command)).resolves.toBe(
509-
`Thread.sleep(${command.target});`
509+
`try {\n${commandPrefixPadding}Thread.sleep(300);\n} catch (InterruptedException e) {\n${commandPrefixPadding}e.printStackTrace();\n}`
510510
)
511511
})
512512
it('should emit `remove selection` command', () => {
@@ -584,7 +584,7 @@ describe('command code emitter', () => {
584584
value: '',
585585
}
586586
return expect(prettify(command)).resolves.toBe(
587-
`driver.switchTo().window("vars.get("window").toString()");`
587+
`driver.switchTo().window(vars.get("window").toString());`
588588
)
589589
})
590590
it('should emit `select window` to select a window by name', () => {
@@ -1042,4 +1042,17 @@ describe('command code emitter', () => {
10421042
endingLevel: 1,
10431043
})
10441044
})
1045+
it('should emit new window handling, if command opens a new window', () => {
1046+
const command = {
1047+
command: 'click',
1048+
target: 'css=button',
1049+
value: '',
1050+
opensWindow: true,
1051+
windowHandleName: 'newWin',
1052+
windowTimeout: 2000,
1053+
}
1054+
return expect(prettify(command)).resolves.toBe(
1055+
`vars.put("window_handles", driver.getWindowHandles());\ndriver.findElement(By.cssSelector("button")).click();\nvars.put("newWin", waitForWindow(2000));`
1056+
)
1057+
})
10451058
})

packages/code-export-java-junit/__test__/src/index.spec.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ describe('Code Export Java Selenium', () => {
5757
expect(results.body).toBeDefined()
5858
expect(results.body).toMatchSnapshot()
5959
})
60+
it('should export a test to JUnit code with commands that open a new window', async () => {
61+
const project = normalizeProject(readFile('select-window.side'))
62+
const results = await emitTest({
63+
baseUrl: project.url,
64+
test: project.tests[0],
65+
tests: project.tests,
66+
})
67+
expect(results.body).toBeDefined()
68+
expect(results.body).toMatchSnapshot()
69+
})
6070
it('should export a suite to JUnit code with reused test method', async () => {
6171
const project = normalizeProject(readFile('test-case-reuse.side'))
6272
const results = await emitSuite({
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{
2+
"id": "c0f8143d-d29b-43cc-ab08-268ef217f3b4",
3+
"version": "2.0",
4+
"name": "select window",
5+
"url": "http://the-internet.herokuapp.com",
6+
"tests": [{
7+
"id": "5d92f854-623b-41da-826b-2feb4ad20f2a",
8+
"name": "select window",
9+
"commands": [{
10+
"id": "0441ea10-c31c-4322-965b-6f61e22048cf",
11+
"comment": "",
12+
"command": "open",
13+
"target": "/",
14+
"targets": [],
15+
"value": ""
16+
}, {
17+
"id": "2d33741e-04a8-4f17-a7f0-fd4a0cb17fc8",
18+
"comment": "",
19+
"command": "setWindowSize",
20+
"target": "1260x1027",
21+
"targets": [],
22+
"value": ""
23+
}, {
24+
"id": "343f1636-850a-4a24-b99c-6702a890e572",
25+
"comment": "",
26+
"command": "click",
27+
"target": "linkText=Multiple Windows",
28+
"targets": [
29+
["linkText=Multiple Windows", "linkText"],
30+
["css=li:nth-child(33) > a", "css:finder"],
31+
["xpath=//a[contains(text(),'Multiple Windows')]", "xpath:link"],
32+
["xpath=//div[@id='content']/ul/li[33]/a", "xpath:idRelative"],
33+
["xpath=//a[contains(@href, '/windows')]", "xpath:href"],
34+
["xpath=//li[33]/a", "xpath:position"],
35+
["xpath=//a[contains(.,'Multiple Windows')]", "xpath:innerText"]
36+
],
37+
"value": ""
38+
}, {
39+
"id": "ffc4bbd5-e3cb-4a43-ad80-30c1d2ec5f25",
40+
"comment": "",
41+
"command": "click",
42+
"target": "linkText=Click Here",
43+
"targets": [
44+
["linkText=Click Here", "linkText"],
45+
["css=a:nth-child(2)", "css:finder"],
46+
["xpath=//a[contains(text(),'Click Here')]", "xpath:link"],
47+
["xpath=//div[@id='content']/div/a", "xpath:idRelative"],
48+
["xpath=//a[contains(@href, '/windows/new')]", "xpath:href"],
49+
["xpath=//div/div/a", "xpath:position"],
50+
["xpath=//a[contains(.,'Click Here')]", "xpath:innerText"]
51+
],
52+
"value": "",
53+
"opensWindow": true,
54+
"windowHandleName": "win9625",
55+
"windowTimeout": 2000
56+
}, {
57+
"id": "2a1a9e51-71d0-45db-9d77-479d160a67f0",
58+
"comment": "",
59+
"command": "storeWindowHandle",
60+
"target": "root",
61+
"targets": [],
62+
"value": ""
63+
}, {
64+
"id": "0d33a445-a65b-4a69-82c6-c89bb1d53a5e",
65+
"comment": "",
66+
"command": "selectWindow",
67+
"target": "handle=${win9625}",
68+
"targets": [],
69+
"value": ""
70+
}, {
71+
"id": "528b6f23-22a7-4a4c-993d-c772ceea96bc",
72+
"comment": "",
73+
"command": "assertTitle",
74+
"target": "New Window",
75+
"targets": [],
76+
"value": ""
77+
}, {
78+
"id": "dd32287e-b69b-4674-8171-e50aef15d904",
79+
"comment": "",
80+
"command": "selectWindow",
81+
"target": "handle=${root}",
82+
"targets": [],
83+
"value": ""
84+
}, {
85+
"id": "f02dff23-83d9-457f-8010-d5d15c32f0c4",
86+
"comment": "",
87+
"command": "assertTitle",
88+
"target": "The Internet",
89+
"targets": [],
90+
"value": ""
91+
}]
92+
}],
93+
"suites": [{
94+
"id": "988ac055-dcc7-48ba-ab8a-6fe3e3079a54",
95+
"name": "Default Suite",
96+
"persistSession": false,
97+
"parallel": false,
98+
"timeout": 300,
99+
"tests": ["5d92f854-623b-41da-826b-2feb4ad20f2a"]
100+
}],
101+
"urls": ["http://the-internet.herokuapp.com/"],
102+
"plugins": []
103+
}

packages/code-export-java-junit/src/command.js

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export const emitters = {
112112
waitForElementNotEditable: emitWaitForElementNotEditable,
113113
waitForElementNotPresent: emitWaitForElementNotPresent,
114114
waitForElementNotVisible: emitWaitForElementNotVisible,
115+
waitForWindow: emitWaitForWindow,
115116
webdriverAnswerOnVisiblePrompt: emitAnswerOnNextPrompt,
116117
webdriverChooseCancelOnVisibleConfirmation: emitChooseCancelOnNextConfirmation,
117118
webdriverChooseCancelOnVisiblePrompt: emitChooseCancelOnNextConfirmation,
@@ -126,11 +127,10 @@ function register(command, emitter) {
126127
}
127128

128129
function emit(command) {
129-
return exporter.emit.command(
130-
command,
131-
emitters[command.command],
132-
variableLookup
133-
)
130+
return exporter.emit.command(command, emitters[command.command], {
131+
variableLookup,
132+
emitNewWindowHandling,
133+
})
134134
}
135135

136136
function variableLookup(varName) {
@@ -141,6 +141,47 @@ function variableSetter(varName, value) {
141141
return varName ? `vars.put("${varName}", ${value});` : ''
142142
}
143143

144+
function emitWaitForWindow() {
145+
const generateMethodDeclaration = name => {
146+
return `public String ${name}(int timeout) {`
147+
}
148+
const commands = [
149+
{ level: 0, statement: 'try {' },
150+
{ level: 1, statement: 'Thread.sleep(timeout);' },
151+
{ level: 0, statement: '} catch (InterruptedException e) {' },
152+
{ level: 1, statement: 'e.printStackTrace();' },
153+
{ level: 0, statement: '}' },
154+
{ level: 0, statement: 'Set<String> whNow = driver.getWindowHandles();' },
155+
{
156+
level: 0,
157+
statement:
158+
'Set<String> whThen = (Set<String>) vars.get("window_handles");',
159+
},
160+
{ level: 0, statement: 'if (whNow.size() > whThen.size()) {' },
161+
{ level: 1, statement: 'whNow.removeAll(whThen);' },
162+
{ level: 0, statement: '}' },
163+
{ level: 0, statement: 'return whNow.iterator().next();' },
164+
]
165+
return Promise.resolve({
166+
name: 'waitForWindow',
167+
commands,
168+
generateMethodDeclaration,
169+
})
170+
}
171+
172+
async function emitNewWindowHandling(command, emittedCommand) {
173+
// TODO: add waitForWindow method to global emitting
174+
// TODO: fix interpolation bug
175+
// TODO: e2e test
176+
// TODO: test with a command that emits an object instead of a string
177+
// TODO: port to code-export-python-pytest
178+
return Promise.resolve(
179+
`vars.put("window_handles", driver.getWindowHandles());\n${await emittedCommand}\nvars.put("${
180+
command.windowHandleName
181+
}", waitForWindow(${command.windowTimeout}));`
182+
)
183+
}
184+
144185
function emitAssert(varName, value) {
145186
return Promise.resolve(
146187
`assertEquals(vars.get("${varName}").toString(), "${value}");`
@@ -453,7 +494,14 @@ function emitOpen(target) {
453494
}
454495

455496
async function emitPause(time) {
456-
return Promise.resolve(`Thread.sleep(${time});`)
497+
const commands = [
498+
{ level: 0, statement: 'try {' },
499+
{ level: 1, statement: `Thread.sleep(${time});` },
500+
{ level: 0, statement: '} catch (InterruptedException e) {' },
501+
{ level: 1, statement: 'e.printStackTrace();' },
502+
{ level: 0, statement: '}' },
503+
]
504+
return Promise.resolve({ commands })
457505
}
458506

459507
async function emitRun(testName) {
@@ -522,7 +570,7 @@ async function emitSelectFrame(frameLocation) {
522570
async function emitSelectWindow(windowLocation) {
523571
if (/^handle=/.test(windowLocation)) {
524572
return Promise.resolve(
525-
`driver.switchTo().window("${windowLocation.split('handle=')[1]}");`
573+
`driver.switchTo().window(${windowLocation.split('handle=')[1]});`
526574
)
527575
} else if (/^name=/.test(windowLocation)) {
528576
return Promise.resolve(
@@ -1001,4 +1049,5 @@ async function emitWaitForElementNotVisible(locator, timeout) {
10011049
export default {
10021050
emit,
10031051
register,
1052+
emitWaitForWindow,
10041053
}

0 commit comments

Comments
 (0)