@serenity-js/protractor 3.0.0-rc.9 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/CHANGELOG.md +144 -2236
  2. package/README.md +39 -26
  3. package/lib/adapter/Config.d.ts +11 -9
  4. package/lib/adapter/Config.d.ts.map +1 -0
  5. package/lib/adapter/ProtractorFrameworkAdapter.d.ts +2 -3
  6. package/lib/adapter/ProtractorFrameworkAdapter.d.ts.map +1 -0
  7. package/lib/adapter/ProtractorFrameworkAdapter.js +11 -10
  8. package/lib/adapter/ProtractorFrameworkAdapter.js.map +1 -1
  9. package/lib/adapter/browser-detector/BrowserDetector.d.ts +1 -0
  10. package/lib/adapter/browser-detector/BrowserDetector.d.ts.map +1 -0
  11. package/lib/adapter/browser-detector/BrowserDetector.js +5 -5
  12. package/lib/adapter/browser-detector/BrowserDetector.js.map +1 -1
  13. package/lib/adapter/browser-detector/StandardisedCapabilities.d.ts +5 -4
  14. package/lib/adapter/browser-detector/StandardisedCapabilities.d.ts.map +1 -0
  15. package/lib/adapter/browser-detector/StandardisedCapabilities.js +17 -17
  16. package/lib/adapter/browser-detector/StandardisedCapabilities.js.map +1 -1
  17. package/lib/adapter/browser-detector/index.d.ts +1 -0
  18. package/lib/adapter/browser-detector/index.d.ts.map +1 -0
  19. package/lib/adapter/browser-detector/index.js +5 -1
  20. package/lib/adapter/browser-detector/index.js.map +1 -1
  21. package/lib/adapter/index.d.ts +2 -0
  22. package/lib/adapter/index.d.ts.map +1 -0
  23. package/lib/adapter/index.js +6 -1
  24. package/lib/adapter/index.js.map +1 -1
  25. package/lib/adapter/reporter/ProtractorReport.d.ts +5 -6
  26. package/lib/adapter/reporter/ProtractorReport.d.ts.map +1 -0
  27. package/lib/adapter/reporter/ProtractorReporter.d.ts +1 -0
  28. package/lib/adapter/reporter/ProtractorReporter.d.ts.map +1 -0
  29. package/lib/adapter/reporter/ProtractorReporter.js +10 -5
  30. package/lib/adapter/reporter/ProtractorReporter.js.map +1 -1
  31. package/lib/adapter/reporter/index.d.ts +1 -0
  32. package/lib/adapter/reporter/index.d.ts.map +1 -0
  33. package/lib/adapter/reporter/index.js +5 -1
  34. package/lib/adapter/reporter/index.js.map +1 -1
  35. package/lib/adapter/run.d.ts +7 -4
  36. package/lib/adapter/run.d.ts.map +1 -0
  37. package/lib/adapter/run.js +6 -4
  38. package/lib/adapter/run.js.map +1 -1
  39. package/lib/adapter/runner/CucumberAdapterConfig.d.ts +5 -10
  40. package/lib/adapter/runner/CucumberAdapterConfig.d.ts.map +1 -0
  41. package/lib/adapter/runner/TestRunnerDetector.d.ts +5 -12
  42. package/lib/adapter/runner/TestRunnerDetector.d.ts.map +1 -0
  43. package/lib/adapter/runner/TestRunnerDetector.js +7 -15
  44. package/lib/adapter/runner/TestRunnerDetector.js.map +1 -1
  45. package/lib/adapter/runner/TestRunnerLoader.d.ts +20 -17
  46. package/lib/adapter/runner/TestRunnerLoader.d.ts.map +1 -0
  47. package/lib/adapter/runner/TestRunnerLoader.js +18 -18
  48. package/lib/adapter/runner/TestRunnerLoader.js.map +1 -1
  49. package/lib/adapter/runner/index.d.ts +1 -0
  50. package/lib/adapter/runner/index.d.ts.map +1 -0
  51. package/lib/adapter/runner/index.js +5 -1
  52. package/lib/adapter/runner/index.js.map +1 -1
  53. package/lib/index.d.ts +1 -0
  54. package/lib/index.d.ts.map +1 -0
  55. package/lib/index.js +5 -1
  56. package/lib/index.js.map +1 -1
  57. package/lib/screenplay/abilities/BrowseTheWebWithProtractor.d.ts +62 -300
  58. package/lib/screenplay/abilities/BrowseTheWebWithProtractor.d.ts.map +1 -0
  59. package/lib/screenplay/abilities/BrowseTheWebWithProtractor.js +62 -422
  60. package/lib/screenplay/abilities/BrowseTheWebWithProtractor.js.map +1 -1
  61. package/lib/screenplay/abilities/index.d.ts +1 -0
  62. package/lib/screenplay/abilities/index.d.ts.map +1 -0
  63. package/lib/screenplay/abilities/index.js +5 -1
  64. package/lib/screenplay/abilities/index.js.map +1 -1
  65. package/lib/screenplay/index.d.ts +1 -0
  66. package/lib/screenplay/index.d.ts.map +1 -0
  67. package/lib/screenplay/index.js +5 -1
  68. package/lib/screenplay/index.js.map +1 -1
  69. package/lib/screenplay/interactions/UseAngular.d.ts +53 -48
  70. package/lib/screenplay/interactions/UseAngular.d.ts.map +1 -0
  71. package/lib/screenplay/interactions/UseAngular.js +52 -42
  72. package/lib/screenplay/interactions/UseAngular.js.map +1 -1
  73. package/lib/screenplay/interactions/index.d.ts +1 -0
  74. package/lib/screenplay/interactions/index.d.ts.map +1 -0
  75. package/lib/screenplay/interactions/index.js +5 -1
  76. package/lib/screenplay/interactions/index.js.map +1 -1
  77. package/lib/screenplay/models/ProtractorBrowsingSession.d.ts +22 -0
  78. package/lib/screenplay/models/ProtractorBrowsingSession.d.ts.map +1 -0
  79. package/lib/screenplay/models/ProtractorBrowsingSession.js +99 -0
  80. package/lib/screenplay/models/ProtractorBrowsingSession.js.map +1 -0
  81. package/lib/screenplay/models/ProtractorCookie.d.ts +6 -0
  82. package/lib/screenplay/models/ProtractorCookie.d.ts.map +1 -0
  83. package/lib/screenplay/models/ProtractorCookie.js +8 -3
  84. package/lib/screenplay/models/ProtractorCookie.js.map +1 -1
  85. package/lib/screenplay/models/ProtractorErrorHandler.d.ts +8 -0
  86. package/lib/screenplay/models/ProtractorErrorHandler.d.ts.map +1 -0
  87. package/lib/screenplay/models/ProtractorErrorHandler.js +23 -0
  88. package/lib/screenplay/models/ProtractorErrorHandler.js.map +1 -0
  89. package/lib/screenplay/models/ProtractorModalDialogHandler.d.ts +25 -0
  90. package/lib/screenplay/models/ProtractorModalDialogHandler.d.ts.map +1 -0
  91. package/lib/screenplay/models/ProtractorModalDialogHandler.js +74 -0
  92. package/lib/screenplay/models/ProtractorModalDialogHandler.js.map +1 -0
  93. package/lib/screenplay/models/ProtractorPage.d.ts +58 -6
  94. package/lib/screenplay/models/ProtractorPage.d.ts.map +1 -0
  95. package/lib/screenplay/models/ProtractorPage.js +221 -44
  96. package/lib/screenplay/models/ProtractorPage.js.map +1 -1
  97. package/lib/screenplay/models/ProtractorPageElement.d.ts +10 -1
  98. package/lib/screenplay/models/ProtractorPageElement.d.ts.map +1 -0
  99. package/lib/screenplay/models/ProtractorPageElement.js +141 -147
  100. package/lib/screenplay/models/ProtractorPageElement.js.map +1 -1
  101. package/lib/screenplay/models/index.d.ts +2 -1
  102. package/lib/screenplay/models/index.d.ts.map +1 -0
  103. package/lib/screenplay/models/index.js +6 -2
  104. package/lib/screenplay/models/index.js.map +1 -1
  105. package/lib/screenplay/models/locators/ProtractorLocator.d.ts +21 -8
  106. package/lib/screenplay/models/locators/ProtractorLocator.d.ts.map +1 -0
  107. package/lib/screenplay/models/locators/ProtractorLocator.js +107 -10
  108. package/lib/screenplay/models/locators/ProtractorLocator.js.map +1 -1
  109. package/lib/screenplay/models/locators/ProtractorRootLocator.d.ts +17 -0
  110. package/lib/screenplay/models/locators/ProtractorRootLocator.d.ts.map +1 -0
  111. package/lib/screenplay/models/locators/ProtractorRootLocator.js +38 -0
  112. package/lib/screenplay/models/locators/ProtractorRootLocator.js.map +1 -0
  113. package/lib/screenplay/models/locators/index.d.ts +2 -1
  114. package/lib/screenplay/models/locators/index.d.ts.map +1 -0
  115. package/lib/screenplay/models/locators/index.js +6 -2
  116. package/lib/screenplay/models/locators/index.js.map +1 -1
  117. package/lib/screenplay/promised.d.ts +3 -3
  118. package/lib/screenplay/promised.d.ts.map +1 -0
  119. package/lib/screenplay/promised.js +2 -3
  120. package/lib/screenplay/promised.js.map +1 -1
  121. package/lib/screenplay/questions/ProtractorParam.d.ts +64 -51
  122. package/lib/screenplay/questions/ProtractorParam.d.ts.map +1 -0
  123. package/lib/screenplay/questions/ProtractorParam.js +59 -47
  124. package/lib/screenplay/questions/ProtractorParam.js.map +1 -1
  125. package/lib/screenplay/questions/index.d.ts +1 -0
  126. package/lib/screenplay/questions/index.d.ts.map +1 -0
  127. package/lib/screenplay/questions/index.js +5 -1
  128. package/lib/screenplay/questions/index.js.map +1 -1
  129. package/lib/screenplay/unpromisedWebElement.d.ts +6 -4
  130. package/lib/screenplay/unpromisedWebElement.d.ts.map +1 -0
  131. package/lib/screenplay/unpromisedWebElement.js +5 -4
  132. package/lib/screenplay/unpromisedWebElement.js.map +1 -1
  133. package/package.json +36 -60
  134. package/src/adapter/Config.ts +10 -9
  135. package/src/adapter/ProtractorFrameworkAdapter.ts +16 -10
  136. package/src/adapter/browser-detector/BrowserDetector.ts +3 -3
  137. package/src/adapter/browser-detector/StandardisedCapabilities.ts +24 -24
  138. package/src/adapter/index.ts +1 -0
  139. package/src/adapter/reporter/ProtractorReport.ts +4 -6
  140. package/src/adapter/reporter/ProtractorReporter.ts +16 -16
  141. package/src/adapter/run.ts +6 -4
  142. package/src/adapter/runner/CucumberAdapterConfig.ts +5 -10
  143. package/src/adapter/runner/TestRunnerDetector.ts +5 -13
  144. package/src/adapter/runner/TestRunnerLoader.ts +21 -19
  145. package/src/screenplay/abilities/BrowseTheWebWithProtractor.ts +63 -480
  146. package/src/screenplay/interactions/UseAngular.ts +55 -44
  147. package/src/screenplay/models/ProtractorBrowsingSession.ts +133 -0
  148. package/src/screenplay/models/ProtractorCookie.ts +8 -3
  149. package/src/screenplay/models/ProtractorErrorHandler.ts +23 -0
  150. package/src/screenplay/models/ProtractorModalDialogHandler.ts +97 -0
  151. package/src/screenplay/models/ProtractorPage.ts +282 -54
  152. package/src/screenplay/models/ProtractorPageElement.ts +160 -165
  153. package/src/screenplay/models/index.ts +1 -1
  154. package/src/screenplay/models/locators/ProtractorLocator.ts +121 -31
  155. package/src/screenplay/models/locators/ProtractorRootLocator.ts +41 -0
  156. package/src/screenplay/models/locators/index.ts +1 -1
  157. package/src/screenplay/promised.ts +2 -3
  158. package/src/screenplay/questions/ProtractorParam.ts +62 -49
  159. package/src/screenplay/unpromisedWebElement.ts +5 -4
  160. package/tsconfig.build.json +14 -0
  161. package/lib/screenplay/models/ProtractorModalDialog.d.ts +0 -11
  162. package/lib/screenplay/models/ProtractorModalDialog.js +0 -43
  163. package/lib/screenplay/models/ProtractorModalDialog.js.map +0 -1
  164. package/lib/screenplay/models/locators/ProtractorNativeElementRoot.d.ts +0 -5
  165. package/lib/screenplay/models/locators/ProtractorNativeElementRoot.js +0 -3
  166. package/lib/screenplay/models/locators/ProtractorNativeElementRoot.js.map +0 -1
  167. package/src/screenplay/models/ProtractorModalDialog.ts +0 -49
  168. package/src/screenplay/models/locators/ProtractorNativeElementRoot.ts +0 -6
  169. package/tsconfig.eslint.json +0 -10
