forked from webdriverio/webdriverio
-
Notifications
You must be signed in to change notification settings - Fork 0
Wdio Percy support v8 #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
amaanbs
wants to merge
44
commits into
main
Choose a base branch
from
wdio_percy_support_v8
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
933fcae
Add support for Percy
amaanbs a007216
es-lint fixes
amaanbs c85e2b1
binary download fix
amaanbs d1cba84
Merge branch 'main' of github.com:amaanbs/webdriverio into wdio_percy…
amaanbs 02a7706
resolve merge conflicts
amaanbs f165eaf
add error handling
amaanbs 4f6d8ca
best platform for caps as objects
amaanbs ffca74b
minor fix
amaanbs f7a9ca1
minor fixes
amaanbs abd6493
added unit tests
amaanbs 3047eb2
ts-lint fixes
amaanbs b29658a
PR review fixes
amaanbs 497c10f
add package-lock.json
amaanbs f6ee31b
minor fixes
amaanbs f067682
Screenshot stabilization + default mode = auto
amaanbs dafa563
PR review fixes
amaanbs a7a9397
Merge branch 'main' of github.com:amaanbs/webdriverio into wdio_percy…
amaanbs 42b9e06
Fix test failure import
amaanbs b8e8755
update tests
amaanbs 7c7b1ab
PR review fixes
amaanbs 6819cf2
Merge branch 'main' of github.com:amaanbs/webdriverio into wdio_percy…
amaanbs 907de46
Merge branch 'main' of github.com:amaanbs/webdriverio into wdio_percy…
rev-doshi 1315406
Merge branch 'main' of github.com:amaanbs/webdriverio into wdio_percy…
rev-doshi e8d6b94
review changes
rev-doshi 4ab0126
linting fix
rev-doshi e9279bb
import fix
rev-doshi 7811083
import fix
rev-doshi 08c222d
test fixes and using # prefix for private fields
rev-doshi 52b38d9
Revert "test fixes and using # prefix for private fields"
rev-doshi a0b80e5
test fix
rev-doshi b438b1f
review comments fix
rev-doshi 425e941
percy packages changes
rev-doshi 7b07fa3
Merge pull request #3 from rev-doshi/wdio_percy_support_v8
rev-doshi 5d5d033
conflict resolution
rev-doshi 436e132
package-lock fix
rev-doshi 463e3b4
review changes
rev-doshi 7b4503c
review changes
rev-doshi 68e13ce
review changes
rev-doshi fdfcf82
Merge branch 'main' of github.com:amaanbs/webdriverio into wdio_percy…
rev-doshi 77bc0fe
minor fix
rev-doshi 250ed1d
review changes
rev-doshi 0f01b16
master merge and UT fix
rev-doshi a84203b
master merge
rev-doshi d39f702
minor fix
rev-doshi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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
183 changes: 183 additions & 0 deletions
183
packages/wdio-browserstack-service/src/Percy/Percy-Handler.ts
This file contains hidden or 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,183 @@ | ||
| import type { Capabilities } from '@wdio/types' | ||
| import type { BeforeCommandArgs, AfterCommandArgs } from '@wdio/reporter' | ||
|
|
||
| import { | ||
| o11yClassErrorHandler, | ||
| sleep | ||
| } from '../util.js' | ||
| import PercyCaptureMap from './PercyCaptureMap.js' | ||
|
|
||
| import * as PercySDK from './PercySDK.js' | ||
| import { PercyLogger } from './PercyLogger.js' | ||
|
|
||
| import { PERCY_DOM_CHANGING_COMMANDS_ENDPOINTS, CAPTURE_MODES } from '../constants.js' | ||
|
|
||
| class _PercyHandler { | ||
| private _testMetadata: { [key: string]: any } = {} | ||
| private _sessionName?: string | ||
| private _isPercyCleanupProcessingUnderway?: boolean = false | ||
| private _percyScreenshotCounter: any = 0 | ||
| private _percyDeferredScreenshots: any = [] | ||
| private _percyScreenshotInterval: any = null | ||
| private _percyCaptureMap?: PercyCaptureMap | ||
|
|
||
| constructor ( | ||
| private _percyAutoCaptureMode: string | undefined, | ||
| private _browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, | ||
| private _capabilities: Capabilities.RemoteCapability, | ||
| private _isAppAutomate?: boolean, | ||
| private _framework?: string | ||
| ) { | ||
| if (!_percyAutoCaptureMode || !CAPTURE_MODES.includes(_percyAutoCaptureMode as string)) { | ||
| this._percyAutoCaptureMode = 'auto' | ||
| } | ||
| } | ||
|
|
||
| _setSessionName(name: string) { | ||
| this._sessionName = name | ||
| } | ||
|
|
||
| async teardown () { | ||
| await new Promise<void>((resolve) => { | ||
| setInterval(() => { | ||
| if (this._percyScreenshotCounter === 0) { | ||
| resolve() | ||
| } | ||
| }, 1000) | ||
| }) | ||
| } | ||
|
|
||
| async percyAutoCapture(eventName: string | null, sessionName: string | null) { | ||
| try { | ||
| if (eventName) { | ||
| if (!sessionName) { | ||
| /* Service doesn't wait for handling of browser commands so the below counter is used in teardown method to delay service exit */ | ||
| this._percyScreenshotCounter += 1 | ||
| } | ||
|
|
||
| this._percyCaptureMap?.increment(sessionName ? sessionName : (this._sessionName as string), eventName) | ||
| await (this._isAppAutomate ? PercySDK.screenshotApp(this._percyCaptureMap?.getName( sessionName ? sessionName : (this._sessionName as string), eventName)) : await PercySDK.screenshot(this._browser, this._percyCaptureMap?.getName( sessionName ? sessionName : (this._sessionName as string), eventName))) | ||
| this._percyScreenshotCounter -= 1 | ||
| } | ||
| } catch (err: any) { | ||
| this._percyScreenshotCounter -= 1 | ||
| this._percyCaptureMap?.decrement(sessionName ? sessionName : (this._sessionName as string), eventName as string) | ||
| PercyLogger.error(`Error while trying to auto capture Percy screenshot ${err}`) | ||
| } | ||
| } | ||
|
|
||
| async before () { | ||
| this._percyCaptureMap = new PercyCaptureMap() | ||
| } | ||
|
|
||
| deferCapture(sessionName: string, eventName: string | null) { | ||
| /* Service doesn't wait for handling of browser commands so the below counter is used in teardown method to delay service exit */ | ||
| this._percyScreenshotCounter += 1 | ||
| this._percyDeferredScreenshots.push({ sessionName, eventName }) | ||
| } | ||
|
|
||
| isDOMChangingCommand(args: BeforeCommandArgs): boolean { | ||
| /* | ||
| Percy screenshots which are to be taken on events such as send keys, element click & screenshot are deferred until | ||
| another DOM changing command is seen such that any DOM processing post the previous command is completed | ||
| */ | ||
| return ( | ||
| typeof args.method === 'string' && typeof args.endpoint === 'string' && | ||
| ( | ||
| ( | ||
| args.method === 'POST' && | ||
| ( | ||
| PERCY_DOM_CHANGING_COMMANDS_ENDPOINTS.includes(args.endpoint) || | ||
| ( | ||
| /* click / clear element */ | ||
| args.endpoint.includes('/session/:sessionId/element') && | ||
| ( | ||
| args.endpoint.includes('click') || | ||
| args.endpoint.includes('clear') | ||
| ) | ||
| ) || | ||
| /* execute script sync / async */ | ||
| (args.endpoint.includes('/session/:sessionId/execute') && args.body?.script) || | ||
| /* Touch action for Appium */ | ||
| (args.endpoint.includes('/session/:sessionId/touch')) | ||
| ) | ||
| ) || | ||
| ( args.method === 'DELETE' && args.endpoint === '/session/:sessionId' ) | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| async cleanupDeferredScreenshots() { | ||
| this._isPercyCleanupProcessingUnderway = true | ||
| for (const entry of this._percyDeferredScreenshots) { | ||
| await this.percyAutoCapture(entry.eventName, entry.sessionName) | ||
| } | ||
| this._percyDeferredScreenshots = [] | ||
| this._isPercyCleanupProcessingUnderway = false | ||
| } | ||
|
|
||
| async browserBeforeCommand (args: BeforeCommandArgs) { | ||
| try { | ||
| if (!this.isDOMChangingCommand(args)) { | ||
| return | ||
| } | ||
| do { | ||
| await sleep(1000) | ||
| } while (this._percyScreenshotInterval) | ||
| this._percyScreenshotInterval = setInterval(async () => { | ||
| if (!this._isPercyCleanupProcessingUnderway) { | ||
| clearInterval(this._percyScreenshotInterval) | ||
| await this.cleanupDeferredScreenshots() | ||
| this._percyScreenshotInterval = null | ||
| } | ||
| }, 1000) | ||
| } catch (err: any) { | ||
| PercyLogger.error(`Error while trying to cleanup deferred screenshots ${err}`) | ||
| } | ||
| } | ||
|
|
||
| async browserAfterCommand (args: BeforeCommandArgs & AfterCommandArgs) { | ||
| try { | ||
| if (!args.endpoint || !this._percyAutoCaptureMode) { | ||
| return | ||
| } | ||
| let eventName = null | ||
| const endpoint = args.endpoint as string | ||
| if (endpoint.includes('click') && ['click', 'auto'].includes(this._percyAutoCaptureMode as string)) { | ||
| eventName = 'click' | ||
| } else if (endpoint.includes('screenshot') && ['screenshot', 'auto'].includes(this._percyAutoCaptureMode as string)) { | ||
| eventName = 'screenshot' | ||
| } else if (endpoint.includes('actions') && ['auto'].includes(this._percyAutoCaptureMode as string)) { | ||
| if (args.body && args.body.actions && Array.isArray(args.body.actions) && args.body.actions.length && args.body.actions[0].type === 'key') { | ||
| eventName = 'keys' | ||
| } | ||
| } else if (endpoint.includes('/session/:sessionId/element') && endpoint.includes('value') && ['auto'].includes(this._percyAutoCaptureMode as string)) { | ||
| eventName = 'keys' | ||
| } | ||
| if (eventName) { | ||
| this.deferCapture(this._sessionName as string, eventName) | ||
| } | ||
| } catch (err: any) { | ||
| PercyLogger.error(`Error while trying to calculate auto capture parameters ${err}`) | ||
| } | ||
| } | ||
|
|
||
| async afterTest () { | ||
| if (this._percyAutoCaptureMode && this._percyAutoCaptureMode === 'testcase') { | ||
| await this.percyAutoCapture('testcase', null) | ||
| } | ||
| } | ||
|
|
||
| async afterScenario () { | ||
| if (this._percyAutoCaptureMode && this._percyAutoCaptureMode === 'testcase') { | ||
| await this.percyAutoCapture('testcase', null) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // https://github.com/microsoft/TypeScript/issues/6543 | ||
| const PercyHandler: typeof _PercyHandler = o11yClassErrorHandler(_PercyHandler) | ||
| type PercyHandler = _PercyHandler | ||
|
|
||
| export default PercyHandler | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.