-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
misc: Ensure cypress tab is active before any command runs (#28334)
- Loading branch information
1 parent
424d408
commit 06b5ca2
Showing
17 changed files
with
352 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import type { ICypress } from '../cypress' | ||
|
||
const isCypressInCypress = document.defaultView !== top | ||
|
||
function activateMainTab () { | ||
// Don't need to activate the main tab if it already has focus | ||
if (document.hasFocus()) return | ||
|
||
return new Promise<void>((resolve) => { | ||
const url = `${window.location.origin}${window.location.pathname}` | ||
|
||
// This sends a message on the window that the extension content script | ||
// listens for in order to carry out activating the main tab | ||
window.postMessage({ message: 'cypress:extension:activate:main:tab', url }, '*') | ||
|
||
function onMessage ({ data, source }) { | ||
// only accept messages from ourself | ||
if (source !== window) return | ||
|
||
if (data.message === 'cypress:extension:main:tab:activated') { | ||
window.removeEventListener('message', onMessage) | ||
|
||
resolve() | ||
} | ||
} | ||
|
||
// The reply from the extension comes back via the same means, a message | ||
// sent on the window | ||
window.addEventListener('message', onMessage) | ||
}) | ||
} | ||
|
||
// Ensures the main Cypress tab has focus before every command | ||
// and at the end of the test run | ||
export function handleTabActivation (Cypress: ICypress) { | ||
// - Only implemented for Chromium right now. Support for Firefox/webkit | ||
// could be added later | ||
// - Electron doesn't have tabs | ||
// - Focus doesn't matter for headless browsers and old headless Chrome | ||
// doesn't run the extension | ||
// - Don't need to worry about tabs for Cypress in Cypress tests (and they | ||
// can't currently communicate with the extension anyway) | ||
if ( | ||
!Cypress.isBrowser({ family: 'chromium', name: '!electron', isHeadless: false }) | ||
|| isCypressInCypress | ||
) return | ||
|
||
Cypress.on('command:start:async', activateMainTab) | ||
Cypress.on('test:after:run:async', activateMainTab) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* global chrome, window */ | ||
|
||
// this content script has access to the DOM, but is otherwise isolated from | ||
// the page running Cypress, so we have to use postMessage to communicate. it | ||
// also doesn't have direct access to the extension API, so we use the | ||
// messaging API it can access to communicate with the background service | ||
// worker script. so essentially, it's an intermediary between Cypress and | ||
// the extension background script | ||
const port = chrome.runtime.connect() | ||
|
||
// this listens for messages from the main window that Cypress runs on. it's | ||
// a very global message bus, so messages could come from a variety of sources | ||
window.addEventListener('message', ({ data, source }) => { | ||
// only accept messages from ourself | ||
if (source !== window) return | ||
|
||
// this is the only message we're currently interested in, which tells us | ||
// to activate the main tab | ||
if (data.message === 'cypress:extension:activate:main:tab') { | ||
port.postMessage({ message: 'activate:main:tab', url: data.url }) | ||
} | ||
}) | ||
|
||
// this listens for messages from the background service worker script | ||
port.onMessage.addListener(({ message }) => { | ||
// this lets us know the message we sent to the background script to activate | ||
// the main tab was successful, so we in turn send it on to Cypress | ||
// via postMessage | ||
if (message === 'main:tab:activated') { | ||
window.postMessage({ message: 'cypress:extension:main:tab:activated' }, '*') | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* global chrome */ | ||
|
||
// this background script runs in a service worker. it has access to the | ||
// extension API, but not direct access the web page or anything else | ||
// running in the browser | ||
|
||
// to debug this script, go to `chrome://inspect` in a new Chrome tab, | ||
// select Service Workers on the left and click `inspect`. to reload changes | ||
// go to `chrome://extensions` and hit the reload button under the Cypress | ||
// extension. sometimes that doesn't work and requires re-launching Chrome | ||
// and then reloading the extension via `chrome://extensions` | ||
|
||
async function activateMainTab (url) { | ||
try { | ||
const tabs = await chrome.tabs.query({}) | ||
|
||
const cypressTab = tabs.find((tab) => tab.url.includes(url)) | ||
|
||
if (!cypressTab) return | ||
|
||
// this brings the main Cypress tab to the front of any other tabs | ||
// without Chrome stealing focus from other running apps | ||
await chrome.tabs.update(cypressTab.id, { active: true }) | ||
} catch (err) { | ||
// ignore the error but log it. these logs only appear if you inspect | ||
// the service worker, so it won't clutter up the console for users | ||
|
||
// eslint-disable-next-line no-console | ||
console.log('Activating main Cypress tab errored:', err) | ||
} | ||
} | ||
|
||
// here we connect to the content script, which has access to the web page | ||
// running Cypress, but not the extension API | ||
chrome.runtime.onConnect.addListener((port) => { | ||
port.onMessage.addListener(async ({ message, url }) => { | ||
if (message === 'activate:main:tab') { | ||
await activateMainTab(url) | ||
|
||
// send an ack back to let the content script know we successfully | ||
// activated the main tab | ||
port.postMessage({ message: 'main:tab:activated' }) | ||
} | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
06b5ca2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circle has built the
linux x64
version of the Test Runner.Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version
Run this command to install the pre-release locally:
06b5ca2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circle has built the
linux arm64
version of the Test Runner.Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version
Run this command to install the pre-release locally:
06b5ca2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circle has built the
darwin x64
version of the Test Runner.Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version
Run this command to install the pre-release locally:
06b5ca2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circle has built the
darwin arm64
version of the Test Runner.Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version
Run this command to install the pre-release locally:
06b5ca2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circle has built the
win32 x64
version of the Test Runner.Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version
Run this command to install the pre-release locally: