doc-detective 4.29.0 → 4.29.1

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/index.cjs CHANGED
@@ -9324,7 +9324,7 @@ var init_schemas = __esm({
9324
9324
  },
9325
9325
  elementText: {
9326
9326
  type: "string",
9327
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
9327
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
9328
9328
  },
9329
9329
  selector: {
9330
9330
  type: "string",
@@ -13470,7 +13470,7 @@ var init_schemas = __esm({
13470
13470
  },
13471
13471
  elementText: {
13472
13472
  type: "string",
13473
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
13473
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
13474
13474
  },
13475
13475
  selector: {
13476
13476
  type: "string",
@@ -18701,7 +18701,7 @@ var init_schemas = __esm({
18701
18701
  },
18702
18702
  elementText: {
18703
18703
  type: "string",
18704
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
18704
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
18705
18705
  },
18706
18706
  elementId: {
18707
18707
  type: "string",
@@ -19233,7 +19233,7 @@ var init_schemas = __esm({
19233
19233
  },
19234
19234
  elementText: {
19235
19235
  type: "string",
19236
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
19236
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
19237
19237
  },
19238
19238
  elementId: {
19239
19239
  type: "string",
@@ -54963,7 +54963,7 @@ var init_schemas = __esm({
54963
54963
  },
54964
54964
  elementText: {
54965
54965
  type: "string",
54966
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
54966
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
54967
54967
  },
54968
54968
  selector: {
54969
54969
  type: "string",
@@ -59109,7 +59109,7 @@ var init_schemas = __esm({
59109
59109
  },
59110
59110
  elementText: {
59111
59111
  type: "string",
59112
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
59112
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
59113
59113
  },
59114
59114
  selector: {
59115
59115
  type: "string",
@@ -64340,7 +64340,7 @@ var init_schemas = __esm({
64340
64340
  },
64341
64341
  elementText: {
64342
64342
  type: "string",
64343
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
64343
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
64344
64344
  },
64345
64345
  elementId: {
64346
64346
  type: "string",
@@ -64872,7 +64872,7 @@ var init_schemas = __esm({
64872
64872
  },
64873
64873
  elementText: {
64874
64874
  type: "string",
64875
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
64875
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
64876
64876
  },
64877
64877
  elementId: {
64878
64878
  type: "string",
@@ -95536,7 +95536,7 @@ var init_schemas = __esm({
95536
95536
  },
95537
95537
  elementText: {
95538
95538
  type: "string",
95539
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
95539
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
95540
95540
  },
95541
95541
  selector: {
95542
95542
  type: "string",
@@ -99682,7 +99682,7 @@ var init_schemas = __esm({
99682
99682
  },
99683
99683
  elementText: {
99684
99684
  type: "string",
99685
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
99685
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
99686
99686
  },
99687
99687
  selector: {
99688
99688
  type: "string",
@@ -103964,7 +103964,7 @@ var init_schemas = __esm({
103964
103964
  },
103965
103965
  elementText: {
103966
103966
  type: "string",
103967
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
103967
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
103968
103968
  },
103969
103969
  elementId: {
103970
103970
  type: "string",
@@ -104496,7 +104496,7 @@ var init_schemas = __esm({
104496
104496
  },
104497
104497
  elementText: {
104498
104498
  type: "string",
104499
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
104499
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
104500
104500
  },
104501
104501
  elementId: {
104502
104502
  type: "string",
@@ -113889,7 +113889,7 @@ var init_schemas = __esm({
113889
113889
  },
113890
113890
  elementText: {
113891
113891
  type: "string",
113892
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
113892
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
113893
113893
  },
113894
113894
  selector: {
113895
113895
  type: "string",
@@ -118035,7 +118035,7 @@ var init_schemas = __esm({
118035
118035
  },
118036
118036
  elementText: {
118037
118037
  type: "string",
118038
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
118038
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
118039
118039
  },
118040
118040
  selector: {
118041
118041
  type: "string",
@@ -123266,7 +123266,7 @@ var init_schemas = __esm({
123266
123266
  },
123267
123267
  elementText: {
123268
123268
  type: "string",
123269
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
123269
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
123270
123270
  },
123271
123271
  elementId: {
123272
123272
  type: "string",
@@ -123798,7 +123798,7 @@ var init_schemas = __esm({
123798
123798
  },
123799
123799
  elementText: {
123800
123800
  type: "string",
123801
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
123801
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
123802
123802
  },
123803
123803
  elementId: {
123804
123804
  type: "string",
@@ -159528,7 +159528,7 @@ var init_schemas = __esm({
159528
159528
  },
159529
159529
  elementText: {
159530
159530
  type: "string",
159531
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
159531
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
159532
159532
  },
159533
159533
  selector: {
159534
159534
  type: "string",
@@ -163674,7 +163674,7 @@ var init_schemas = __esm({
163674
163674
  },
163675
163675
  elementText: {
163676
163676
  type: "string",
163677
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
163677
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
163678
163678
  },
163679
163679
  selector: {
163680
163680
  type: "string",
@@ -168905,7 +168905,7 @@ var init_schemas = __esm({
168905
168905
  },
168906
168906
  elementText: {
168907
168907
  type: "string",
168908
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
168908
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
168909
168909
  },
168910
168910
  elementId: {
168911
168911
  type: "string",
@@ -169437,7 +169437,7 @@ var init_schemas = __esm({
169437
169437
  },
169438
169438
  elementText: {
169439
169439
  type: "string",
169440
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
169440
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
169441
169441
  },
169442
169442
  elementId: {
169443
169443
  type: "string",
@@ -206906,7 +206906,7 @@ var init_schemas = __esm({
206906
206906
  },
206907
206907
  elementText: {
206908
206908
  type: "string",
206909
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
206909
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
206910
206910
  },
206911
206911
  selector: {
206912
206912
  type: "string",
@@ -211052,7 +211052,7 @@ var init_schemas = __esm({
211052
211052
  },
211053
211053
  elementText: {
211054
211054
  type: "string",
211055
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
211055
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
211056
211056
  },
211057
211057
  selector: {
211058
211058
  type: "string",
@@ -216283,7 +216283,7 @@ var init_schemas = __esm({
216283
216283
  },
216284
216284
  elementText: {
216285
216285
  type: "string",
216286
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
216286
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
216287
216287
  },
216288
216288
  elementId: {
216289
216289
  type: "string",
@@ -216815,7 +216815,7 @@ var init_schemas = __esm({
216815
216815
  },
216816
216816
  elementText: {
216817
216817
  type: "string",
216818
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
216818
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
216819
216819
  },
216820
216820
  elementId: {
216821
216821
  type: "string",
@@ -251807,7 +251807,7 @@ var init_schemas = __esm({
251807
251807
  },
251808
251808
  elementText: {
251809
251809
  type: "string",
251810
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
251810
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
251811
251811
  },
251812
251812
  selector: {
251813
251813
  type: "string",
@@ -255953,7 +255953,7 @@ var init_schemas = __esm({
255953
255953
  },
255954
255954
  elementText: {
255955
255955
  type: "string",
255956
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
255956
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
255957
255957
  },
255958
255958
  selector: {
255959
255959
  type: "string",
@@ -261184,7 +261184,7 @@ var init_schemas = __esm({
261184
261184
  },
261185
261185
  elementText: {
261186
261186
  type: "string",
261187
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
261187
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
261188
261188
  },
261189
261189
  elementId: {
261190
261190
  type: "string",
@@ -261716,7 +261716,7 @@ var init_schemas = __esm({
261716
261716
  },
261717
261717
  elementText: {
261718
261718
  type: "string",
261719
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
261719
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
261720
261720
  },
261721
261721
  elementId: {
261722
261722
  type: "string",
@@ -299669,7 +299669,7 @@ var init_schemas = __esm({
299669
299669
  },
299670
299670
  elementText: {
299671
299671
  type: "string",
299672
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
299672
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
299673
299673
  },
299674
299674
  selector: {
299675
299675
  type: "string",
@@ -303815,7 +303815,7 @@ var init_schemas = __esm({
303815
303815
  },
303816
303816
  elementText: {
303817
303817
  type: "string",
303818
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
303818
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
303819
303819
  },
303820
303820
  selector: {
303821
303821
  type: "string",
@@ -309046,7 +309046,7 @@ var init_schemas = __esm({
309046
309046
  },
309047
309047
  elementText: {
309048
309048
  type: "string",
309049
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
309049
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
309050
309050
  },
309051
309051
  elementId: {
309052
309052
  type: "string",
@@ -309578,7 +309578,7 @@ var init_schemas = __esm({
309578
309578
  },
309579
309579
  elementText: {
309580
309580
  type: "string",
309581
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
309581
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
309582
309582
  },
309583
309583
  elementId: {
309584
309584
  type: "string",
@@ -344570,7 +344570,7 @@ var init_schemas = __esm({
344570
344570
  },
344571
344571
  elementText: {
344572
344572
  type: "string",
344573
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
344573
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
344574
344574
  },
344575
344575
  selector: {
344576
344576
  type: "string",
@@ -348716,7 +348716,7 @@ var init_schemas = __esm({
348716
348716
  },
348717
348717
  elementText: {
348718
348718
  type: "string",
348719
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
348719
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
348720
348720
  },
348721
348721
  selector: {
348722
348722
  type: "string",
@@ -353947,7 +353947,7 @@ var init_schemas = __esm({
353947
353947
  },
353948
353948
  elementText: {
353949
353949
  type: "string",
353950
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
353950
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
353951
353951
  },
353952
353952
  elementId: {
353953
353953
  type: "string",
@@ -354479,7 +354479,7 @@ var init_schemas = __esm({
354479
354479
  },
354480
354480
  elementText: {
354481
354481
  type: "string",
354482
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
354482
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
354483
354483
  },
354484
354484
  elementId: {
354485
354485
  type: "string",
@@ -395756,7 +395756,7 @@ var init_schemas = __esm({
395756
395756
  },
395757
395757
  elementText: {
395758
395758
  type: "string",
395759
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
395759
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
395760
395760
  },
395761
395761
  selector: {
395762
395762
  type: "string",
@@ -399902,7 +399902,7 @@ var init_schemas = __esm({
399902
399902
  },
399903
399903
  elementText: {
399904
399904
  type: "string",
399905
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
399905
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
399906
399906
  },
399907
399907
  selector: {
399908
399908
  type: "string",
@@ -405133,7 +405133,7 @@ var init_schemas = __esm({
405133
405133
  },
405134
405134
  elementText: {
405135
405135
  type: "string",
405136
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
405136
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
405137
405137
  },
405138
405138
  elementId: {
405139
405139
  type: "string",
@@ -405665,7 +405665,7 @@ var init_schemas = __esm({
405665
405665
  },
405666
405666
  elementText: {
405667
405667
  type: "string",
405668
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
405668
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
405669
405669
  },
405670
405670
  elementId: {
405671
405671
  type: "string",
@@ -440657,7 +440657,7 @@ var init_schemas = __esm({
440657
440657
  },
440658
440658
  elementText: {
440659
440659
  type: "string",
440660
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
440660
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
440661
440661
  },
440662
440662
  selector: {
440663
440663
  type: "string",
@@ -444803,7 +444803,7 @@ var init_schemas = __esm({
444803
444803
  },
444804
444804
  elementText: {
444805
444805
  type: "string",
444806
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
444806
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
444807
444807
  },
444808
444808
  selector: {
444809
444809
  type: "string",
@@ -450034,7 +450034,7 @@ var init_schemas = __esm({
450034
450034
  },
450035
450035
  elementText: {
450036
450036
  type: "string",
450037
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
450037
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
450038
450038
  },
450039
450039
  elementId: {
450040
450040
  type: "string",
@@ -450566,7 +450566,7 @@ var init_schemas = __esm({
450566
450566
  },
450567
450567
  elementText: {
450568
450568
  type: "string",
450569
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
450569
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
450570
450570
  },
450571
450571
  elementId: {
450572
450572
  type: "string",
@@ -487250,7 +487250,7 @@ var init_schemas = __esm({
487250
487250
  },
487251
487251
  elementText: {
487252
487252
  type: "string",
487253
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
487253
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
487254
487254
  },
487255
487255
  selector: {
487256
487256
  type: "string",
@@ -491396,7 +491396,7 @@ var init_schemas = __esm({
491396
491396
  },
491397
491397
  elementText: {
491398
491398
  type: "string",
491399
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
491399
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
491400
491400
  },
491401
491401
  selector: {
491402
491402
  type: "string",
@@ -496627,7 +496627,7 @@ var init_schemas = __esm({
496627
496627
  },
496628
496628
  elementText: {
496629
496629
  type: "string",
496630
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
496630
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
496631
496631
  },
496632
496632
  elementId: {
496633
496633
  type: "string",
@@ -497159,7 +497159,7 @@ var init_schemas = __esm({
497159
497159
  },
497160
497160
  elementText: {
497161
497161
  type: "string",
497162
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
497162
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
497163
497163
  },
497164
497164
  elementId: {
497165
497165
  type: "string",
@@ -535496,7 +535496,7 @@ var init_schemas = __esm({
535496
535496
  },
535497
535497
  elementText: {
535498
535498
  type: "string",
535499
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
535499
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
535500
535500
  },
535501
535501
  selector: {
535502
535502
  type: "string",
@@ -539642,7 +539642,7 @@ var init_schemas = __esm({
539642
539642
  },
539643
539643
  elementText: {
539644
539644
  type: "string",
539645
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
539645
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
539646
539646
  },
539647
539647
  selector: {
539648
539648
  type: "string",
@@ -544873,7 +544873,7 @@ var init_schemas = __esm({
544873
544873
  },
544874
544874
  elementText: {
544875
544875
  type: "string",
544876
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
544876
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
544877
544877
  },
544878
544878
  elementId: {
544879
544879
  type: "string",
@@ -545405,7 +545405,7 @@ var init_schemas = __esm({
545405
545405
  },
545406
545406
  elementText: {
545407
545407
  type: "string",
545408
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
545408
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
545409
545409
  },
545410
545410
  elementId: {
545411
545411
  type: "string",
@@ -580397,7 +580397,7 @@ var init_schemas = __esm({
580397
580397
  },
580398
580398
  elementText: {
580399
580399
  type: "string",
580400
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
580400
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
580401
580401
  },
580402
580402
  selector: {
580403
580403
  type: "string",
@@ -584543,7 +584543,7 @@ var init_schemas = __esm({
584543
584543
  },
584544
584544
  elementText: {
584545
584545
  type: "string",
584546
- description: "Display text of the element to find. If combined with other element finding fields, the element must match all specified criteria."
584546
+ description: "Display text of the element to find. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed to single spaces), so text a framework splits across several nodes still matches and a driver's surrounding whitespace doesn't cause a miss. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text. If combined with other element finding fields, the element must match all specified criteria."
584547
584547
  },
584548
584548
  selector: {
584549
584549
  type: "string",
@@ -589774,7 +589774,7 @@ var init_schemas = __esm({
589774
589774
  },
589775
589775
  elementText: {
589776
589776
  type: "string",
589777
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
589777
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
589778
589778
  },
589779
589779
  elementId: {
589780
589780
  type: "string",
@@ -590306,7 +590306,7 @@ var init_schemas = __esm({
590306
590306
  },
590307
590307
  elementText: {
590308
590308
  type: "string",
590309
- description: "Text content the element must contain. Supports exact match or regex pattern using /pattern/ syntax."
590309
+ description: "Display text of the element to wait for. Matched against the element's full visible text with whitespace normalized (leading/trailing trimmed, internal runs collapsed), so framework-fragmented text still matches. Wrap the value in slashes (`/pattern/`) to match a substring by regular expression instead of the whole normalized text."
590310
590310
  },
590311
590311
  elementId: {
590312
590312
  type: "string",
@@ -631868,6 +631868,9 @@ function getRandomUUID() {
631868
631868
  return v.toString(16);
631869
631869
  });
631870
631870
  }
631871
+ function cloneForValidation(object) {
631872
+ return JSON.parse(JSON.stringify(object));
631873
+ }
631871
631874
  function escapeRegExp(string) {
631872
631875
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
631873
631876
  }
@@ -631891,29 +631894,37 @@ function validate({ schemaKey, object, addDefaults = true }) {
631891
631894
  result.object = object;
631892
631895
  return result;
631893
631896
  }
631894
- validationObject = JSON.parse(JSON.stringify(object));
631897
+ validationObject = cloneForValidation(object);
631895
631898
  result.valid = check(validationObject);
631896
631899
  result.errors = "";
631897
631900
  if (check.errors) {
631901
+ const targetErrors = check.errors;
631898
631902
  const compatibleSchemasList = compatibleSchemas[schemaKey];
631899
631903
  if (!compatibleSchemasList) {
631900
- result.errors = check.errors.map((error) => `${error.instancePath} ${error.message} (${JSON.stringify(error.params)})`).join(", ");
631904
+ result.errors = targetErrors.map((error) => `${error.instancePath} ${error.message} (${JSON.stringify(error.params)})`).join(", ");
631901
631905
  result.object = object;
631902
631906
  result.valid = false;
631903
631907
  return result;
631904
631908
  }
631905
- const matchedSchemaKey = compatibleSchemasList.find((key) => {
631906
- validationObject = JSON.parse(JSON.stringify(object));
631907
- const check2 = ajv.getSchema(key);
631908
- if (check2 && check2(validationObject))
631909
- return key;
631909
+ let matchedSchemaKey = compatibleSchemasList.find((key) => {
631910
+ const probe = ajvCheck.getSchema(key);
631911
+ return probe(object);
631910
631912
  });
631911
631913
  if (!matchedSchemaKey) {
631912
- result.errors = check.errors.map((error) => `${error.instancePath} ${error.message} (${JSON.stringify(error.params)})`).join(", ");
631914
+ matchedSchemaKey = compatibleSchemasList.find((key) => {
631915
+ const mutatingCheck = ajv.getSchema(key);
631916
+ return mutatingCheck(cloneForValidation(object));
631917
+ });
631918
+ }
631919
+ if (!matchedSchemaKey) {
631920
+ result.errors = targetErrors.map((error) => `${error.instancePath} ${error.message} (${JSON.stringify(error.params)})`).join(", ");
631913
631921
  result.object = object;
631914
631922
  result.valid = false;
631915
631923
  return result;
631916
631924
  } else {
631925
+ validationObject = cloneForValidation(object);
631926
+ const matchedCheck = ajv.getSchema(matchedSchemaKey);
631927
+ matchedCheck(validationObject);
631917
631928
  const transformedObject = transformToSchemaKey({
631918
631929
  currentSchema: matchedSchemaKey,
631919
631930
  targetSchema: schemaKey,
@@ -632270,7 +632281,7 @@ Errors: ${result.errors}`);
632270
632281
  }
632271
632282
  return null;
632272
632283
  }
632273
- var import_ajv, import_ajv_formats, import_ajv_keywords, import_ajv_errors, import_dynamicDefaults, ajv, compatibleSchemas;
632284
+ var import_ajv, import_ajv_formats, import_ajv_keywords, import_ajv_errors, import_dynamicDefaults, ajv, ajvCheck, compatibleSchemas;
632274
632285
  var init_validate = __esm({
632275
632286
  "dist/common/src/validate.js"() {
632276
632287
  "use strict";
@@ -632287,12 +632298,23 @@ var init_validate = __esm({
632287
632298
  allowUnionTypes: true,
632288
632299
  coerceTypes: true
632289
632300
  });
632301
+ ajvCheck = new import_ajv.default({
632302
+ strictSchema: false,
632303
+ useDefaults: false,
632304
+ allErrors: true,
632305
+ allowUnionTypes: true,
632306
+ coerceTypes: false
632307
+ });
632290
632308
  import_dynamicDefaults.default.DEFAULTS.uuid = (_args) => getRandomUUID;
632291
632309
  (0, import_ajv_formats.default)(ajv);
632292
632310
  (0, import_ajv_keywords.default)(ajv);
632293
632311
  (0, import_ajv_errors.default)(ajv);
632312
+ (0, import_ajv_formats.default)(ajvCheck);
632313
+ (0, import_ajv_keywords.default)(ajvCheck);
632314
+ (0, import_ajv_errors.default)(ajvCheck);
632294
632315
  for (const [key, value] of Object.entries(schemas)) {
632295
632316
  ajv.addSchema(value, key);
632317
+ ajvCheck.addSchema(value, key);
632296
632318
  }
632297
632319
  compatibleSchemas = {
632298
632320
  config_v3: ["config_v2"],
@@ -633722,8 +633744,8 @@ function waitForStdio(bg, expected, { deadline }) {
633722
633744
  return Promise.reject(new Error(`waitUntil.stdio: invalid regular expression ${expected}: ${error.message}`));
633723
633745
  }
633724
633746
  }
633725
- const matchesText = (text) => regex ? regex.test(text) : text.includes(expected);
633726
- const matched = () => matchesText(bg.getStdout()) || matchesText(bg.getStderr());
633747
+ const matchesText2 = (text) => regex ? regex.test(text) : text.includes(expected);
633748
+ const matched = () => matchesText2(bg.getStdout()) || matchesText2(bg.getStderr());
633727
633749
  return new Promise((resolve, reject) => {
633728
633750
  if (matched())
633729
633751
  return resolve();
@@ -634062,13 +634084,14 @@ async function loadEnvs(envsFile) {
634062
634084
  }
634063
634085
  }
634064
634086
  function logLevelEnabled(config, level) {
634065
- if (config.logLevel === "error" && level === "error")
634087
+ const currentLevel = config.logLevel || "info";
634088
+ if (currentLevel === "error" && level === "error")
634066
634089
  return true;
634067
- if (config.logLevel === "warning" && (level === "error" || level === "warning"))
634090
+ if (currentLevel === "warning" && (level === "error" || level === "warning"))
634068
634091
  return true;
634069
- if (config.logLevel === "info" && (level === "error" || level === "warning" || level === "info"))
634092
+ if (currentLevel === "info" && (level === "error" || level === "warning" || level === "info"))
634070
634093
  return true;
634071
- if (config.logLevel === "debug" && (level === "error" || level === "warning" || level === "info" || level === "debug"))
634094
+ if (currentLevel === "debug" && (level === "error" || level === "warning" || level === "info" || level === "debug"))
634072
634095
  return true;
634073
634096
  return false;
634074
634097
  }
@@ -635100,12 +635123,19 @@ var init_files = __esm({
635100
635123
  });
635101
635124
 
635102
635125
  // dist/core/openapi.js
635126
+ function getGenerator() {
635127
+ if (!jsfPromise) {
635128
+ jsfPromise = import("json-schema-faker").then(({ createGenerator }) => createGenerator({ optionalsProbability: 0 }));
635129
+ }
635130
+ return jsfPromise;
635131
+ }
635103
635132
  async function loadDescription(descriptionPath = "") {
635104
635133
  if (!descriptionPath) {
635105
635134
  throw new Error("Description is required.");
635106
635135
  }
635107
635136
  const definition = await readFile({ fileURLOrPath: descriptionPath });
635108
- const dereferencedDefinition = await import_json_schema_ref_parser.default.dereference(definition);
635137
+ const parser = (await import("@apidevtools/json-schema-ref-parser")).default;
635138
+ const dereferencedDefinition = await parser.dereference(definition);
635109
635139
  return dereferencedDefinition;
635110
635140
  }
635111
635141
  async function getOperation(definition = {}, operationId = "", responseCode = "", exampleKey = "", server = "") {
@@ -635229,7 +635259,8 @@ async function getExample(definition = {}, exampleKey = "", generateFromSchema =
635229
635259
  }
635230
635260
  if (generateFromSchema && definition.type) {
635231
635261
  try {
635232
- example = await jsf.generate(definition);
635262
+ const generator = await getGenerator();
635263
+ example = await generator.generate(definition);
635233
635264
  if (example)
635234
635265
  return example;
635235
635266
  } catch (error) {
@@ -635304,15 +635335,12 @@ function checkForExamples(definition = {}, exampleKey = "") {
635304
635335
  return true;
635305
635336
  return false;
635306
635337
  }
635307
- var import_json_schema_faker, import_json_schema_ref_parser, jsf;
635338
+ var jsfPromise;
635308
635339
  var init_openapi = __esm({
635309
635340
  "dist/core/openapi.js"() {
635310
635341
  "use strict";
635311
635342
  init_utils();
635312
- import_json_schema_faker = require("json-schema-faker");
635313
635343
  init_files();
635314
- import_json_schema_ref_parser = __toESM(require("@apidevtools/json-schema-ref-parser"), 1);
635315
- jsf = (0, import_json_schema_faker.createGenerator)({ optionalsProbability: 0 });
635316
635344
  }
635317
635345
  });
635318
635346
 
@@ -635320,9 +635348,11 @@ var init_openapi = __esm({
635320
635348
  var config_exports = {};
635321
635349
  __export(config_exports, {
635322
635350
  clearAppCache: () => clearAppCache,
635351
+ detectInstalledBrowserDrivers: () => detectInstalledBrowserDrivers,
635323
635352
  getAvailableApps: () => getAvailableApps,
635324
635353
  getBrowserDiagnostics: () => getBrowserDiagnostics,
635325
635354
  getEnvironment: () => getEnvironment,
635355
+ patchAppCache: () => patchAppCache,
635326
635356
  resolveConcurrentRunners: () => resolveConcurrentRunners,
635327
635357
  setConfig: () => setConfig,
635328
635358
  verifyAppDrivers: () => verifyAppDrivers
@@ -635533,13 +635563,62 @@ function clearAppCache(config) {
635533
635563
  }
635534
635564
  cachedAppsByDir.delete(cacheKeyFor(config));
635535
635565
  }
635566
+ async function patchAppCache(config, installed, deps = {}) {
635567
+ const key = cacheKeyFor(config);
635568
+ try {
635569
+ const verify = deps.verify ?? verifyDriverBinary;
635570
+ const drivers = (deps.detectDrivers ?? detectInstalledBrowserDrivers)(config);
635571
+ const descriptors = [];
635572
+ for (const b of installed ?? []) {
635573
+ if (b.name === "chrome" && b.path && b.driverPath && drivers.chromium) {
635574
+ descriptors.push({
635575
+ app: {
635576
+ name: "chrome",
635577
+ version: b.version,
635578
+ path: b.path,
635579
+ driver: b.driverPath
635580
+ },
635581
+ driverName: "chromedriver",
635582
+ driverPath: b.driverPath
635583
+ });
635584
+ } else if (b.name === "firefox" && b.path && drivers.gecko) {
635585
+ descriptors.push({
635586
+ app: { name: "firefox", version: b.version, path: b.path },
635587
+ driverName: b.driverPath ? "geckodriver" : void 0,
635588
+ driverPath: b.driverPath
635589
+ });
635590
+ }
635591
+ }
635592
+ if (descriptors.length === 0) {
635593
+ cachedAppsByDir.delete(key);
635594
+ return;
635595
+ }
635596
+ const verifiedApps = await verifyAppDrivers(descriptors, {
635597
+ verify: (driverName, driverPath) => verify(driverName, driverPath),
635598
+ logger: (msg, level) => log(config, level ?? "warning", msg)
635599
+ });
635600
+ const existing = cachedAppsByDir.get(key) ?? [];
635601
+ const existingNames = new Set(existing.map((a) => a?.name));
635602
+ const additions = verifiedApps.filter((a) => !existingNames.has(a?.name));
635603
+ cachedAppsByDir.set(key, [...existing, ...additions]);
635604
+ } catch {
635605
+ cachedAppsByDir.delete(key);
635606
+ }
635607
+ }
635608
+ function detectInstalledBrowserDrivers(config, isInstalled = (name) => Boolean(resolveHeavyDepPath(name, { cacheDir: config?.cacheDir }))) {
635609
+ return {
635610
+ chromium: isInstalled("appium-chromium-driver"),
635611
+ gecko: isInstalled("appium-geckodriver"),
635612
+ safari: isInstalled("appium-safari-driver")
635613
+ };
635614
+ }
635536
635615
  async function probeBrowserEnvironment({ config, browsersDir }) {
635537
635616
  setAppiumHome({ cacheDir: config?.cacheDir });
635538
635617
  const cwd = process.cwd();
635539
635618
  process.chdir(import_node_path9.default.join(__dirname4, "../.."));
635540
635619
  let installedBrowsers = [];
635541
635620
  let browserDetectionFailed = false;
635542
- let appiumDriverOutput = "";
635621
+ let installedDrivers = { chromium: false, gecko: false, safari: false };
635543
635622
  try {
635544
635623
  const browsersInstalled = resolveHeavyDepPath("@puppeteer/browsers", {
635545
635624
  cacheDir: config?.cacheDir
@@ -635559,47 +635638,11 @@ async function probeBrowserEnvironment({ config, browsersDir }) {
635559
635638
  installedBrowsers = [];
635560
635639
  }
635561
635640
  }
635562
- const appiumEntry = resolveHeavyDepPath("appium", {
635563
- cacheDir: config?.cacheDir
635564
- });
635565
- const installedAppiumDrivers = await new Promise((resolve) => {
635566
- if (!appiumEntry) {
635567
- resolve({
635568
- stdout: "",
635569
- stderr: "appium is not installed; driver list unavailable",
635570
- exitCode: 1
635571
- });
635572
- return;
635573
- }
635574
- const child = (0, import_node_child_process6.spawn)(process.execPath, [appiumEntry, "driver", "list"], { env: process.env });
635575
- let stdout = "";
635576
- let stderr = "";
635577
- child.stdout?.on("data", (c) => {
635578
- stdout += typeof c === "string" ? c : c.toString("utf8");
635579
- });
635580
- child.stderr?.on("data", (c) => {
635581
- stderr += typeof c === "string" ? c : c.toString("utf8");
635582
- });
635583
- child.on("error", (err) => {
635584
- resolve({
635585
- stdout: stdout.replace(/\n$/, ""),
635586
- stderr: (stderr + String(err)).replace(/\n$/, ""),
635587
- exitCode: 1
635588
- });
635589
- });
635590
- child.on("close", (code) => {
635591
- resolve({
635592
- stdout: stdout.replace(/\n$/, ""),
635593
- stderr: stderr.replace(/\n$/, ""),
635594
- exitCode: code ?? 1
635595
- });
635596
- });
635597
- });
635598
- appiumDriverOutput = installedAppiumDrivers.stdout + "\n" + installedAppiumDrivers.stderr;
635641
+ installedDrivers = detectInstalledBrowserDrivers(config);
635599
635642
  } finally {
635600
635643
  process.chdir(cwd);
635601
635644
  }
635602
- return { installedBrowsers, appiumDriverOutput, browserDetectionFailed };
635645
+ return { installedBrowsers, installedDrivers, browserDetectionFailed };
635603
635646
  }
635604
635647
  async function getAvailableApps({ config }) {
635605
635648
  const browsersDir = getBrowsersDir({ cacheDir: config?.cacheDir });
@@ -635607,12 +635650,12 @@ async function getAvailableApps({ config }) {
635607
635650
  const hit = cachedAppsByDir.get(key);
635608
635651
  if (hit)
635609
635652
  return hit;
635610
- const { installedBrowsers, appiumDriverOutput, browserDetectionFailed } = await probeBrowserEnvironment({ config, browsersDir });
635653
+ const { installedBrowsers, installedDrivers, browserDetectionFailed } = await probeBrowserEnvironment({ config, browsersDir });
635611
635654
  const descriptors = [];
635612
635655
  const chrome = installedBrowsers.find((browser) => browser.browser === "chrome");
635613
635656
  const chromeVersion = chrome?.buildId;
635614
635657
  const chromedriver = installedBrowsers.find((browser) => browser.browser === "chromedriver");
635615
- const appiumChromium = appiumDriverOutput.match(/\n.*chromium.*installed \(npm\).*\n/);
635658
+ const appiumChromium = installedDrivers.chromium;
635616
635659
  if (chrome && chromedriver && appiumChromium) {
635617
635660
  descriptors.push({
635618
635661
  app: {
@@ -635626,7 +635669,7 @@ async function getAvailableApps({ config }) {
635626
635669
  });
635627
635670
  }
635628
635671
  const firefox = installedBrowsers.find((browser) => browser.browser === "firefox");
635629
- const appiumFirefox = appiumDriverOutput.match(/\n.*gecko.*installed \(npm\).*\n/);
635672
+ const appiumFirefox = installedDrivers.gecko;
635630
635673
  if (firefox && appiumFirefox) {
635631
635674
  const geckodriverPath = resolveGeckodriverBinaryPath(config, browsersDir);
635632
635675
  descriptors.push({
@@ -635642,7 +635685,7 @@ async function getAvailableApps({ config }) {
635642
635685
  const currentPlatform = config?.environment?.platform ?? getEnvironment().platform;
635643
635686
  if (currentPlatform === "mac") {
635644
635687
  const safariVersion = await spawnCommand("defaults read /Applications/Safari.app/Contents/Info.plist CFBundleShortVersionString");
635645
- const appiumSafari = appiumDriverOutput.match(/\n.*safari.*installed \(npm\).*\n/);
635688
+ const appiumSafari = installedDrivers.safari;
635646
635689
  if (safariVersion.exitCode === 0 && appiumSafari) {
635647
635690
  descriptors.push({
635648
635691
  app: { name: "safari", version: safariVersion.stdout.trim(), path: "" },
@@ -638294,6 +638337,7 @@ async function loadHerettoContent(herettoConfig, log3, config, deps) {
638294
638337
  }
638295
638338
 
638296
638339
  // dist/core/detectTests.js
638340
+ var DETECTION_PARSE_CONCURRENCY = 8;
638297
638341
  async function detectTests2({ config }) {
638298
638342
  const files = await qualifyFiles({ config });
638299
638343
  log(config, "debug", `FILES:`);
@@ -638325,7 +638369,20 @@ async function isValidSourceFile({ config, files, source, allowedExtensions }) {
638325
638369
  if (files.indexOf(source) >= 0)
638326
638370
  return false;
638327
638371
  if (import_node_path11.default.extname(source) === ".json" || import_node_path11.default.extname(source) === ".yaml" || import_node_path11.default.extname(source) === ".yml") {
638328
- const content = await readFile({ fileURLOrPath: source });
638372
+ const ext = import_node_path11.default.extname(source).slice(1).toLowerCase();
638373
+ let rawContent;
638374
+ try {
638375
+ rawContent = await import_node_fs13.default.promises.readFile(source, "utf8");
638376
+ } catch {
638377
+ log(config, "debug", `${source} couldn't be read. Skipping.`);
638378
+ return false;
638379
+ }
638380
+ let content;
638381
+ try {
638382
+ content = ext === "json" ? JSON.parse(rawContent) : import_yaml3.default.parse(rawContent);
638383
+ } catch {
638384
+ content = rawContent;
638385
+ }
638329
638386
  if (typeof content !== "object") {
638330
638387
  log(config, "debug", `${source} isn't a valid test specification. Skipping.`);
638331
638388
  return false;
@@ -638366,6 +638423,7 @@ async function isValidSourceFile({ config, files, source, allowedExtensions }) {
638366
638423
  }
638367
638424
  }
638368
638425
  }
638426
+ config._parsedFileCache?.set(source, { rawContent, content });
638369
638427
  }
638370
638428
  const extension = import_node_path11.default.extname(source).substring(1);
638371
638429
  if (!allowed.has(extension)) {
@@ -638408,6 +638466,8 @@ async function qualifyFiles({ config }) {
638408
638466
  let sequence = [];
638409
638467
  const phaseByFile = /* @__PURE__ */ new Map();
638410
638468
  config._phaseByFile = phaseByFile;
638469
+ const parsedFileCache = /* @__PURE__ */ new Map();
638470
+ config._parsedFileCache = parsedFileCache;
638411
638471
  const toEntries = (value, phase) => (value == null ? [] : [].concat(value)).map((source) => ({
638412
638472
  source,
638413
638473
  phase
@@ -638536,27 +638596,34 @@ async function qualifyFiles({ config }) {
638536
638596
  return files;
638537
638597
  }
638538
638598
  async function parseTests({ config, files }) {
638539
- let specs = [];
638540
- for (const file of files) {
638599
+ const parseOneFile = async (file) => {
638541
638600
  log(config, "debug", `file: ${file}`);
638542
638601
  const extension = import_node_path11.default.extname(file).slice(1);
638543
638602
  let content = "";
638544
638603
  let rawContent;
638545
638604
  if (extension === "json" || extension === "yaml" || extension === "yml") {
638546
- try {
638547
- rawContent = await import_node_fs13.default.promises.readFile(file, "utf8");
638548
- if (extension === "json") {
638549
- content = JSON.parse(rawContent);
638550
- } else {
638551
- content = import_yaml3.default.parse(rawContent);
638605
+ const cached = config._parsedFileCache?.get(file);
638606
+ if (cached) {
638607
+ rawContent = cached.rawContent;
638608
+ content = cached.content;
638609
+ } else {
638610
+ try {
638611
+ rawContent = await import_node_fs13.default.promises.readFile(file, "utf8");
638612
+ if (extension === "json") {
638613
+ content = JSON.parse(rawContent);
638614
+ } else {
638615
+ content = import_yaml3.default.parse(rawContent);
638616
+ }
638617
+ } catch (err) {
638618
+ console.warn(`Failed to read/parse ${file}: ${err.message}`);
638619
+ content = await readFile({ fileURLOrPath: file });
638552
638620
  }
638553
- } catch (err) {
638554
- console.warn(`Failed to read/parse ${file}: ${err.message}`);
638555
- content = await readFile({ fileURLOrPath: file });
638556
638621
  }
638557
638622
  } else {
638558
638623
  content = await readFile({ fileURLOrPath: file });
638559
638624
  }
638625
+ if (content === null)
638626
+ return null;
638560
638627
  if (typeof content === "object") {
638561
638628
  if (!content.specId)
638562
638629
  content.specId = generateSpecId(file);
@@ -638620,7 +638687,10 @@ async function parseTests({ config, files }) {
638620
638687
  content = await resolvePaths({
638621
638688
  config,
638622
638689
  object: content,
638623
- filePath: file
638690
+ filePath: file,
638691
+ // Detection only ever resolves specs; passing the known objectType skips
638692
+ // resolvePaths' config_v3-then-spec_v3 discovery probe (item 3.1).
638693
+ objectType: "spec"
638624
638694
  });
638625
638695
  for (let t = 0; t < content.tests.length; t++) {
638626
638696
  const test = content.tests[t];
@@ -638685,13 +638755,16 @@ async function parseTests({ config, files }) {
638685
638755
  if (!validation.valid) {
638686
638756
  log(config, "warning", validation);
638687
638757
  log(config, "warning", `After applying setup and cleanup steps, ${file} isn't a valid test specification. Skipping.`);
638688
- continue;
638758
+ return null;
638689
638759
  }
638690
638760
  content = validation.object;
638691
638761
  content = await resolvePaths({
638692
638762
  config,
638693
638763
  object: content,
638694
- filePath: file
638764
+ filePath: file,
638765
+ // Detection only ever resolves specs; passing the known objectType skips
638766
+ // resolvePaths' config_v3-then-spec_v3 discovery probe (item 3.1).
638767
+ objectType: "spec"
638695
638768
  });
638696
638769
  content._phase = specPhase;
638697
638770
  for (const [testIdx, testMap] of stepLocations) {
@@ -638724,7 +638797,7 @@ async function parseTests({ config, files }) {
638724
638797
  }
638725
638798
  }
638726
638799
  }
638727
- specs.push(content);
638800
+ return content;
638728
638801
  } else {
638729
638802
  let id = generateSpecId(file);
638730
638803
  let spec = {
@@ -638752,7 +638825,7 @@ async function parseTests({ config, files }) {
638752
638825
  });
638753
638826
  if (!validation2.valid) {
638754
638827
  log(config, "warning", `Failed to convert ${file} to a runShell step: ${validation2.errors}. Skipping.`);
638755
- continue;
638828
+ return null;
638756
638829
  }
638757
638830
  spec.tests.push(test);
638758
638831
  const specValidation = validate({
@@ -638766,12 +638839,14 @@ async function parseTests({ config, files }) {
638766
638839
  spec = await resolvePaths({
638767
638840
  config,
638768
638841
  object: spec,
638769
- filePath: file
638842
+ filePath: file,
638843
+ // Detection only resolves specs — skip the discovery probe (3.1).
638844
+ objectType: "spec"
638770
638845
  });
638771
638846
  spec._phase = config._phaseByFile?.get(import_node_path11.default.resolve(file)) ?? "main";
638772
- specs.push(spec);
638847
+ return spec;
638773
638848
  }
638774
- continue;
638849
+ return null;
638775
638850
  }
638776
638851
  const tests = await detectTests({
638777
638852
  config,
@@ -638793,14 +638868,21 @@ async function parseTests({ config, files }) {
638793
638868
  spec = await resolvePaths({
638794
638869
  config,
638795
638870
  object: spec,
638796
- filePath: file
638871
+ filePath: file,
638872
+ // Detection only resolves specs — skip the discovery probe (3.1).
638873
+ objectType: "spec"
638797
638874
  });
638798
638875
  spec._phase = config._phaseByFile?.get(import_node_path11.default.resolve(file)) ?? "main";
638799
- specs.push(spec);
638876
+ return spec;
638800
638877
  }
638801
638878
  }
638802
- }
638803
- return specs;
638879
+ return null;
638880
+ };
638881
+ const slots = new Array(files.length).fill(null);
638882
+ await runConcurrent(files.map((_, i) => i), DETECTION_PARSE_CONCURRENCY, async (i) => {
638883
+ slots[i] = await parseOneFile(files[i]);
638884
+ });
638885
+ return slots.filter((spec) => spec != null);
638804
638886
  }
638805
638887
 
638806
638888
  // dist/core/resolveTests.js
@@ -638897,11 +638979,22 @@ ${JSON.stringify(documentArray, null, 2)}`);
638897
638979
  const openApiDocuments = [];
638898
638980
  if (config?.integrations?.openApi?.length > 0)
638899
638981
  openApiDocuments.push(...config.integrations.openApi);
638982
+ const descriptionCache = config._openApiDescriptionCache || (config._openApiDescriptionCache = /* @__PURE__ */ new Map());
638900
638983
  if (documentArray?.length > 0) {
638901
638984
  for (const definition of documentArray) {
638902
638985
  try {
638903
- const openApiDefinition = await loadDescription(definition.descriptionPath);
638904
- definition.definition = openApiDefinition;
638986
+ if (!definition.definition) {
638987
+ const key = definition.descriptionPath;
638988
+ let pending = descriptionCache.get(key);
638989
+ if (!pending) {
638990
+ pending = loadDescription(key).catch((err) => {
638991
+ descriptionCache.delete(key);
638992
+ throw err;
638993
+ });
638994
+ descriptionCache.set(key, pending);
638995
+ }
638996
+ definition.definition = await pending;
638997
+ }
638905
638998
  } catch (error) {
638906
638999
  log(config, "error", `Failed to load OpenAPI definition from ${definition.descriptionPath}: ${error.message}`);
638907
639000
  continue;
@@ -639028,6 +639121,7 @@ ${JSON.stringify(detectedTests, null, 2)}`);
639028
639121
  config,
639029
639122
  specs: []
639030
639123
  };
639124
+ config._openApiDescriptionCache = /* @__PURE__ */ new Map();
639031
639125
  log(config, "info", "Resolving test specs.");
639032
639126
  for (const spec of detectedTests) {
639033
639127
  const resolvedSpec = await resolveSpec({ config, spec });
@@ -642697,7 +642791,7 @@ async function setElementOutputs({ element }) {
642697
642791
  }
642698
642792
  async function findElementByRegex({ pattern, timeout, driver }) {
642699
642793
  await driver.pause(timeout);
642700
- const elements = await driver.$$("//*[normalize-space(text())]");
642794
+ const elements = await driver.$$("//*[text()[normalize-space()]]");
642701
642795
  for (const element of elements) {
642702
642796
  const text = await element.getText();
642703
642797
  if (text.match(pattern)) {
@@ -642784,7 +642878,8 @@ async function findElementByShorthand({ string, timeout = 5e3, driver }) {
642784
642878
  await el.waitForExist({ timeout });
642785
642879
  return el;
642786
642880
  }).catch(() => null);
642787
- const textPromise = driver.$(`//*[normalize-space(text())="${string}"]`).then(async (el) => {
642881
+ const textLiteral = xpathLiteral2(normalizeText(string));
642882
+ const textPromise = driver.$(`//*[normalize-space(.)=${textLiteral} and not(.//*[normalize-space(.)=${textLiteral}])]`).then(async (el) => {
642788
642883
  await el.waitForExist({ timeout });
642789
642884
  return el;
642790
642885
  }).catch(() => null);
@@ -642832,6 +642927,24 @@ async function findElementByShorthand({ string, timeout = 5e3, driver }) {
642832
642927
  function isRegexPattern(str) {
642833
642928
  return typeof str === "string" && str.startsWith("/") && str.endsWith("/");
642834
642929
  }
642930
+ function normalizeText(value) {
642931
+ return String(value ?? "").replace(/\s+/g, " ").trim();
642932
+ }
642933
+ function xpathLiteral2(value) {
642934
+ if (!value.includes('"'))
642935
+ return `"${value}"`;
642936
+ if (!value.includes("'"))
642937
+ return `'${value}'`;
642938
+ const parts = value.split('"').map((p) => `"${p}"`);
642939
+ return `concat(${parts.join(`, '"', `)})`;
642940
+ }
642941
+ function matchesText(value, pattern) {
642942
+ if (isRegexPattern(pattern)) {
642943
+ const regex = new RegExp(pattern.slice(1, -1));
642944
+ return regex.test(String(value ?? ""));
642945
+ }
642946
+ return normalizeText(value) === normalizeText(pattern);
642947
+ }
642835
642948
  function matchesPattern(value, pattern) {
642836
642949
  if (isRegexPattern(pattern)) {
642837
642950
  const regex = new RegExp(pattern.slice(1, -1));
@@ -642933,8 +643046,11 @@ async function findElementByCriteria({ selector, elementText, elementId, element
642933
643046
  }
642934
643047
  }
642935
643048
  }
642936
- if (elementText) {
642937
- xpathConditions.push(`normalize-space(text())`);
643049
+ if (elementText && !isRegexPattern(elementText)) {
643050
+ const lit = xpathLiteral2(normalizeText(elementText));
643051
+ xpathConditions.push(`(normalize-space(.)=${lit} and not(.//*[normalize-space(.)=${lit}]))`);
643052
+ } else if (elementText) {
643053
+ xpathConditions.push(`text()[normalize-space()]`);
642938
643054
  }
642939
643055
  let xpath;
642940
643056
  if (xpathConditions.length > 0) {
@@ -643011,7 +643127,9 @@ async function findElementByCriteria({ selector, elementText, elementId, element
643011
643127
  }
643012
643128
  elementCriteriaUsed.push(checkType.type);
643013
643129
  } else {
643014
- if (!actualValue || !matchesPattern(actualValue, checkType.value)) {
643130
+ const isTextCriterion = checkType.type === "elementText" || checkType.type === "elementAria";
643131
+ const matched = isTextCriterion ? matchesText(actualValue, checkType.value) : matchesPattern(actualValue, checkType.value);
643132
+ if (!actualValue || !matched) {
643015
643133
  allChecksPassed = false;
643016
643134
  break;
643017
643135
  }
@@ -652929,6 +653047,9 @@ async function runTests(config, options = {}) {
652929
653047
  return null;
652930
653048
  }
652931
653049
  }
653050
+ if (typeof options.updateJoin === "function") {
653051
+ await options.updateJoin();
653052
+ }
652932
653053
  if (config.dryRun) {
652933
653054
  console.log(JSON.stringify(resolvedTests, null, 2));
652934
653055
  cleanTemp();
@@ -652960,23 +653081,43 @@ async function runTests(config, options = {}) {
652960
653081
  }
652961
653082
  if (needs.browsers.size > 0) {
652962
653083
  try {
652963
- const { getAvailableApps: getAvailableApps2, clearAppCache: clearAppCache2 } = await Promise.resolve().then(() => (init_config(), config_exports));
653084
+ const { getAvailableApps: getAvailableApps2, patchAppCache: patchAppCache2 } = await Promise.resolve().then(() => (init_config(), config_exports));
652964
653085
  const { ensureBrowserInstalled: ensureBrowserInstalled2, requiredBrowserAssets: requiredBrowserAssets2 } = await Promise.resolve().then(() => (init_browsers(), browsers_exports));
652965
653086
  const available = await getAvailableApps2({ config });
652966
653087
  const availableNames = new Set(available.map((a) => a.name));
652967
- let installedAnything = false;
653088
+ const installedDescriptors = [];
652968
653089
  for (const browser of needs.browsers) {
652969
653090
  if (availableNames.has(browser))
652970
653091
  continue;
652971
653092
  const assets = requiredBrowserAssets2(browser);
653093
+ const assetResults = {};
652972
653094
  for (const asset of assets) {
652973
- await ensureBrowserInstalled2(asset, { ctx, deps: { logger: preflightLogger } });
653095
+ assetResults[asset] = await ensureBrowserInstalled2(asset, {
653096
+ ctx,
653097
+ deps: { logger: preflightLogger }
653098
+ });
652974
653099
  }
652975
- if (assets.length > 0)
652976
- installedAnything = true;
653100
+ if (assets.length === 0)
653101
+ continue;
653102
+ if (browser === "chrome") {
653103
+ installedDescriptors.push({
653104
+ name: "chrome",
653105
+ version: assetResults.chrome?.version,
653106
+ path: assetResults.chrome?.path,
653107
+ driverPath: assetResults.chromedriver?.path
653108
+ });
653109
+ } else if (browser === "firefox") {
653110
+ installedDescriptors.push({
653111
+ name: "firefox",
653112
+ version: assetResults.firefox?.version,
653113
+ path: assetResults.firefox?.path,
653114
+ driverPath: assetResults.geckodriver?.path
653115
+ });
653116
+ }
653117
+ }
653118
+ if (installedDescriptors.length > 0) {
653119
+ await patchAppCache2(config, installedDescriptors);
652977
653120
  }
652978
- if (installedAnything)
652979
- clearAppCache2(config);
652980
653121
  } catch (browserErr) {
652981
653122
  log(config, "debug", `Browser pre-flight check skipped: ${browserErr?.message ?? browserErr}`);
652982
653123
  }
@@ -653003,8 +653144,8 @@ async function runTests(config, options = {}) {
653003
653144
  } else {
653004
653145
  results = await runSpecs({ resolvedTests });
653005
653146
  }
653006
- log(config, "info", "RESULTS:");
653007
- log(config, "info", results);
653147
+ log(config, "debug", "RESULTS:");
653148
+ log(config, "debug", results);
653008
653149
  log(config, "info", "Cleaning up and finishing post-processing.");
653009
653150
  cleanTemp();
653010
653151
  sendTelemetry(config, "runTests", results);