diff --git a/packages/webdriverio/src/utils/actions/base.ts b/packages/webdriverio/src/utils/actions/base.ts index a77b8db51e3..7e6b313afbe 100644 --- a/packages/webdriverio/src/utils/actions/base.ts +++ b/packages/webdriverio/src/utils/actions/base.ts @@ -18,7 +18,14 @@ interface Sequence { value?: string } -let actionIds = 0 +/** + * Separate counters for each action type to ensure W3C WebDriver compliance. + * According to the spec, each input source ID must always map to the same action type + * throughout the session duration. + */ +let keyActionIds = 0 +let pointerActionIds = 0 +let wheelActionIds = 0 export default class BaseAction { #id: string @@ -27,18 +34,41 @@ export default class BaseAction { #instance: WebdriverIO.Browser protected sequence: Sequence[] = [] - constructor ( + constructor( protected instance: WebdriverIO.Browser, type: ActionType, params?: BaseActionParams ) { this.#instance = instance - this.#id = params?.id || `action${++actionIds}` + + /** + * Generate type-specific IDs to prevent conflicts when mixing action types. + * This ensures compliance with W3C WebDriver spec which requires each input + * source ID to consistently map to the same action type. + */ + if (params?.id) { + this.#id = params.id + } else { + switch (type) { + case 'key': + this.#id = `key${++keyActionIds}` + break + case 'pointer': + this.#id = `pointer${++pointerActionIds}` + break + case 'wheel': + this.#id = `wheel${++wheelActionIds}` + break + default: + this.#id = `action${type}` + } + } + this.#type = type this.#parameters = params?.parameters || {} } - toJSON () { + toJSON() { return { id: this.#id, type: this.#type, @@ -51,7 +81,7 @@ export default class BaseAction { * Inserts a pause action for the specified device, ensuring it idles for a tick. * @param duration idle time of tick */ - pause (duration: number) { + pause(duration: number) { this.sequence.push({ type: 'pause', duration }) return this } @@ -60,7 +90,7 @@ export default class BaseAction { * Perform action sequence * @param skipRelease set to true if `releaseActions` command should not be invoked */ - async perform (skipRelease = false) { + async perform(skipRelease = false) { /** * transform chainable / not resolved elements into WDIO elements */ diff --git a/packages/webdriverio/tests/commands/browser/__snapshots__/action.test.ts.snap b/packages/webdriverio/tests/commands/browser/__snapshots__/action.test.ts.snap index ef457f920d3..d7a34980140 100644 --- a/packages/webdriverio/tests/commands/browser/__snapshots__/action.test.ts.snap +++ b/packages/webdriverio/tests/commands/browser/__snapshots__/action.test.ts.snap @@ -16,7 +16,7 @@ exports[`action command > resolves not resolved wdio elements in pointer action "y": 0, }, ], - "id": "action2", + "id": "pointer1", "parameters": { "pointerType": "mouse", }, @@ -43,7 +43,7 @@ exports[`action command > resolves not resolved wdio elements in wheel action 1` "y": 0, }, ], - "id": "action3", + "id": "wheel1", "parameters": {}, "type": "wheel", }, diff --git a/packages/webdriverio/tests/commands/browser/__snapshots__/scroll.test.ts.snap b/packages/webdriverio/tests/commands/browser/__snapshots__/scroll.test.ts.snap index 0e1b0ffd2a2..dd734fade01 100644 --- a/packages/webdriverio/tests/commands/browser/__snapshots__/scroll.test.ts.snap +++ b/packages/webdriverio/tests/commands/browser/__snapshots__/scroll.test.ts.snap @@ -14,7 +14,7 @@ exports[`scroll > desktop > should be able to scroll 1`] = ` "y": 0, }, ], - "id": "action1", + "id": "wheel1", "parameters": {}, "type": "wheel", }, diff --git a/packages/webdriverio/tests/commands/element/__snapshots__/click.test.ts.snap b/packages/webdriverio/tests/commands/element/__snapshots__/click.test.ts.snap index 6d7bae5f912..f859db84349 100644 --- a/packages/webdriverio/tests/commands/element/__snapshots__/click.test.ts.snap +++ b/packages/webdriverio/tests/commands/element/__snapshots__/click.test.ts.snap @@ -26,7 +26,7 @@ exports[`click test > should allow to left click on an element by passing a butt "type": "pointerUp", }, ], - "id": "action1", + "id": "pointer1", "parameters": { "pointerType": "mouse", }, @@ -60,7 +60,7 @@ exports[`click test > should allow to left click on an element by passing a butt "type": "pointerUp", }, ], - "id": "action2", + "id": "pointer2", "parameters": { "pointerType": "mouse", }, @@ -95,7 +95,7 @@ exports[`click test > should allow to left click on an element with an offset wi "type": "pointerUp", }, ], - "id": "action7", + "id": "pointer7", "parameters": { "pointerType": "mouse", }, @@ -130,7 +130,7 @@ exports[`click test > should allow to middle click on an element 1`] = ` "type": "pointerUp", }, ], - "id": "action5", + "id": "pointer5", "parameters": { "pointerType": "mouse", }, @@ -164,7 +164,7 @@ exports[`click test > should allow to middle click on an element 2`] = ` "type": "pointerUp", }, ], - "id": "action6", + "id": "pointer6", "parameters": { "pointerType": "mouse", }, @@ -198,7 +198,7 @@ exports[`click test > should allow to right click on an element 1`] = ` "type": "pointerUp", }, ], - "id": "action3", + "id": "pointer3", "parameters": { "pointerType": "mouse", }, @@ -232,7 +232,7 @@ exports[`click test > should allow to right click on an element 2`] = ` "type": "pointerUp", }, ], - "id": "action4", + "id": "pointer4", "parameters": { "pointerType": "mouse", }, @@ -273,7 +273,7 @@ exports[`click test > should to send a duration to execute a longPress on a mobi "type": "pointerUp", }, ], - "id": "action9", + "id": "pointer9", "parameters": { "pointerType": "touch", }, diff --git a/packages/webdriverio/tests/commands/element/__snapshots__/dragAndDrop.test.ts.snap b/packages/webdriverio/tests/commands/element/__snapshots__/dragAndDrop.test.ts.snap index 6c40ef18ed9..ffc0c7730e3 100644 --- a/packages/webdriverio/tests/commands/element/__snapshots__/dragAndDrop.test.ts.snap +++ b/packages/webdriverio/tests/commands/element/__snapshots__/dragAndDrop.test.ts.snap @@ -35,7 +35,7 @@ exports[`dragAndDrop > should allow drag and drop to 0 coordinates 1`] = ` "type": "pointerUp", }, ], - "id": "action5", + "id": "pointer5", "parameters": { "pointerType": "mouse", }, @@ -81,7 +81,7 @@ exports[`dragAndDrop > should do a dragAndDrop 1`] = ` "type": "pointerUp", }, ], - "id": "action1", + "id": "pointer1", "parameters": { "pointerType": "mouse", }, @@ -127,7 +127,7 @@ exports[`dragAndDrop > should do a dragAndDrop for mobile 1`] = ` "type": "pointerUp", }, ], - "id": "action3", + "id": "pointer3", "parameters": { "pointerType": "touch", }, @@ -171,7 +171,7 @@ exports[`dragAndDrop > should do a dragAndDrop with coordinates 1`] = ` "type": "pointerUp", }, ], - "id": "action4", + "id": "pointer4", "parameters": { "pointerType": "mouse", }, diff --git a/packages/webdriverio/tests/commands/element/__snapshots__/scrollIntoView.test.ts.snap b/packages/webdriverio/tests/commands/element/__snapshots__/scrollIntoView.test.ts.snap index 1fa6d05a86e..33b7cf81ed2 100644 --- a/packages/webdriverio/tests/commands/element/__snapshots__/scrollIntoView.test.ts.snap +++ b/packages/webdriverio/tests/commands/element/__snapshots__/scrollIntoView.test.ts.snap @@ -17,7 +17,7 @@ exports[`scrollIntoView test > desktop > scrolls by default the element to the t "y": -30, }, ], - "id": "action1", + "id": "wheel1", "parameters": {}, "type": "wheel", }, @@ -42,7 +42,7 @@ exports[`scrollIntoView test > desktop > scrolls element using scroll into view "y": -385, }, ], - "id": "action4", + "id": "wheel4", "parameters": {}, "type": "wheel", }, @@ -67,7 +67,7 @@ exports[`scrollIntoView test > desktop > scrolls element when using boolean scro "y": -30, }, ], - "id": "action2", + "id": "wheel2", "parameters": {}, "type": "wheel", }, @@ -92,7 +92,7 @@ exports[`scrollIntoView test > desktop > scrolls element when using boolean scro "y": -770, }, ], - "id": "action3", + "id": "wheel3", "parameters": {}, "type": "wheel", }, diff --git a/packages/webdriverio/tests/commands/mobile/__snapshots__/swipe.test.ts.snap b/packages/webdriverio/tests/commands/mobile/__snapshots__/swipe.test.ts.snap index d641187c302..57e77b8f987 100644 --- a/packages/webdriverio/tests/commands/mobile/__snapshots__/swipe.test.ts.snap +++ b/packages/webdriverio/tests/commands/mobile/__snapshots__/swipe.test.ts.snap @@ -40,7 +40,7 @@ exports[`swipe test > should be able to swipe based on provided coordinates 1`] "type": "pointerUp", }, ], - "id": "action4", + "id": "pointer4", "parameters": { "pointerType": "touch", }, @@ -80,7 +80,7 @@ exports[`swipe test > should call a swipe down command with 25% for a scrollable "type": "pointerUp", }, ], - "id": "action8", + "id": "pointer8", "parameters": { "pointerType": "touch", }, @@ -120,7 +120,7 @@ exports[`swipe test > should call a swipe down command with duration 5000 for a "type": "pointerUp", }, ], - "id": "action12", + "id": "pointer12", "parameters": { "pointerType": "touch", }, @@ -160,7 +160,7 @@ exports[`swipe test > should call a swipe left command with 50% for a scrollable "type": "pointerUp", }, ], - "id": "action10", + "id": "pointer10", "parameters": { "pointerType": "touch", }, @@ -200,7 +200,7 @@ exports[`swipe test > should call a swipe right command with 75% for a scrollabl "type": "pointerUp", }, ], - "id": "action11", + "id": "pointer11", "parameters": { "pointerType": "touch", }, @@ -240,7 +240,7 @@ exports[`swipe test > should call a swipe up command with 45% for a scrollable e "type": "pointerUp", }, ], - "id": "action9", + "id": "pointer9", "parameters": { "pointerType": "touch", }, diff --git a/packages/webdriverio/tests/commands/mobile/__snapshots__/tap.test.ts.snap b/packages/webdriverio/tests/commands/mobile/__snapshots__/tap.test.ts.snap index b9c8e4efd3c..daf871a5ea9 100644 --- a/packages/webdriverio/tests/commands/mobile/__snapshots__/tap.test.ts.snap +++ b/packages/webdriverio/tests/commands/mobile/__snapshots__/tap.test.ts.snap @@ -102,7 +102,7 @@ exports[`screen tap test > should call the action command for mobile web when a "type": "pointerUp", }, ], - "id": "action1", + "id": "pointer1", "parameters": { "pointerType": "touch", },