@@ -1,38 +1,263 @@
1
- import { Page } from '@serenity-js/web';
2
- import { ProtractorBrowser } from 'protractor';
1
+ import { LogicError } from '@serenity-js/core';
2
+ import { CorrelationId } from '@serenity-js/core/lib/model';
3
+ import { BrowserWindowClosedError, Cookie, CookieData, Key, ModalDialogHandler, Page, PageElement, PageElements, Selector } from '@serenity-js/web';
4
+ import { ElementFinder, ProtractorBrowser } from 'protractor';
3
5
  import { URL } from 'url';
4
6
 
5
7
  import { promised } from '../promised';
8
+ import { ProtractorLocator, ProtractorRootLocator } from './locators';
9
+ import { ProtractorBrowsingSession } from './ProtractorBrowsingSession';
10
+ import { ProtractorCookie } from './ProtractorCookie';
11
+ import { ProtractorErrorHandler } from './ProtractorErrorHandler';
12
+ import { ProtractorPageElement } from './ProtractorPageElement';
13
+
14
+ /**
15
+ * Protractor-specific implementation of {@apilink Page}.
16
+ *
17
+ * @group Models
18
+ */
19
+ export class ProtractorPage extends Page<ElementFinder> {
20
+
21
+ /**
22
+ * @private
23
+ */
24
+ private lastScriptExecutionSummary: LastScriptExecutionSummary;
6
25
 
7
- export class ProtractorPage extends Page {
8
26
  constructor(
27
+ session: ProtractorBrowsingSession,
9
28
  private readonly browser: ProtractorBrowser,
10
- handle: string
29
+ modalDialogHandler: ModalDialogHandler,
30
+ private readonly errorHandler: ProtractorErrorHandler,
31
+ pageId: CorrelationId
11
32
  ) {
12
- super(handle);
33
+ super(
34
+ session,
35
+ new ProtractorRootLocator(browser),
36
+ modalDialogHandler,
37
+ pageId,
38
+ );
39
+ }
40
+
41
+ locate(selector: Selector): PageElement<ElementFinder> {
42
+ return new ProtractorPageElement(
43
+ new ProtractorLocator(this.rootLocator, selector, this.errorHandler)
44
+ )
45
+ }
46
+
47
+ locateAll(selector: Selector): PageElements<ElementFinder> {
48
+ return new PageElements(
49
+ new ProtractorLocator(this.rootLocator, selector, this.errorHandler)
50
+ );
51
+ }
52
+
53
+ /**
54
+ * If set to `false`, Protractor will not wait for Angular 1.x `$http` and `$timeout`
55
+ * tasks to complete before interacting with the browser.
56
+ *
57
+ * This can be useful when:
58
+ * - you need to switch to a non-Angular app during your tests, e.g. to sign in using an SSO gateway
59
+ * - your app continuously polls an API with `$timeout`
60
+ *
61
+ * If you're not testing an Angular app, it's better to disable Angular synchronisation completely
62
+ * in protractor configuration:
63
+ *
64
+ * ```js
65
+ * // protractor.conf.js
66
+ * exports.config = {
67
+ * onPrepare: function () {
68
+ * return browser.waitForAngularEnabled(false)
69
+ * },
70
+ *
71
+ * // ... other config
72
+ * }
73
+ * ```
74
+ *
75
+ * @param enable
76
+ */
77
+ async enableAngularSynchronisation(enable: boolean): Promise<boolean> {
78
+ return await this.inContextOfThisPage(() => {
79
+ return promised(this.browser.waitForAngularEnabled(enable));
80
+ });
81
+ }
82
+
83
+ async navigateTo(destination: string): Promise<void> {
84
+ return await this.inContextOfThisPage(() => {
85
+ return promised(this.browser.get(destination));
86
+ });
87
+ }
88
+
89
+ async navigateBack(): Promise<void> {
90
+ return await this.inContextOfThisPage(() => {
91
+ return promised(this.browser.navigate().back());
92
+ });
93
+ }
94
+
95
+ async navigateForward(): Promise<void> {
96
+ return await this.inContextOfThisPage(() => {
97
+ return promised(this.browser.navigate().forward());
98
+ });
99
+ }
100
+
101
+ async reload(): Promise<void> {
102
+ return await this.inContextOfThisPage(() => {
103
+ return promised(this.browser.navigate().refresh());
104
+ });
105
+ }
106
+
107
+ async sendKeys(keys: (string | Key)[]): Promise<void> {
108
+ function isModifier(maybeKey: string | Key): boolean {
109
+ return Key.isKey(maybeKey) && maybeKey.isModifier;
110
+ }
111
+
112
+ function asCodePoint(maybeKey: string | Key): string {
113
+ if (! Key.isKey(maybeKey)) {
114
+ return maybeKey;
115
+ }
116
+
117
+ return maybeKey.utf16codePoint;
118
+ }
119
+
120
+ return await this.inContextOfThisPage(() => {
121
+ // keyDown for any modifier keys and sendKeys otherwise
122
+ const keyDownActions = keys.reduce((actions, key) => {
123
+ return isModifier(key)
124
+ ? actions.keyDown(asCodePoint(key))
125
+ : actions.sendKeys(asCodePoint(key))
126
+ }, this.browser.actions());
127
+
128
+ // keyUp for any modifier keys, ignore for regular keys
129
+ const keyUpActions = keys.reduce((actions, key) => {
130
+ return isModifier(key)
131
+ ? actions.keyUp(asCodePoint(key))
132
+ : actions;
133
+ }, keyDownActions);
134
+
135
+ return promised(keyUpActions.perform());
136
+ });
137
+ }
138
+
139
+ async executeScript<Result, InnerArguments extends any[]>(
140
+ script: string | ((...parameters: InnerArguments) => Result),
141
+ ...args: InnerArguments
142
+ ): Promise<Result> {
143
+ const innerArguments = [] as InnerArguments;
144
+ for (const arg of args) {
145
+ const innerArgument = arg instanceof ProtractorPageElement
146
+ ? await arg.nativeElement()
147
+ : arg;
148
+
149
+ innerArguments.push(innerArgument);
150
+ }
151
+
152
+ const result = await this.inContextOfThisPage<Result>(() => {
153
+ return promised(this.browser.executeScript(script, ...innerArguments));
154
+ });
155
+
156
+ this.lastScriptExecutionSummary = new LastScriptExecutionSummary(result);
157
+
158
+ return result;
159
+ }
160
+
161
+ async executeAsyncScript<Result, Parameters extends any[]>(
162
+ script: string | ((...args: [...parameters: Parameters, callback: (result: Result) => void]) => void),
163
+ ...args: Parameters
164
+ ): Promise<Result> {
165
+ const parameters = [] as Parameters;
166
+ for (const arg of args) {
167
+ const parameter = arg instanceof ProtractorPageElement
168
+ ? await arg.nativeElement()
169
+ : arg;
170
+
171
+ parameters.push(parameter);
172
+ }
173
+
174
+ const result = await this.inContextOfThisPage<Result>(() => {
175
+ return promised(this.browser.executeAsyncScript(script, ...parameters));
176
+ });
177
+
178
+ this.lastScriptExecutionSummary = new LastScriptExecutionSummary(result);
179
+
180
+ return result;
181
+ }
182
+
183
+ lastScriptExecutionResult(): any {
184
+ if (! this.lastScriptExecutionSummary) {
185
+ throw new LogicError(`Make sure to execute a script before checking on the result`);
186
+ }
187
+
188
+ // Selenium 3 returns `null` when the script it executed returns `undefined`
189
+ // so we're mapping the result back.
190
+ return this.lastScriptExecutionSummary.result === null
191
+ ? undefined
192
+ : this.lastScriptExecutionSummary.result;
193
+ }
194
+
195
+ async takeScreenshot(): Promise<string> {
196
+ return await this.inContextOfThisPage(() => {
197
+ try {
198
+ return promised(this.browser.takeScreenshot());
199
+ }
200
+ catch (error) {
201
+
202
+ if (error.name && error.name === 'NoSuchSessionError') {
203
+ throw new BrowserWindowClosedError(
204
+ 'Browser window is not available to take a screenshot',
205
+ error,
206
+ );
207
+ }
208
+
209
+ throw error;
210
+ }
211
+ });
212
+ }
213
+
214
+ async cookie(name: string): Promise<Cookie> {
215
+ return new ProtractorCookie(this.browser, name);
216
+ }
217
+
218
+ async setCookie(cookieData: CookieData): Promise<void> {
219
+ return await this.inContextOfThisPage(() => {
220
+ return promised(this.browser.manage().addCookie({
221
+ name: cookieData.name,
222
+ value: cookieData.value,
223
+ path: cookieData.path,
224
+ domain: cookieData.domain,
225
+ secure: cookieData.secure,
226
+ httpOnly: cookieData.httpOnly,
227
+ expiry: cookieData.expiry
228
+ ? cookieData.expiry.toSeconds()
229
+ : undefined,
230
+ }));
231
+ });
13
232
  }
14
233
 
15
- title(): Promise<string> {
16
- return this.switchToAndPerform(async browser => {
17
- return promised(browser.getTitle());
234
+ async deleteAllCookies(): Promise<void> {
235
+ return await this.inContextOfThisPage(() => {
236
+ return promised(this.browser.manage().deleteAllCookies());
18
237
  });
19
238
  }
20
239
 
21
- name(): Promise<string> {
22
- return this.switchToAndPerform(async browser => {
23
- return promised(browser.executeScript('return window.name'));
240
+ async title(): Promise<string> {
241
+ return await this.inContextOfThisPage(() => {
242
+ return promised(this.browser.getTitle());
24
243
  });
25
244
  }
26
245
 
27
- url(): Promise<URL> {
28
- return this.switchToAndPerform(async browser => {
29
- return new URL(await promised(browser.getCurrentUrl()));
246
+ async name(): Promise<string> {
247
+ return await this.inContextOfThisPage(() => {
248
+ return promised(this.browser.executeScript('return window.name'));
249
+ });
250
+ }
251
+
252
+ async url(): Promise<URL> {
253
+ return await this.inContextOfThisPage(async () => {
254
+ return new URL(await promised(this.browser.getCurrentUrl()));
30
255
  });
31
256
  }
32
257
 
33
258
  async viewportSize(): Promise<{ width: number, height: number }> {
34
- return this.switchToAndPerform(async browser => {
35
- const calculatedViewportSize = await promised(browser.executeScript(
259
+ return await this.inContextOfThisPage(async () => {
260
+ const calculatedViewportSize = await promised(this.browser.executeScript(
36
261
  `return {
37
262
  width: Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
38
263
  height: Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
@@ -44,13 +269,13 @@ export class ProtractorPage extends Page {
44
269
  }
45
270
 
46
271
  // Chrome headless hard-codes window.innerWidth and window.innerHeight to 0
47
- return promised(browser.manage().window().getSize());
272
+ return await promised(this.browser.manage().window().getSize());
48
273
  });
49
274
  }
50
275
 
51
276
  async setViewportSize(size: { width: number, height: number }): Promise<void> {
52
- return this.switchToAndPerform(async browser => {
53
- const desiredWindowSize: { width: number, height: number } = await promised(browser.executeScript(`
277
+ return await this.inContextOfThisPage(async () => {
278
+ const desiredWindowSize: { width: number, height: number } = await promised(this.browser.executeScript(`
54
279
  var currentViewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
55
280
  var currentViewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
56
281
 
@@ -60,57 +285,60 @@ export class ProtractorPage extends Page {
60
285
  };
61
286
  `));
62
287
 
63
- return promised(browser.manage().window().setSize(desiredWindowSize.width, desiredWindowSize.height));
288
+ return promised(this.browser.manage().window().setSize(desiredWindowSize.width, desiredWindowSize.height));
64
289
  });
65
290
  }
66
291
 
67
292
  async close(): Promise<void> {
68
- return this.switchToAndPerform(browser => promised(browser.close()));
293
+ try {
294
+ await this.inContextOfThisPage(async () => {
295
+ await promised(this.browser.close())
296
+ });
297
+ } catch (error) {
298
+ if (error.name !== 'NoSuchWindowError') {
299
+ throw error
300
+ }
301
+ }
69
302
  }
70
303
 
71
304
  async closeOthers(): Promise<void> {
72
- const windowHandles = await this.browser.getAllWindowHandles();
305
+ await this.session.closePagesOtherThan(this);
306
+ }
73
307
 
74
- for (const handle of windowHandles) {
75
- if (handle !== this.handle) {
76
- await this.browser.switchTo().window(handle);
77
- await this.browser.close();
308
+ async isPresent(): Promise<boolean> {
309
+ const allPages = await this.session.allPages();
310
+ for (const page of allPages) {
311
+ if (page === this) {
312
+ return true;
78
313
  }
79
314
  }
80
-
81
- await this.browser.switchTo().window(this.handle);
315
+ return false;
82
316
  }
83
317
 
84
- async isPresent(): Promise<boolean> {
85
- const currentPageHandle = await this.browser.getWindowHandle();
86
- const desiredPageHandle = this.handle;
87
-
88
- const isOpen = await this.browser.switchTo().window(desiredPageHandle).then(() => true, _error => false);
89
-
90
- await this.browser.switchTo().window(currentPageHandle);
318
+ private async inContextOfThisPage<T>(action: () => Promise<T> | T): Promise<T> {
319
+ let originalPage;
91
320
 
92
- return isOpen;
93
- }
94
-
95
- async switchTo(): Promise<void> {
96
- await this.browser.switchTo().window(this.handle);
97
- }
321
+ try {
322
+ originalPage = await this.session.currentPage();
98
323
 
99
- private async switchToAndPerform<T>(action: (browser: ProtractorBrowser) => Promise<T> | T): Promise<T> {
100
- const originalPageHandle = await this.browser.getWindowHandle();
101
- const desiredPageHandle = this.handle;
102
- const shouldSwitch = originalPageHandle !== desiredPageHandle;
324
+ await this.session.changeCurrentPageTo(this);
103
325
 
104
- if (shouldSwitch) {
105
- await this.browser.switchTo().window(desiredPageHandle);
326
+ return await action();
106
327
  }
107
-
108
- const result = await action(this.browser);
109
-
110
- if (shouldSwitch) {
111
- await this.browser.switchTo().window(originalPageHandle);
328
+ catch (error) {
329
+ return await this.errorHandler.executeIfHandled(error, action);
330
+ }
331
+ finally {
332
+ if (originalPage) {
333
+ await this.session.changeCurrentPageTo(originalPage);
334
+ }
112
335
  }
113
-
114
- return result;
115
336
  }
116
337
  }
338
+
339
+ /**
340
+ * @package
341
+ */
342
+ class LastScriptExecutionSummary {
343
+ constructor(public readonly result: any) {}
344
+ }