Repository: elastic/synthetics
Pull request #353 (2021-07-22 00:23:38)

fix: record correct screenshots for popups
+ part of #253 
+ captures proper screenshots for new navigations done via popups and new tabs.
+ Listens for `page` events in each step and captures the screenshot of last navigation that happened in the step. 

### Tested using inline script for popups and navigation
```js
 step('Popup Landing Page', async () => {
  await page.goto(`http://localhost:8080/popup1.html`);
  await page.waitForSelector('text=Test popup page 1');
});
step('Open Popup', async () => {
  const [popup] = await Promise.all([
    page.waitForEvent('popup'),
    page.click('#linkWithPopup'),
  ]);
  // Test 2 - new tab (not new popup window)
  await Promise.all([
    context.waitForEvent('page'),
    page.click('#linkWithPopupNoNewWindow'),
  ]);
});

```

### Screenshots

<img width="689" alt="Screen Shot 2021-07-21 at 17 00 12" src="https://user-images.githubusercontent.com/3902525/126575596-fb24c1c9-f8a9-4d6f-90f6-62fed19037c1.png">
<img width="623" alt="Screen Shot 2021-07-21 at 17 00 02" src="https://user-images.githubusercontent.com/3902525/126575599-7d53d7c0-34eb-4348-8465-d31b37c3d2e7.png">




apmmachine: 
## :green_heart: Build Succeeded


<!-- BUILD BADGES-->
> _the below badges are clickable and redirect to their specific view in the CI or DOCS_
[![Pipeline View](https://img.shields.io/badge/pipeline-pipeline%20-green)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-rum%2Felastic-synthetics%2FPR-353/detail/PR-353/1//pipeline) [![Test View](https://img.shields.io/badge/test-test-green)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-rum%2Felastic-synthetics%2FPR-353/detail/PR-353/1//tests) [![Changes](https://img.shields.io/badge/changes-changes-green)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-rum%2Felastic-synthetics%2FPR-353/detail/PR-353/1//changes) [![Artifacts](https://img.shields.io/badge/artifacts-artifacts-yellow)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-rum%2Felastic-synthetics%2FPR-353/detail/PR-353/1//artifacts) [![preview](https://img.shields.io/badge/docs-preview-yellowgreen)](http://synthetics_353.docs-preview.app.elstc.co/diff)  [![preview](https://img.shields.io/badge/elastic-observability-blue)](https://ci-stats.elastic.co/app/apm/services/apm-ci/transactions/view?rangeFrom=2021-07-22T00:13:55.400Z&rangeTo=2021-07-22T00:33:55.400Z&transactionName=apm-agent-rum/elastic-synthetics/PR-{number}&transactionType=unknown&latencyAggregationType=avg&traceId=43567196ea738f99fa14d8e68fe0570d&transactionId=578795e6e044675a)

<!-- BUILD SUMMARY-->
<details><summary>Expand to view the summary</summary>
<p>

#### Build stats




* Start Time: 2021-07-22T00:23:55.400+0000


* Duration: 15 min 17 sec


* Commit: de33283d3b13292688bfa511e36b1d87d89d531b



#### Test stats :test_tube:

| Test         | Results                         |
| ------------ | :-----------------------------: |
| Failed       | 0  |
| Passed       | 120  |
| Skipped      | 0 |
| Total        | 120   |


#### Trends :test_tube:


![Image of Build Times](https://apm-ci.elastic.co/job/apm-agent-rum/job/elastic-synthetics/job/PR-353/buildTimeGraph/png)


![Image of Tests](https://apm-ci.elastic.co/job/apm-agent-rum/job/elastic-synthetics/job/PR-353/1/testReport/history/countGraph/png?start=0&amp;end=25)


</p>
</details>

<!-- TEST RESULTS IF ANY-->


<!-- STEPS ERRORS IF ANY -->












<!--COMMENT_GENERATED_WITH_ID_comment.id-->
vigneshshanmugam: > Also, if a user wants to switch the focus back to the original page how does that work? Looking at the code it looks like you'd need to close the popup. Is that right? If so, we should document that.

Not sure if that should be documented, the active window in the step should be screenshoted, otherwise we need to come up with a plan of having multiple screenshots per step if there are more than one active window/pageg. 

Patch:
diff --git a/src/cli.ts b/src/cli.ts
index 9ea3bc1..e31c8f6 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -51,9 +51,16 @@ if (process.env.DEBUG === namespace || Boolean(options.debug)) {
 }
 
 const loadInlineScript = source => {
-  const scriptFn = new Function('step', 'page', 'browser', 'params', source);
-  journey('inline', async ({ page, browser, params }) => {
-    scriptFn.apply(null, [step, page, browser, params]);
+  const scriptFn = new Function(
+    'step',
+    'page',
+    'context',
+    'browser',
+    'params',
+    source
+  );
+  journey('inline', async ({ page, context, browser, params }) => {
+    scriptFn.apply(null, [step, page, context, browser, params]);
   });
 };
 
diff --git a/src/core/runner.ts b/src/core/runner.ts
index 6b6f8b7..8b00839 100644
--- a/src/core/runner.ts
+++ b/src/core/runner.ts
@@ -233,6 +233,7 @@ export default class Runner extends EventEmitter {
       driver.context.off('request', captureUrl);
     };
     driver.context.on('request', captureUrl);
+
     try {
       pluginManager.onStep(step);
       await step.callback();
@@ -243,9 +244,19 @@ export default class Runner extends EventEmitter {
       data.status = 'failed';
       data.error = error;
     } finally {
-      data.url ??= driver.page.url();
-      if (screenshots && screenshots !== 'off') {
-        await this.captureScreenshot(driver.page, step);
+      /**
+       * Capture screenshot for the newly created pages
+       * via popup or new windows/tabs
+       *
+       * Last open page will get us the correct screenshot
+       */
+      const pages = driver.context.pages();
+      const page = pages[pages.length - 1];
+      if (page) {
+        data.url ??= page.url();
+        if (screenshots && screenshots !== 'off') {
+          await this.captureScreenshot(page, step);
+        }
       }
     }
     log(`Runner: end step (${step.name})`);


Test patch:
diff --git a/__tests__/core/runner.test.ts b/__tests__/core/runner.test.ts
index 5973895..827be68 100644
--- a/__tests__/core/runner.test.ts
+++ b/__tests__/core/runner.test.ts
@@ -592,4 +592,37 @@ describe('runner', () => {
       },
     ]);
   });
+
+  it('run - differentiate screenshots for popups', async () => {
+    const j1 = journey('j1', async ({ page, context }) => {
+      step('visit test page', async () => {
+        await page.goto(server.TEST_PAGE);
+        await page.setContent(
+          '<a target=_blank rel=noopener href="/popup.html">popup</a>'
+        );
+      });
+      step('click popup', async () => {
+        const [page1] = await Promise.all([
+          context.waitForEvent('page'),
+          page.click('a'),
+        ]);
+        await page1.waitForLoadState();
+      });
+    });
+    runner.addJourney(j1);
+
+    await runner.run({
+      wsEndpoint,
+      reporter: 'json',
+      screenshots: 'on',
+      outfd: fs.openSync(dest, 'w'),
+    });
+
+    const screenshotDocs = readAndCloseStreamJson().filter(
+      ({ type }) => type === 'step/screenshot'
+    );
+    expect(screenshotDocs.length).toEqual(2);
+    const blobs = screenshotDocs.map(data => data.blob);
+    expect(blobs[0]).not.toEqual(blobs[1]);
+  });
 });