@testring/plugin-selenium-driver 0.8.3 → 0.8.5
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.
- package/dist/plugin/index.d.ts +46 -39
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +208 -172
- package/dist/plugin/index.js.map +1 -1
- package/package.json +7 -7
- package/src/plugin/index.ts +233 -209
package/src/plugin/index.ts
CHANGED
|
@@ -3,7 +3,11 @@ import {
|
|
|
3
3
|
IBrowserProxyPlugin,
|
|
4
4
|
SavePdfOptions,
|
|
5
5
|
WindowFeaturesConfig,
|
|
6
|
-
IWindowFeatures
|
|
6
|
+
IWindowFeatures,
|
|
7
|
+
Selector,
|
|
8
|
+
ShadowCssSelector,
|
|
9
|
+
isXpathSelector,
|
|
10
|
+
isShadowCssSelector
|
|
7
11
|
} from '@testring/types';
|
|
8
12
|
|
|
9
13
|
import {ChildProcess} from 'child_process';
|
|
@@ -187,6 +191,7 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
187
191
|
|
|
188
192
|
if (this.config.host === undefined) {
|
|
189
193
|
this.runLocalSelenium();
|
|
194
|
+
this.setupProcessCleanup();
|
|
190
195
|
}
|
|
191
196
|
|
|
192
197
|
this.initIntervals();
|
|
@@ -240,6 +245,19 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
240
245
|
}
|
|
241
246
|
}
|
|
242
247
|
|
|
248
|
+
private setupProcessCleanup() {
|
|
249
|
+
process.on('SIGINT', () => this.forceKillSelenium());
|
|
250
|
+
process.on('SIGTERM', () => this.forceKillSelenium());
|
|
251
|
+
// Note: SIGKILL cannot be caught or handled - it immediately terminates the process
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private forceKillSelenium() {
|
|
255
|
+
if (this.localSelenium && !this.localSelenium.killed) {
|
|
256
|
+
this.logger.debug('Force killing Selenium process due to signal');
|
|
257
|
+
this.localSelenium.kill('SIGKILL');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
243
261
|
private stopAllSessions() {
|
|
244
262
|
const clientsRequests: Promise<any>[] = [];
|
|
245
263
|
|
|
@@ -313,7 +331,11 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
313
331
|
this.localSelenium = spawnWithPipes('java', seleniumArgs);
|
|
314
332
|
|
|
315
333
|
this.waitForReadyState = new Promise((resolve, reject) => {
|
|
316
|
-
|
|
334
|
+
if (this.localSelenium) {
|
|
335
|
+
setupProcessListeners(this.localSelenium, resolve, reject, version, this.logger);
|
|
336
|
+
} else {
|
|
337
|
+
reject(new Error('Failed to spawn Selenium process'));
|
|
338
|
+
}
|
|
317
339
|
});
|
|
318
340
|
|
|
319
341
|
// Wait for the server to be ready
|
|
@@ -499,6 +521,95 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
499
521
|
return client as BrowserObjectCustom;
|
|
500
522
|
}
|
|
501
523
|
|
|
524
|
+
private async getElement(applicant: string, selector: Selector) {
|
|
525
|
+
await this.createClient(applicant);
|
|
526
|
+
const client = this.getBrowserClient(applicant);
|
|
527
|
+
|
|
528
|
+
if (isXpathSelector(selector)) {
|
|
529
|
+
return client.$(selector.xpath);
|
|
530
|
+
} else if (isShadowCssSelector(selector)) {
|
|
531
|
+
return this.getElementFromShadowCss(client, selector);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
throw new Error('Unknown selector type');
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
private async getElementFromShadowCss(client: BrowserObjectCustom, selector: ShadowCssSelector) {
|
|
538
|
+
const {css, parentSelectors} = selector;
|
|
539
|
+
|
|
540
|
+
// Error first: validate selector structure
|
|
541
|
+
this.validateShadowCssSelector(selector);
|
|
542
|
+
|
|
543
|
+
try {
|
|
544
|
+
return await this.traverseShadowDom(client, css, parentSelectors);
|
|
545
|
+
} catch (error) {
|
|
546
|
+
// Provide more context in error messages
|
|
547
|
+
if (error instanceof Error) {
|
|
548
|
+
throw new Error(`Shadow DOM traversal failed: ${error.message}. Selector: ${JSON.stringify(selector)}`);
|
|
549
|
+
}
|
|
550
|
+
throw error;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
private validateShadowCssSelector(selector: ShadowCssSelector): void {
|
|
555
|
+
const {css, parentSelectors} = selector;
|
|
556
|
+
|
|
557
|
+
if (!css || typeof css !== 'string') {
|
|
558
|
+
throw new Error('Shadow CSS selector must have a valid CSS string');
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (!Array.isArray(parentSelectors) || parentSelectors.length === 0) {
|
|
562
|
+
throw new Error('Shadow CSS selector must have at least one parent selector');
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Validate all parent selectors are non-empty strings
|
|
566
|
+
for (const [index, parentSelector] of parentSelectors.entries()) {
|
|
567
|
+
if (!parentSelector || typeof parentSelector !== 'string') {
|
|
568
|
+
throw new Error(`Parent selector at index ${index} must be a non-empty string`);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private async traverseToLastParentSelector(client: BrowserObjectCustom, parentSelectors: string[]) {
|
|
574
|
+
const [firstParentSelector, ...restParentSelectors] = parentSelectors;
|
|
575
|
+
|
|
576
|
+
// TypeScript assertion: we know firstParentSelector exists due to validation
|
|
577
|
+
if (!firstParentSelector) {
|
|
578
|
+
throw new Error('First parent selector is required');
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Get the first parent element
|
|
582
|
+
let currentElement = await client.$(firstParentSelector);
|
|
583
|
+
|
|
584
|
+
if (!currentElement) {
|
|
585
|
+
throw new Error(`Failed to find parent element with selector: ${firstParentSelector}`);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Traverse through shadow DOM hierarchy
|
|
589
|
+
for (const parentSelector of restParentSelectors) {
|
|
590
|
+
const shadowElement = await currentElement.shadow$(parentSelector);
|
|
591
|
+
if (!shadowElement) {
|
|
592
|
+
throw new Error(`Failed to find shadow element with selector: ${parentSelector}`);
|
|
593
|
+
}
|
|
594
|
+
currentElement = shadowElement;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
return currentElement;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
private async traverseShadowDom(client: BrowserObjectCustom, css: string, parentSelectors: string[]) {
|
|
601
|
+
// Traverse to the last parent selector
|
|
602
|
+
const lastParentElement = await this.traverseToLastParentSelector(client, parentSelectors);
|
|
603
|
+
|
|
604
|
+
// Get the final target element within the shadow DOM
|
|
605
|
+
const targetElement = await lastParentElement.shadow$(css);
|
|
606
|
+
if (!targetElement) {
|
|
607
|
+
throw new Error(`Failed to find target element with CSS selector: ${css}`);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return targetElement;
|
|
611
|
+
}
|
|
612
|
+
|
|
502
613
|
public async end(applicant: string) {
|
|
503
614
|
await this.waitForReadyState;
|
|
504
615
|
|
|
@@ -638,24 +749,17 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
638
749
|
|
|
639
750
|
public async click(
|
|
640
751
|
applicant: string,
|
|
641
|
-
selector:
|
|
752
|
+
selector: Selector,
|
|
642
753
|
options?: ClickOptions,
|
|
643
754
|
) {
|
|
644
|
-
await this.
|
|
645
|
-
const client = this.getBrowserClient(applicant);
|
|
646
|
-
|
|
647
|
-
const element = await client.$(selector);
|
|
755
|
+
const element = await this.getElement(applicant, selector);
|
|
648
756
|
return options && Object.keys(options).length > 0
|
|
649
757
|
? element.click(options)
|
|
650
758
|
: element.click();
|
|
651
759
|
}
|
|
652
760
|
|
|
653
|
-
public async getSize(applicant: string, selector:
|
|
654
|
-
await this.
|
|
655
|
-
const client = this.getBrowserClient(applicant);
|
|
656
|
-
|
|
657
|
-
const element = await client.$(selector);
|
|
658
|
-
|
|
761
|
+
public async getSize(applicant: string, selector: Selector) {
|
|
762
|
+
const element = await this.getElement(applicant, selector);
|
|
659
763
|
return element.getSize();
|
|
660
764
|
}
|
|
661
765
|
|
|
@@ -695,47 +799,35 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
695
799
|
|
|
696
800
|
public async waitForExist(
|
|
697
801
|
applicant: string,
|
|
698
|
-
|
|
802
|
+
selector: Selector,
|
|
699
803
|
timeout: number,
|
|
700
804
|
) {
|
|
701
|
-
await this.
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const selector = await client.$(xpath);
|
|
705
|
-
return selector.waitForExist({timeout});
|
|
805
|
+
const element = await this.getElement(applicant, selector);
|
|
806
|
+
return element.waitForExist({timeout});
|
|
706
807
|
}
|
|
707
808
|
|
|
708
809
|
public async waitForVisible(
|
|
709
810
|
applicant: string,
|
|
710
|
-
|
|
811
|
+
selector: Selector,
|
|
711
812
|
timeout: number,
|
|
712
813
|
) {
|
|
713
|
-
await this.
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const selector = await client.$(xpath);
|
|
717
|
-
return selector.waitForDisplayed({timeout});
|
|
814
|
+
const element = await this.getElement(applicant, selector);
|
|
815
|
+
return element.waitForDisplayed({timeout});
|
|
718
816
|
}
|
|
719
817
|
|
|
720
|
-
public async isVisible(applicant: string,
|
|
721
|
-
await this.
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
const selector = await client.$(xpath);
|
|
725
|
-
return selector.isDisplayed();
|
|
818
|
+
public async isVisible(applicant: string, selector: Selector) {
|
|
819
|
+
const element = await this.getElement(applicant, selector);
|
|
820
|
+
return element.isDisplayed();
|
|
726
821
|
}
|
|
727
822
|
|
|
728
823
|
public async moveToObject(
|
|
729
824
|
applicant: string,
|
|
730
|
-
|
|
825
|
+
selector: Selector,
|
|
731
826
|
xOffset = 0,
|
|
732
827
|
yOffset = 0,
|
|
733
828
|
) {
|
|
734
|
-
await this.
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
const selector = await client.$(xpath);
|
|
738
|
-
return selector.moveTo({xOffset, yOffset});
|
|
829
|
+
const element = await this.getElement(applicant, selector);
|
|
830
|
+
return element.moveTo({xOffset, yOffset});
|
|
739
831
|
}
|
|
740
832
|
|
|
741
833
|
public async execute(applicant: string, fn: any, args: Array<any>) {
|
|
@@ -759,12 +851,9 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
759
851
|
return client.getTitle();
|
|
760
852
|
}
|
|
761
853
|
|
|
762
|
-
public async clearValue(applicant: string,
|
|
763
|
-
await this.
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const selector = await client.$(xpath);
|
|
767
|
-
return selector.clearValue();
|
|
854
|
+
public async clearValue(applicant: string, selector: Selector) {
|
|
855
|
+
const element = await this.getElement(applicant, selector);
|
|
856
|
+
return element.clearValue();
|
|
768
857
|
}
|
|
769
858
|
|
|
770
859
|
public async keys(applicant: string, value: any) {
|
|
@@ -781,19 +870,29 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
781
870
|
return client.getElementText(elementId);
|
|
782
871
|
}
|
|
783
872
|
|
|
784
|
-
public async elements(applicant: string,
|
|
873
|
+
public async elements(applicant: string, selector: Selector) {
|
|
785
874
|
await this.createClient(applicant);
|
|
786
875
|
const client = this.getBrowserClient(applicant);
|
|
787
876
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
877
|
+
if (isXpathSelector(selector)) {
|
|
878
|
+
const elements = (await client.findElements('xpath', selector.xpath)) as unknown;
|
|
879
|
+
return (elements as Array<Record<string, string>>).map((o) => {
|
|
880
|
+
const keys = Object.keys(o);
|
|
881
|
+
const firstKey = keys[0];
|
|
882
|
+
if (firstKey === undefined) {
|
|
883
|
+
return {ELEMENT: ''};
|
|
884
|
+
}
|
|
885
|
+
return {ELEMENT: o[firstKey]};
|
|
886
|
+
});
|
|
887
|
+
} else if (isShadowCssSelector(selector)) {
|
|
888
|
+
const lastParentElement = await this.traverseToLastParentSelector(client, selector.parentSelectors);
|
|
889
|
+
const elements = lastParentElement.shadow$$(selector.css);
|
|
890
|
+
return elements.map((element) => {
|
|
891
|
+
return {ELEMENT: element.elementId};
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
throw new Error('Unknown selector type');
|
|
797
896
|
}
|
|
798
897
|
|
|
799
898
|
public async frame(applicant: string, frameID: any) {
|
|
@@ -809,60 +908,42 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
809
908
|
return client.switchToParentFrame();
|
|
810
909
|
}
|
|
811
910
|
|
|
812
|
-
public async getValue(applicant: string,
|
|
813
|
-
await this.
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
const selector = await client.$(xpath);
|
|
817
|
-
return selector.getValue();
|
|
911
|
+
public async getValue(applicant: string, selector: Selector) {
|
|
912
|
+
const element = await this.getElement(applicant, selector);
|
|
913
|
+
return element.getValue();
|
|
818
914
|
}
|
|
819
915
|
|
|
820
|
-
public async setValue(applicant: string,
|
|
821
|
-
await this.
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const selector = await client.$(xpath);
|
|
825
|
-
return selector.setValue(value);
|
|
916
|
+
public async setValue(applicant: string, selector: Selector, value: any) {
|
|
917
|
+
const element = await this.getElement(applicant, selector);
|
|
918
|
+
return element.setValue(value);
|
|
826
919
|
}
|
|
827
920
|
|
|
828
|
-
public async selectByIndex(applicant: string,
|
|
829
|
-
await this.
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
const selector = await client.$(xpath);
|
|
833
|
-
return selector.selectByIndex(value);
|
|
921
|
+
public async selectByIndex(applicant: string, selector: Selector, value: any) {
|
|
922
|
+
const element = await this.getElement(applicant, selector);
|
|
923
|
+
return element.selectByIndex(value);
|
|
834
924
|
}
|
|
835
925
|
|
|
836
|
-
public async selectByValue(applicant: string,
|
|
837
|
-
await this.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const selector = await client.$(xpath);
|
|
841
|
-
return selector.selectByAttribute('value', value);
|
|
926
|
+
public async selectByValue(applicant: string, selector: Selector, value: any) {
|
|
927
|
+
const element = await this.getElement(applicant, selector);
|
|
928
|
+
return element.selectByAttribute('value', value);
|
|
842
929
|
}
|
|
843
930
|
|
|
844
931
|
public async selectByVisibleText(
|
|
845
932
|
applicant: string,
|
|
846
|
-
|
|
933
|
+
selector: Selector,
|
|
847
934
|
str: string,
|
|
848
935
|
) {
|
|
849
|
-
await this.
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
const selector = await client.$(xpath);
|
|
853
|
-
return selector.selectByVisibleText(str);
|
|
936
|
+
const element = await this.getElement(applicant, selector);
|
|
937
|
+
return element.selectByVisibleText(str);
|
|
854
938
|
}
|
|
855
939
|
|
|
856
940
|
public async getAttribute(
|
|
857
941
|
applicant: string,
|
|
858
|
-
|
|
942
|
+
selector: Selector,
|
|
859
943
|
attr: string,
|
|
860
944
|
): Promise<any> {
|
|
861
|
-
await this.
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const selector = await client.$(xpath);
|
|
865
|
-
return selector.getAttribute(attr);
|
|
945
|
+
const element = await this.getElement(applicant, selector);
|
|
946
|
+
return element.getAttribute(attr);
|
|
866
947
|
}
|
|
867
948
|
|
|
868
949
|
public async windowHandleMaximize(applicant: string) {
|
|
@@ -872,37 +953,28 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
872
953
|
return client.maximizeWindow();
|
|
873
954
|
}
|
|
874
955
|
|
|
875
|
-
public async isEnabled(applicant: string,
|
|
876
|
-
await this.
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
const selector = await client.$(xpath);
|
|
880
|
-
return selector.isEnabled();
|
|
956
|
+
public async isEnabled(applicant: string, selector: Selector) {
|
|
957
|
+
const element = await this.getElement(applicant, selector);
|
|
958
|
+
return element.isEnabled();
|
|
881
959
|
}
|
|
882
960
|
|
|
883
961
|
public async scroll(
|
|
884
962
|
applicant: string,
|
|
885
|
-
|
|
963
|
+
selector: Selector,
|
|
886
964
|
xOffset: number,
|
|
887
965
|
yOffset: number,
|
|
888
966
|
) {
|
|
889
|
-
await this.
|
|
890
|
-
const client = this.getBrowserClient(applicant);
|
|
891
|
-
|
|
892
|
-
const element = await client.$(xpath);
|
|
967
|
+
const element = await this.getElement(applicant, selector);
|
|
893
968
|
await element.scrollIntoView();
|
|
894
969
|
return element.moveTo({xOffset, yOffset});
|
|
895
970
|
}
|
|
896
971
|
|
|
897
972
|
public async scrollIntoView(
|
|
898
973
|
applicant: string,
|
|
899
|
-
|
|
974
|
+
selector: Selector,
|
|
900
975
|
scrollIntoViewOptions?: boolean | null,
|
|
901
976
|
) {
|
|
902
|
-
await this.
|
|
903
|
-
const client = this.getBrowserClient(applicant);
|
|
904
|
-
|
|
905
|
-
const element = await client.$(xpath);
|
|
977
|
+
const element = await this.getElement(applicant, selector);
|
|
906
978
|
await element.scrollIntoView(
|
|
907
979
|
scrollIntoViewOptions !== null ? scrollIntoViewOptions : undefined,
|
|
908
980
|
);
|
|
@@ -950,14 +1022,11 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
950
1022
|
|
|
951
1023
|
public async dragAndDrop(
|
|
952
1024
|
applicant: string,
|
|
953
|
-
|
|
954
|
-
|
|
1025
|
+
sourceSelector: Selector,
|
|
1026
|
+
destinationSelector: Selector,
|
|
955
1027
|
) {
|
|
956
|
-
await this.
|
|
957
|
-
const
|
|
958
|
-
|
|
959
|
-
const sourceElement = await client.$(xpathSource);
|
|
960
|
-
const destinationElement = await client.$(xpathDestination);
|
|
1028
|
+
const sourceElement = await this.getElement(applicant, sourceSelector);
|
|
1029
|
+
const destinationElement = await this.getElement(applicant, destinationSelector);
|
|
961
1030
|
return sourceElement.dragAndDrop(destinationElement);
|
|
962
1031
|
}
|
|
963
1032
|
|
|
@@ -995,12 +1064,9 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
995
1064
|
return client.deleteAllCookies();
|
|
996
1065
|
}
|
|
997
1066
|
|
|
998
|
-
public async getHTML(applicant: string,
|
|
999
|
-
await this.
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const selector = await client.$(xpath);
|
|
1003
|
-
return selector.getHTML(b);
|
|
1067
|
+
public async getHTML(applicant: string, selector: Selector, b: any) {
|
|
1068
|
+
const element = await this.getElement(applicant, selector);
|
|
1069
|
+
return element.getHTML(b);
|
|
1004
1070
|
}
|
|
1005
1071
|
|
|
1006
1072
|
public async getCurrentTabId(applicant: string) {
|
|
@@ -1054,28 +1120,19 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1054
1120
|
return client.closeWindow();
|
|
1055
1121
|
}
|
|
1056
1122
|
|
|
1057
|
-
public async getTagName(applicant: string,
|
|
1058
|
-
await this.
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const selector = await client.$(xpath);
|
|
1062
|
-
return selector.getTagName();
|
|
1123
|
+
public async getTagName(applicant: string, selector: Selector) {
|
|
1124
|
+
const element = await this.getElement(applicant, selector);
|
|
1125
|
+
return element.getTagName();
|
|
1063
1126
|
}
|
|
1064
1127
|
|
|
1065
|
-
public async isSelected(applicant: string,
|
|
1066
|
-
await this.
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
const selector = await client.$(xpath);
|
|
1070
|
-
return selector.isSelected();
|
|
1128
|
+
public async isSelected(applicant: string, selector: Selector) {
|
|
1129
|
+
const element = await this.getElement(applicant, selector);
|
|
1130
|
+
return element.isSelected();
|
|
1071
1131
|
}
|
|
1072
1132
|
|
|
1073
|
-
public async getText(applicant: string,
|
|
1074
|
-
await this.
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
const selector = await client.$(xpath);
|
|
1078
|
-
return selector.getText();
|
|
1133
|
+
public async getText(applicant: string, selector: Selector) {
|
|
1134
|
+
const element = await this.getElement(applicant, selector);
|
|
1135
|
+
return element.getText();
|
|
1079
1136
|
}
|
|
1080
1137
|
|
|
1081
1138
|
public async elementIdSelected(applicant: string, id: string) {
|
|
@@ -1104,13 +1161,10 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1104
1161
|
|
|
1105
1162
|
public async getCssProperty(
|
|
1106
1163
|
applicant: string,
|
|
1107
|
-
|
|
1164
|
+
selector: Selector,
|
|
1108
1165
|
cssProperty: string,
|
|
1109
1166
|
): Promise<any> {
|
|
1110
|
-
await this.
|
|
1111
|
-
const client = this.getBrowserClient(applicant);
|
|
1112
|
-
|
|
1113
|
-
const element = await client.$(xpath);
|
|
1167
|
+
const element = await this.getElement(applicant, selector);
|
|
1114
1168
|
const property = await element.getCSSProperty(cssProperty);
|
|
1115
1169
|
return property.value;
|
|
1116
1170
|
}
|
|
@@ -1122,17 +1176,14 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1122
1176
|
return client.getPageSource();
|
|
1123
1177
|
}
|
|
1124
1178
|
|
|
1125
|
-
public async isExisting(applicant: string,
|
|
1126
|
-
await this.
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
const selector = await client.$(xpath);
|
|
1130
|
-
return selector.isExisting();
|
|
1179
|
+
public async isExisting(applicant: string, selector: Selector) {
|
|
1180
|
+
const element = await this.getElement(applicant, selector);
|
|
1181
|
+
return element.isExisting();
|
|
1131
1182
|
}
|
|
1132
1183
|
|
|
1133
1184
|
public async waitForValue(
|
|
1134
1185
|
applicant: string,
|
|
1135
|
-
|
|
1186
|
+
selector: Selector,
|
|
1136
1187
|
timeout: number,
|
|
1137
1188
|
reverse: boolean,
|
|
1138
1189
|
) {
|
|
@@ -1141,7 +1192,8 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1141
1192
|
|
|
1142
1193
|
return client.waitUntil(
|
|
1143
1194
|
async () => {
|
|
1144
|
-
const
|
|
1195
|
+
const element = await this.getElement(applicant, selector);
|
|
1196
|
+
const elemValue = await element.getValue();
|
|
1145
1197
|
return reverse ? !elemValue : !!elemValue;
|
|
1146
1198
|
},
|
|
1147
1199
|
{timeout},
|
|
@@ -1150,7 +1202,7 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1150
1202
|
|
|
1151
1203
|
public async waitForSelected(
|
|
1152
1204
|
applicant: string,
|
|
1153
|
-
|
|
1205
|
+
selector: Selector,
|
|
1154
1206
|
timeout: number,
|
|
1155
1207
|
reverse: boolean,
|
|
1156
1208
|
) {
|
|
@@ -1159,7 +1211,8 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1159
1211
|
|
|
1160
1212
|
return client.waitUntil(
|
|
1161
1213
|
async () => {
|
|
1162
|
-
const
|
|
1214
|
+
const element = await this.getElement(applicant, selector);
|
|
1215
|
+
const isSelected = await element.isSelected();
|
|
1163
1216
|
return reverse ? !isSelected : isSelected;
|
|
1164
1217
|
},
|
|
1165
1218
|
{timeout},
|
|
@@ -1193,15 +1246,12 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1193
1246
|
|
|
1194
1247
|
public async selectByAttribute(
|
|
1195
1248
|
applicant: string,
|
|
1196
|
-
|
|
1249
|
+
selector: Selector,
|
|
1197
1250
|
attribute: string,
|
|
1198
1251
|
value: string,
|
|
1199
1252
|
) {
|
|
1200
|
-
await this.
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
const selector = await client.$(xpath);
|
|
1204
|
-
return selector.selectByAttribute(attribute, value);
|
|
1253
|
+
const element = await this.getElement(applicant, selector);
|
|
1254
|
+
return element.selectByAttribute(attribute, value);
|
|
1205
1255
|
}
|
|
1206
1256
|
|
|
1207
1257
|
public async gridTestSession(applicant: string) {
|
|
@@ -1299,10 +1349,8 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1299
1349
|
return client.getActiveElement();
|
|
1300
1350
|
}
|
|
1301
1351
|
|
|
1302
|
-
public async getLocation(applicant: string,
|
|
1303
|
-
await this.
|
|
1304
|
-
const client = this.getBrowserClient(applicant);
|
|
1305
|
-
const element = client.$(xpath);
|
|
1352
|
+
public async getLocation(applicant: string, selector: Selector) {
|
|
1353
|
+
const element = await this.getElement(applicant, selector);
|
|
1306
1354
|
return element.getLocation();
|
|
1307
1355
|
}
|
|
1308
1356
|
|
|
@@ -1329,82 +1377,58 @@ export class SeleniumPlugin implements IBrowserProxyPlugin {
|
|
|
1329
1377
|
|
|
1330
1378
|
public async addValue(
|
|
1331
1379
|
applicant: string,
|
|
1332
|
-
|
|
1380
|
+
selector: Selector,
|
|
1333
1381
|
value: string | number,
|
|
1334
1382
|
) {
|
|
1335
|
-
await this.
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
const selector = await client.$(xpath);
|
|
1339
|
-
return selector.addValue(value);
|
|
1383
|
+
const element = await this.getElement(applicant, selector);
|
|
1384
|
+
return element.addValue(value);
|
|
1340
1385
|
}
|
|
1341
1386
|
|
|
1342
|
-
public async doubleClick(applicant: string,
|
|
1343
|
-
await this.
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
const selector = await client.$(xpath);
|
|
1347
|
-
return selector.doubleClick();
|
|
1387
|
+
public async doubleClick(applicant: string, selector: Selector) {
|
|
1388
|
+
const element = await this.getElement(applicant, selector);
|
|
1389
|
+
return element.doubleClick();
|
|
1348
1390
|
}
|
|
1349
1391
|
|
|
1350
|
-
public async isClickable(applicant: string,
|
|
1351
|
-
await this.
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
const selector = await client.$(xpath);
|
|
1355
|
-
return selector.isClickable();
|
|
1392
|
+
public async isClickable(applicant: string, selector: Selector) {
|
|
1393
|
+
const element = await this.getElement(applicant, selector);
|
|
1394
|
+
return element.isClickable();
|
|
1356
1395
|
}
|
|
1357
1396
|
|
|
1358
1397
|
public async waitForClickable(
|
|
1359
1398
|
applicant: string,
|
|
1360
|
-
|
|
1399
|
+
selector: Selector,
|
|
1361
1400
|
timeout: number,
|
|
1362
1401
|
) {
|
|
1363
|
-
await this.
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
const selector = await client.$(xpath);
|
|
1367
|
-
return selector.waitForClickable({timeout});
|
|
1402
|
+
const element = await this.getElement(applicant, selector);
|
|
1403
|
+
return element.waitForClickable({timeout});
|
|
1368
1404
|
}
|
|
1369
1405
|
|
|
1370
|
-
public async isFocused(applicant: string,
|
|
1371
|
-
await this.
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
const selector = await client.$(xpath);
|
|
1375
|
-
return selector.isFocused();
|
|
1406
|
+
public async isFocused(applicant: string, selector: Selector) {
|
|
1407
|
+
const element = await this.getElement(applicant, selector);
|
|
1408
|
+
return element.isFocused();
|
|
1376
1409
|
}
|
|
1377
1410
|
|
|
1378
|
-
public async isStable(applicant: string,
|
|
1379
|
-
await this.
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
const selector = await client.$(xpath);
|
|
1383
|
-
return selector.isStable();
|
|
1411
|
+
public async isStable(applicant: string, selector: Selector) {
|
|
1412
|
+
const element = await this.getElement(applicant, selector);
|
|
1413
|
+
return element.isStable();
|
|
1384
1414
|
}
|
|
1385
1415
|
|
|
1386
1416
|
public async waitForEnabled(
|
|
1387
1417
|
applicant: string,
|
|
1388
|
-
|
|
1418
|
+
selector: Selector,
|
|
1389
1419
|
timeout: number,
|
|
1390
1420
|
) {
|
|
1391
|
-
await this.
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
const selector = await client.$(xpath);
|
|
1395
|
-
return selector.waitForEnabled({timeout});
|
|
1421
|
+
const element = await this.getElement(applicant, selector);
|
|
1422
|
+
return element.waitForEnabled({timeout});
|
|
1396
1423
|
}
|
|
1397
1424
|
|
|
1398
1425
|
public async waitForStable(
|
|
1399
1426
|
applicant: string,
|
|
1400
|
-
|
|
1427
|
+
selector: Selector,
|
|
1401
1428
|
timeout: number,
|
|
1402
1429
|
) {
|
|
1403
|
-
await this.
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
const selector = await client.$(xpath);
|
|
1407
|
-
return selector.waitForStable({timeout});
|
|
1430
|
+
const element = await this.getElement(applicant, selector);
|
|
1431
|
+
return element.waitForStable({timeout});
|
|
1408
1432
|
}
|
|
1409
1433
|
}
|
|
1410
1434
|
|