ex-pw 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -25,15 +25,6 @@ import exPw from "ex-pw";
25
25
  expect.extend(exPw);
26
26
  ```
27
27
 
28
- ### Option 2: Import Individual Matchers
29
-
30
- ```typescript
31
- import { expect } from "@playwright/test";
32
- import { toBeClickable, toBeRequired, toMatchSchema } from "ex-pw";
33
-
34
- expect.extend({ toBeClickable, toBeRequired, toMatchSchema });
35
- ```
36
-
37
28
  ---
38
29
 
39
30
  ## Locator Matchers
@@ -516,13 +507,6 @@ await expect(request).toRespondWithin(1000);
516
507
  Asymmetric matchers can be used both in `expect().toEqual()` assertions and as
517
508
  standalone matchers.
518
509
 
519
- > **Note:** To use asymmetric matchers like `expect.toBeEmail()`, you need to
520
- > import `expect` directly from ex-pw:
521
- >
522
- > ```typescript
523
- > import { expect } from "ex-pw";
524
- > ```
525
-
526
510
  ### String Matchers
527
511
 
528
512
  #### toStartWith
package/dist/index.d.mts CHANGED
@@ -483,68 +483,434 @@ interface ExPwAsymmetricMatchers {
483
483
  }
484
484
 
485
485
 
486
- // Augment Playwright's types
487
- declare module '@playwright/test' {
488
- interface Matchers<R, T = unknown> {
489
- // Locator matchers (when T is Locator)
490
- toBeClickable(options?: TimeoutOptions): Promise<R>;
491
- toBeCheckable(options?: TimeoutOptions): Promise<R>;
492
- toBeRequired(options?: TimeoutOptions): Promise<R>;
493
- toBeInvalid(options?: TimeoutOptions): Promise<R>;
494
- toBeValid(options?: TimeoutOptions): Promise<R>;
495
- toHaveCountGreaterThan(count: number, options?: TimeoutOptions): Promise<R>;
496
- toHaveCountGreaterThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
497
- toHaveCountLessThan(count: number, options?: TimeoutOptions): Promise<R>;
498
- toHaveCountLessThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
499
- toHaveWidth(expected: number, options?: TimeoutOptions): Promise<R>;
500
- toHaveHeight(expected: number, options?: TimeoutOptions): Promise<R>;
501
- toHaveSize(width: number, height: number, options?: TimeoutOptions): Promise<R>;
502
- toHaveLoadedImage(options?: TimeoutOptions): Promise<R>;
503
-
504
-
505
- // Page matchers (when T is Page)
506
- toHaveCookie(name: string, options?: ToHaveCookieOptions$1): Promise<R>;
507
- toHaveLocalStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
508
- toHaveSessionStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
509
- toHaveClipboardText(expected: string | RegExp, options?: TimeoutOptions): Promise<R>;
510
- toHaveRequest(options?: ToHaveRequestOptions$1): Promise<R>;
511
- toHaveConsoleMessage(options?: ToHaveConsoleMessageOptions$1): Promise<R>;
512
- toHavePageError(options?: ToHavePageErrorOptions$1): Promise<R>;
513
-
514
-
515
- // TestInfo matchers (when T is TestInfo)
516
- toHaveNoErrors(options?: ToHaveNoErrorsOptions$1): R;
517
-
518
- // API matchers (when T is APIResponse)
519
- toMatchJSON(expected: unknown): Promise<R>;
520
- toMatchSchema(schema: ZodSchema): Promise<R>;
521
- toHaveStatus(expected: number | { min: number; max: number }): Promise<R>;
522
- toHaveHeader(name: string, options?: { value?: string | RegExp }): Promise<R>;
523
- toRespondWithin(timeout: number): Promise<R>;
524
-
525
- // General matchers (when T is Array or Locator)
526
- toBeSorted(options?: ToBeSortedOptions$1): Promise<R>;
527
-
528
- // Asymmetric matchers available as symmetric matchers
529
- toBeWithinRange(min: number, max: number): R;
530
- toBeUUID(version?: 'v1' | 'v4' | 'v5'): R;
531
- toBeISODate(): R;
532
- toBeDateString(format: string): R;
533
- toBeEmail(): R;
534
- toBeURL(options?: ToBeURLAsymmetricOptions): R;
535
- toBeJSON(): R;
536
- toStartWith(expected: string): R;
537
- toEndWith(expected: string): R;
538
- toBeUpperCase(): R;
539
- toBeLowerCase(): R;
540
- toBeKebabCase(): R;
541
- toBeCamelCase(): R;
542
- toBeSnakeCase(): R;
543
- toBePascalCase(): R;
486
+ // Augment Playwright's types using global namespace
487
+ declare global {
488
+ namespace PlaywrightTest {
489
+ interface Matchers<R, T = unknown> {
490
+ // Locator matchers (when T is Locator)
491
+
492
+ /**
493
+ * Asserts that an element is visible, enabled, stable, and not obscured.
494
+ * @example
495
+ * await expect(page.getByRole('button')).toBeClickable();
496
+ */
497
+ toBeClickable(options?: TimeoutOptions): Promise<R>;
498
+
499
+ /**
500
+ * Asserts that a checkbox or radio button is in a checkable state.
501
+ * @example
502
+ * await expect(page.getByRole('checkbox')).toBeCheckable();
503
+ */
504
+ toBeCheckable(options?: TimeoutOptions): Promise<R>;
505
+
506
+ /**
507
+ * Asserts that a form element is required.
508
+ * @example
509
+ * await expect(page.getByLabel('Email')).toBeRequired();
510
+ */
511
+ toBeRequired(options?: TimeoutOptions): Promise<R>;
512
+
513
+ /**
514
+ * Asserts that a form element is in an invalid validation state.
515
+ * @example
516
+ * await expect(page.getByRole('textbox')).toBeInvalid();
517
+ */
518
+ toBeInvalid(options?: TimeoutOptions): Promise<R>;
519
+
520
+ /**
521
+ * Asserts that a form element is in a valid validation state.
522
+ * @example
523
+ * await expect(page.getByRole('textbox')).toBeValid();
524
+ */
525
+ toBeValid(options?: TimeoutOptions): Promise<R>;
526
+
527
+ /**
528
+ * Asserts that a locator resolves to more than the specified number of elements.
529
+ * @example
530
+ * await expect(page.locator('li')).toHaveCountGreaterThan(3);
531
+ */
532
+ toHaveCountGreaterThan(count: number, options?: TimeoutOptions): Promise<R>;
533
+
534
+ /**
535
+ * Asserts that a locator resolves to at least the specified number of elements.
536
+ * @example
537
+ * await expect(page.locator('li')).toHaveCountGreaterThanOrEqual(1);
538
+ */
539
+ toHaveCountGreaterThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
540
+
541
+ /**
542
+ * Asserts that a locator resolves to fewer than the specified number of elements.
543
+ * @example
544
+ * await expect(page.locator('.loading')).toHaveCountLessThan(1);
545
+ */
546
+ toHaveCountLessThan(count: number, options?: TimeoutOptions): Promise<R>;
547
+
548
+ /**
549
+ * Asserts that a locator resolves to at most the specified number of elements.
550
+ * @example
551
+ * await expect(page.locator('.result')).toHaveCountLessThanOrEqual(5);
552
+ */
553
+ toHaveCountLessThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
554
+
555
+ /**
556
+ * Asserts that an element has a specific width in pixels.
557
+ * @example
558
+ * await expect(page.locator('#box')).toHaveWidth(100);
559
+ */
560
+ toHaveWidth(expected: number, options?: TimeoutOptions): Promise<R>;
561
+
562
+ /**
563
+ * Asserts that an element has a specific height in pixels.
564
+ * @example
565
+ * await expect(page.locator('#box')).toHaveHeight(200);
566
+ */
567
+ toHaveHeight(expected: number, options?: TimeoutOptions): Promise<R>;
568
+
569
+ /**
570
+ * Asserts that an element has a specific width and height in pixels.
571
+ * @example
572
+ * await expect(page.locator('#box')).toHaveSize(100, 200);
573
+ */
574
+ toHaveSize(width: number, height: number, options?: TimeoutOptions): Promise<R>;
575
+
576
+ /**
577
+ * Asserts that an image element has fully loaded.
578
+ * @example
579
+ * await expect(page.locator('img.logo')).toHaveLoadedImage();
580
+ */
581
+ toHaveLoadedImage(options?: TimeoutOptions): Promise<R>;
582
+
583
+ // Page matchers (when T is Page)
584
+
585
+ /**
586
+ * Asserts that the page has a cookie with the specified name.
587
+ * @example
588
+ * await expect(page).toHaveCookie('session_id');
589
+ * await expect(page).toHaveCookie('csrf', { value: /.+/ });
590
+ */
591
+ toHaveCookie(name: string, options?: ToHaveCookieOptions$1): Promise<R>;
592
+
593
+ /**
594
+ * Asserts that localStorage has a specific key.
595
+ * @example
596
+ * await expect(page).toHaveLocalStorage('token');
597
+ */
598
+ toHaveLocalStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
599
+
600
+ /**
601
+ * Asserts that sessionStorage has a specific key.
602
+ * @example
603
+ * await expect(page).toHaveSessionStorage('cart_id');
604
+ */
605
+ toHaveSessionStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
606
+
607
+ /**
608
+ * Asserts that the clipboard contains the specified text.
609
+ * @example
610
+ * await expect(page).toHaveClipboardText('copied text');
611
+ */
612
+ toHaveClipboardText(expected: string | RegExp, options?: TimeoutOptions): Promise<R>;
613
+
614
+ /**
615
+ * Asserts that a network request matching the criteria was made.
616
+ * @example
617
+ * await expect(page).toHaveRequest({ url: '/api/login', method: 'POST' });
618
+ */
619
+ toHaveRequest(options?: ToHaveRequestOptions$1): Promise<R>;
620
+
621
+ /**
622
+ * Asserts that a console message matching the criteria was logged.
623
+ * @example
624
+ * await expect(page).toHaveConsoleMessage({ type: 'error', text: /failed/ });
625
+ */
626
+ toHaveConsoleMessage(options?: ToHaveConsoleMessageOptions$1): Promise<R>;
627
+
628
+ /**
629
+ * Asserts that the page threw an uncaught exception.
630
+ * @example
631
+ * await expect(page).toHavePageError({ message: /ReferenceError/ });
632
+ */
633
+ toHavePageError(options?: ToHavePageErrorOptions$1): Promise<R>;
634
+
635
+ // TestInfo matchers (when T is TestInfo)
636
+
637
+ /**
638
+ * Asserts that there are no errors in the current test execution. Common with soft assertions.
639
+ * @example
640
+ * await expect(test).toHaveNoErrors();
641
+ */
642
+ toHaveNoErrors(options?: ToHaveNoErrorsOptions$1): R;
643
+
644
+ // API matchers (when T is APIResponse)
645
+
646
+ /**
647
+ * Asserts that the API response body matches the expected JSON.
648
+ * @example
649
+ * await expect(response).toMatchJSON({ success: true });
650
+ */
651
+ toMatchJSON(expected: unknown): Promise<R>;
652
+
653
+ /**
654
+ * Asserts that the API response body matches a Zod schema.
655
+ * @example
656
+ * await expect(response).toMatchSchema(UserSchema);
657
+ */
658
+ toMatchSchema(schema: ZodSchema): Promise<R>;
659
+
660
+ /**
661
+ * Asserts that the API response has the specified status code or is within range.
662
+ * @example
663
+ * await expect(response).toHaveStatus(200);
664
+ * await expect(response).toHaveStatus({ min: 200, max: 299 });
665
+ */
666
+ toHaveStatus(expected: number | { min: number; max: number }): Promise<R>;
667
+
668
+ /**
669
+ * Asserts that the API response contains a specific header.
670
+ * @example
671
+ * await expect(response).toHaveHeader('content-type', { value: /json/ });
672
+ */
673
+ toHaveHeader(name: string, options?: { value?: string | RegExp }): Promise<R>;
674
+
675
+ /**
676
+ * Asserts that the API response was received within the specified timeout.
677
+ * @example
678
+ * await expect(requestPromise).toRespondWithin(1000);
679
+ */
680
+ toRespondWithin(timeout: number): Promise<R>;
681
+
682
+ // General matchers (when T is Array or Locator)
683
+
684
+ /**
685
+ * Asserts that an array or items in a locator are sorted.
686
+ * @example
687
+ * await expect([1, 2, 3]).toBeSorted();
688
+ * await expect(page.locator('li')).toBeSorted({ descending: true });
689
+ */
690
+ toBeSorted(options?: ToBeSortedOptions$1): Promise<R>;
691
+
692
+ // Asymmetric matchers available as symmetric matchers
693
+
694
+ /**
695
+ * Asserts that the value is within the specified range (inclusive).
696
+ * @example
697
+ * await expect(5).toBeWithinRange(1, 10);
698
+ */
699
+ toBeWithinRange(min: number, max: number): R;
700
+
701
+ /**
702
+ * Asserts that the value is a valid UUID.
703
+ * @example
704
+ * await expect(uuid).toBeUUID();
705
+ */
706
+ toBeUUID(version?: 'v1' | 'v4' | 'v5'): R;
707
+
708
+ /**
709
+ * Asserts that the value is a valid ISO 8601 date string.
710
+ * @example
711
+ * await expect('2023-01-01T00:00:00Z').toBeISODate();
712
+ */
713
+ toBeISODate(): R;
714
+
715
+ /**
716
+ * Asserts that the value matches the specified date format.
717
+ * @example
718
+ * await expect('01/01/2023').toBeDateString('MM/DD/YYYY');
719
+ */
720
+ toBeDateString(format: string): R;
721
+
722
+ /**
723
+ * Asserts that the value is a valid email address.
724
+ * @example
725
+ * await expect('user@example.com').toBeEmail();
726
+ */
727
+ toBeEmail(): R;
728
+
729
+ /**
730
+ * Asserts that the value is a valid URL.
731
+ * @example
732
+ * await expect('https://example.com').toBeURL();
733
+ */
734
+ toBeURL(options?: ToBeURLAsymmetricOptions): R;
735
+
736
+ /**
737
+ * Asserts that the string value is valid JSON.
738
+ * @example
739
+ * await expect('{"a":1}').toBeJSON();
740
+ */
741
+ toBeJSON(): R;
742
+
743
+ /**
744
+ * Asserts that the string starts with the expected prefix.
745
+ * @example
746
+ * await expect('Hello World').toStartWith('Hello');
747
+ */
748
+ toStartWith(expected: string): R;
749
+
750
+ /**
751
+ * Asserts that the string ends with the expected suffix.
752
+ * @example
753
+ * await expect('image.png').toEndWith('.png');
754
+ */
755
+ toEndWith(expected: string): R;
756
+
757
+ /**
758
+ * Asserts that the string is uppercase.
759
+ * @example
760
+ * await expect('HELLO').toBeUpperCase();
761
+ */
762
+ toBeUpperCase(): R;
763
+
764
+ /**
765
+ * Asserts that the string is lowercase.
766
+ * @example
767
+ * await expect('hello').toBeLowerCase();
768
+ */
769
+ toBeLowerCase(): R;
770
+
771
+ /**
772
+ * Asserts that the string is kebab-case.
773
+ * @example
774
+ * await expect('my-class-name').toBeKebabCase();
775
+ */
776
+ toBeKebabCase(): R;
777
+
778
+ /**
779
+ * Asserts that the string is camelCase.
780
+ * @example
781
+ * await expect('myVariable').toBeCamelCase();
782
+ */
783
+ toBeCamelCase(): R;
784
+
785
+ /**
786
+ * Asserts that the string is snake_case.
787
+ * @example
788
+ * await expect('my_variable').toBeSnakeCase();
789
+ */
790
+ toBeSnakeCase(): R;
791
+
792
+ /**
793
+ * Asserts that the string is PascalCase.
794
+ * @example
795
+ * await expect('MyClass').toBePascalCase();
796
+ */
797
+ toBePascalCase(): R;
798
+ }
799
+
800
+ // Asymmetric matchers available on the expect object (e.g., expect.toBeLowerCase())
801
+ interface AsymmetricMatchers {
802
+ /**
803
+ * Matches any number within the specified range.
804
+ * @example
805
+ * expect(value).toEqual(expect.toBeWithinRange(1, 10));
806
+ */
807
+ toBeWithinRange(min: number, max: number): any;
808
+
809
+ /**
810
+ * Matches any string that is a valid UUID.
811
+ * @example
812
+ * expect(value).toEqual(expect.toBeUUID());
813
+ */
814
+ toBeUUID(version?: 'v1' | 'v4' | 'v5'): any;
815
+
816
+ /**
817
+ * Matches any string that is a valid ISO 8601 date.
818
+ * @example
819
+ * expect(value).toEqual(expect.toBeISODate());
820
+ */
821
+ toBeISODate(): any;
822
+
823
+ /**
824
+ * Matches any string that follows the specified date format.
825
+ * @example
826
+ * expect(value).toEqual(expect.toBeDateString('YYYY-MM-DD'));
827
+ */
828
+ toBeDateString(format: string): any;
829
+
830
+ /**
831
+ * Matches any string that is a valid email address.
832
+ * @example
833
+ * expect(value).toEqual(expect.toBeEmail());
834
+ */
835
+ toBeEmail(): any;
836
+
837
+ /**
838
+ * Matches any string that is a valid URL.
839
+ * @example
840
+ * expect(value).toEqual(expect.toBeURL());
841
+ */
842
+ toBeURL(options?: any): any;
843
+
844
+ /**
845
+ * Matches any string that is valid JSON.
846
+ * @example
847
+ * expect(value).toEqual(expect.toBeJSON());
848
+ */
849
+ toBeJSON(): any;
850
+
851
+ /**
852
+ * Matches any string starting with the expected prefix.
853
+ * @example
854
+ * expect(value).toEqual(expect.toStartWith('Pre'));
855
+ */
856
+ toStartWith(expected: string): any;
857
+
858
+ /**
859
+ * Matches any string ending with the expected suffix.
860
+ * @example
861
+ * expect(value).toEqual(expect.toEndWith('fix'));
862
+ */
863
+ toEndWith(expected: string): any;
864
+
865
+ /**
866
+ * Matches any string that is uppercase.
867
+ * @example
868
+ * expect(value).toEqual(expect.toBeUpperCase());
869
+ */
870
+ toBeUpperCase(): any;
871
+
872
+ /**
873
+ * Matches any string that is lowercase.
874
+ * @example
875
+ * expect(value).toEqual(expect.toBeLowerCase());
876
+ */
877
+ toBeLowerCase(): any;
878
+
879
+ /**
880
+ * Matches any string that is kebab-case.
881
+ * @example
882
+ * expect(value).toEqual(expect.toBeKebabCase());
883
+ */
884
+ toBeKebabCase(): any;
885
+
886
+ /**
887
+ * Matches any string that is camelCase.
888
+ * @example
889
+ * expect(value).toEqual(expect.toBeCamelCase());
890
+ */
891
+ toBeCamelCase(): any;
892
+
893
+ /**
894
+ * Matches any string that is snake_case.
895
+ * @example
896
+ * expect(value).toEqual(expect.toBeSnakeCase());
897
+ */
898
+ toBeSnakeCase(): any;
899
+
900
+ /**
901
+ * Matches any string that is PascalCase.
902
+ * @example
903
+ * expect(value).toEqual(expect.toBePascalCase());
904
+ */
905
+ toBePascalCase(): any;
906
+ }
544
907
  }
545
908
 
546
-
547
- interface Expect extends ExPwAsymmetricMatchers { }
909
+ // Workaround for Playwright's Expect type limitation:
910
+ // Since Expect is a type alias intersection that cannot be augmented directly,
911
+ // and it is compatible with Function, we add the asymmetric matchers to the
912
+ // global Function interface to make them available on the expect object.
913
+ interface Function extends PlaywrightTest.AsymmetricMatchers { }
548
914
  }
549
915
 
550
916
  declare function toHaveWidth(this: ExpectMatcherState, locator: Locator, expected: number, options?: TimeoutOptions): Promise<{
package/dist/index.d.ts CHANGED
@@ -483,68 +483,434 @@ interface ExPwAsymmetricMatchers {
483
483
  }
484
484
 
485
485
 
486
- // Augment Playwright's types
487
- declare module '@playwright/test' {
488
- interface Matchers<R, T = unknown> {
489
- // Locator matchers (when T is Locator)
490
- toBeClickable(options?: TimeoutOptions): Promise<R>;
491
- toBeCheckable(options?: TimeoutOptions): Promise<R>;
492
- toBeRequired(options?: TimeoutOptions): Promise<R>;
493
- toBeInvalid(options?: TimeoutOptions): Promise<R>;
494
- toBeValid(options?: TimeoutOptions): Promise<R>;
495
- toHaveCountGreaterThan(count: number, options?: TimeoutOptions): Promise<R>;
496
- toHaveCountGreaterThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
497
- toHaveCountLessThan(count: number, options?: TimeoutOptions): Promise<R>;
498
- toHaveCountLessThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
499
- toHaveWidth(expected: number, options?: TimeoutOptions): Promise<R>;
500
- toHaveHeight(expected: number, options?: TimeoutOptions): Promise<R>;
501
- toHaveSize(width: number, height: number, options?: TimeoutOptions): Promise<R>;
502
- toHaveLoadedImage(options?: TimeoutOptions): Promise<R>;
503
-
504
-
505
- // Page matchers (when T is Page)
506
- toHaveCookie(name: string, options?: ToHaveCookieOptions$1): Promise<R>;
507
- toHaveLocalStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
508
- toHaveSessionStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
509
- toHaveClipboardText(expected: string | RegExp, options?: TimeoutOptions): Promise<R>;
510
- toHaveRequest(options?: ToHaveRequestOptions$1): Promise<R>;
511
- toHaveConsoleMessage(options?: ToHaveConsoleMessageOptions$1): Promise<R>;
512
- toHavePageError(options?: ToHavePageErrorOptions$1): Promise<R>;
513
-
514
-
515
- // TestInfo matchers (when T is TestInfo)
516
- toHaveNoErrors(options?: ToHaveNoErrorsOptions$1): R;
517
-
518
- // API matchers (when T is APIResponse)
519
- toMatchJSON(expected: unknown): Promise<R>;
520
- toMatchSchema(schema: ZodSchema): Promise<R>;
521
- toHaveStatus(expected: number | { min: number; max: number }): Promise<R>;
522
- toHaveHeader(name: string, options?: { value?: string | RegExp }): Promise<R>;
523
- toRespondWithin(timeout: number): Promise<R>;
524
-
525
- // General matchers (when T is Array or Locator)
526
- toBeSorted(options?: ToBeSortedOptions$1): Promise<R>;
527
-
528
- // Asymmetric matchers available as symmetric matchers
529
- toBeWithinRange(min: number, max: number): R;
530
- toBeUUID(version?: 'v1' | 'v4' | 'v5'): R;
531
- toBeISODate(): R;
532
- toBeDateString(format: string): R;
533
- toBeEmail(): R;
534
- toBeURL(options?: ToBeURLAsymmetricOptions): R;
535
- toBeJSON(): R;
536
- toStartWith(expected: string): R;
537
- toEndWith(expected: string): R;
538
- toBeUpperCase(): R;
539
- toBeLowerCase(): R;
540
- toBeKebabCase(): R;
541
- toBeCamelCase(): R;
542
- toBeSnakeCase(): R;
543
- toBePascalCase(): R;
486
+ // Augment Playwright's types using global namespace
487
+ declare global {
488
+ namespace PlaywrightTest {
489
+ interface Matchers<R, T = unknown> {
490
+ // Locator matchers (when T is Locator)
491
+
492
+ /**
493
+ * Asserts that an element is visible, enabled, stable, and not obscured.
494
+ * @example
495
+ * await expect(page.getByRole('button')).toBeClickable();
496
+ */
497
+ toBeClickable(options?: TimeoutOptions): Promise<R>;
498
+
499
+ /**
500
+ * Asserts that a checkbox or radio button is in a checkable state.
501
+ * @example
502
+ * await expect(page.getByRole('checkbox')).toBeCheckable();
503
+ */
504
+ toBeCheckable(options?: TimeoutOptions): Promise<R>;
505
+
506
+ /**
507
+ * Asserts that a form element is required.
508
+ * @example
509
+ * await expect(page.getByLabel('Email')).toBeRequired();
510
+ */
511
+ toBeRequired(options?: TimeoutOptions): Promise<R>;
512
+
513
+ /**
514
+ * Asserts that a form element is in an invalid validation state.
515
+ * @example
516
+ * await expect(page.getByRole('textbox')).toBeInvalid();
517
+ */
518
+ toBeInvalid(options?: TimeoutOptions): Promise<R>;
519
+
520
+ /**
521
+ * Asserts that a form element is in a valid validation state.
522
+ * @example
523
+ * await expect(page.getByRole('textbox')).toBeValid();
524
+ */
525
+ toBeValid(options?: TimeoutOptions): Promise<R>;
526
+
527
+ /**
528
+ * Asserts that a locator resolves to more than the specified number of elements.
529
+ * @example
530
+ * await expect(page.locator('li')).toHaveCountGreaterThan(3);
531
+ */
532
+ toHaveCountGreaterThan(count: number, options?: TimeoutOptions): Promise<R>;
533
+
534
+ /**
535
+ * Asserts that a locator resolves to at least the specified number of elements.
536
+ * @example
537
+ * await expect(page.locator('li')).toHaveCountGreaterThanOrEqual(1);
538
+ */
539
+ toHaveCountGreaterThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
540
+
541
+ /**
542
+ * Asserts that a locator resolves to fewer than the specified number of elements.
543
+ * @example
544
+ * await expect(page.locator('.loading')).toHaveCountLessThan(1);
545
+ */
546
+ toHaveCountLessThan(count: number, options?: TimeoutOptions): Promise<R>;
547
+
548
+ /**
549
+ * Asserts that a locator resolves to at most the specified number of elements.
550
+ * @example
551
+ * await expect(page.locator('.result')).toHaveCountLessThanOrEqual(5);
552
+ */
553
+ toHaveCountLessThanOrEqual(count: number, options?: TimeoutOptions): Promise<R>;
554
+
555
+ /**
556
+ * Asserts that an element has a specific width in pixels.
557
+ * @example
558
+ * await expect(page.locator('#box')).toHaveWidth(100);
559
+ */
560
+ toHaveWidth(expected: number, options?: TimeoutOptions): Promise<R>;
561
+
562
+ /**
563
+ * Asserts that an element has a specific height in pixels.
564
+ * @example
565
+ * await expect(page.locator('#box')).toHaveHeight(200);
566
+ */
567
+ toHaveHeight(expected: number, options?: TimeoutOptions): Promise<R>;
568
+
569
+ /**
570
+ * Asserts that an element has a specific width and height in pixels.
571
+ * @example
572
+ * await expect(page.locator('#box')).toHaveSize(100, 200);
573
+ */
574
+ toHaveSize(width: number, height: number, options?: TimeoutOptions): Promise<R>;
575
+
576
+ /**
577
+ * Asserts that an image element has fully loaded.
578
+ * @example
579
+ * await expect(page.locator('img.logo')).toHaveLoadedImage();
580
+ */
581
+ toHaveLoadedImage(options?: TimeoutOptions): Promise<R>;
582
+
583
+ // Page matchers (when T is Page)
584
+
585
+ /**
586
+ * Asserts that the page has a cookie with the specified name.
587
+ * @example
588
+ * await expect(page).toHaveCookie('session_id');
589
+ * await expect(page).toHaveCookie('csrf', { value: /.+/ });
590
+ */
591
+ toHaveCookie(name: string, options?: ToHaveCookieOptions$1): Promise<R>;
592
+
593
+ /**
594
+ * Asserts that localStorage has a specific key.
595
+ * @example
596
+ * await expect(page).toHaveLocalStorage('token');
597
+ */
598
+ toHaveLocalStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
599
+
600
+ /**
601
+ * Asserts that sessionStorage has a specific key.
602
+ * @example
603
+ * await expect(page).toHaveSessionStorage('cart_id');
604
+ */
605
+ toHaveSessionStorage(key: string, options?: ToHaveStorageOptions): Promise<R>;
606
+
607
+ /**
608
+ * Asserts that the clipboard contains the specified text.
609
+ * @example
610
+ * await expect(page).toHaveClipboardText('copied text');
611
+ */
612
+ toHaveClipboardText(expected: string | RegExp, options?: TimeoutOptions): Promise<R>;
613
+
614
+ /**
615
+ * Asserts that a network request matching the criteria was made.
616
+ * @example
617
+ * await expect(page).toHaveRequest({ url: '/api/login', method: 'POST' });
618
+ */
619
+ toHaveRequest(options?: ToHaveRequestOptions$1): Promise<R>;
620
+
621
+ /**
622
+ * Asserts that a console message matching the criteria was logged.
623
+ * @example
624
+ * await expect(page).toHaveConsoleMessage({ type: 'error', text: /failed/ });
625
+ */
626
+ toHaveConsoleMessage(options?: ToHaveConsoleMessageOptions$1): Promise<R>;
627
+
628
+ /**
629
+ * Asserts that the page threw an uncaught exception.
630
+ * @example
631
+ * await expect(page).toHavePageError({ message: /ReferenceError/ });
632
+ */
633
+ toHavePageError(options?: ToHavePageErrorOptions$1): Promise<R>;
634
+
635
+ // TestInfo matchers (when T is TestInfo)
636
+
637
+ /**
638
+ * Asserts that there are no errors in the current test execution. Common with soft assertions.
639
+ * @example
640
+ * await expect(test).toHaveNoErrors();
641
+ */
642
+ toHaveNoErrors(options?: ToHaveNoErrorsOptions$1): R;
643
+
644
+ // API matchers (when T is APIResponse)
645
+
646
+ /**
647
+ * Asserts that the API response body matches the expected JSON.
648
+ * @example
649
+ * await expect(response).toMatchJSON({ success: true });
650
+ */
651
+ toMatchJSON(expected: unknown): Promise<R>;
652
+
653
+ /**
654
+ * Asserts that the API response body matches a Zod schema.
655
+ * @example
656
+ * await expect(response).toMatchSchema(UserSchema);
657
+ */
658
+ toMatchSchema(schema: ZodSchema): Promise<R>;
659
+
660
+ /**
661
+ * Asserts that the API response has the specified status code or is within range.
662
+ * @example
663
+ * await expect(response).toHaveStatus(200);
664
+ * await expect(response).toHaveStatus({ min: 200, max: 299 });
665
+ */
666
+ toHaveStatus(expected: number | { min: number; max: number }): Promise<R>;
667
+
668
+ /**
669
+ * Asserts that the API response contains a specific header.
670
+ * @example
671
+ * await expect(response).toHaveHeader('content-type', { value: /json/ });
672
+ */
673
+ toHaveHeader(name: string, options?: { value?: string | RegExp }): Promise<R>;
674
+
675
+ /**
676
+ * Asserts that the API response was received within the specified timeout.
677
+ * @example
678
+ * await expect(requestPromise).toRespondWithin(1000);
679
+ */
680
+ toRespondWithin(timeout: number): Promise<R>;
681
+
682
+ // General matchers (when T is Array or Locator)
683
+
684
+ /**
685
+ * Asserts that an array or items in a locator are sorted.
686
+ * @example
687
+ * await expect([1, 2, 3]).toBeSorted();
688
+ * await expect(page.locator('li')).toBeSorted({ descending: true });
689
+ */
690
+ toBeSorted(options?: ToBeSortedOptions$1): Promise<R>;
691
+
692
+ // Asymmetric matchers available as symmetric matchers
693
+
694
+ /**
695
+ * Asserts that the value is within the specified range (inclusive).
696
+ * @example
697
+ * await expect(5).toBeWithinRange(1, 10);
698
+ */
699
+ toBeWithinRange(min: number, max: number): R;
700
+
701
+ /**
702
+ * Asserts that the value is a valid UUID.
703
+ * @example
704
+ * await expect(uuid).toBeUUID();
705
+ */
706
+ toBeUUID(version?: 'v1' | 'v4' | 'v5'): R;
707
+
708
+ /**
709
+ * Asserts that the value is a valid ISO 8601 date string.
710
+ * @example
711
+ * await expect('2023-01-01T00:00:00Z').toBeISODate();
712
+ */
713
+ toBeISODate(): R;
714
+
715
+ /**
716
+ * Asserts that the value matches the specified date format.
717
+ * @example
718
+ * await expect('01/01/2023').toBeDateString('MM/DD/YYYY');
719
+ */
720
+ toBeDateString(format: string): R;
721
+
722
+ /**
723
+ * Asserts that the value is a valid email address.
724
+ * @example
725
+ * await expect('user@example.com').toBeEmail();
726
+ */
727
+ toBeEmail(): R;
728
+
729
+ /**
730
+ * Asserts that the value is a valid URL.
731
+ * @example
732
+ * await expect('https://example.com').toBeURL();
733
+ */
734
+ toBeURL(options?: ToBeURLAsymmetricOptions): R;
735
+
736
+ /**
737
+ * Asserts that the string value is valid JSON.
738
+ * @example
739
+ * await expect('{"a":1}').toBeJSON();
740
+ */
741
+ toBeJSON(): R;
742
+
743
+ /**
744
+ * Asserts that the string starts with the expected prefix.
745
+ * @example
746
+ * await expect('Hello World').toStartWith('Hello');
747
+ */
748
+ toStartWith(expected: string): R;
749
+
750
+ /**
751
+ * Asserts that the string ends with the expected suffix.
752
+ * @example
753
+ * await expect('image.png').toEndWith('.png');
754
+ */
755
+ toEndWith(expected: string): R;
756
+
757
+ /**
758
+ * Asserts that the string is uppercase.
759
+ * @example
760
+ * await expect('HELLO').toBeUpperCase();
761
+ */
762
+ toBeUpperCase(): R;
763
+
764
+ /**
765
+ * Asserts that the string is lowercase.
766
+ * @example
767
+ * await expect('hello').toBeLowerCase();
768
+ */
769
+ toBeLowerCase(): R;
770
+
771
+ /**
772
+ * Asserts that the string is kebab-case.
773
+ * @example
774
+ * await expect('my-class-name').toBeKebabCase();
775
+ */
776
+ toBeKebabCase(): R;
777
+
778
+ /**
779
+ * Asserts that the string is camelCase.
780
+ * @example
781
+ * await expect('myVariable').toBeCamelCase();
782
+ */
783
+ toBeCamelCase(): R;
784
+
785
+ /**
786
+ * Asserts that the string is snake_case.
787
+ * @example
788
+ * await expect('my_variable').toBeSnakeCase();
789
+ */
790
+ toBeSnakeCase(): R;
791
+
792
+ /**
793
+ * Asserts that the string is PascalCase.
794
+ * @example
795
+ * await expect('MyClass').toBePascalCase();
796
+ */
797
+ toBePascalCase(): R;
798
+ }
799
+
800
+ // Asymmetric matchers available on the expect object (e.g., expect.toBeLowerCase())
801
+ interface AsymmetricMatchers {
802
+ /**
803
+ * Matches any number within the specified range.
804
+ * @example
805
+ * expect(value).toEqual(expect.toBeWithinRange(1, 10));
806
+ */
807
+ toBeWithinRange(min: number, max: number): any;
808
+
809
+ /**
810
+ * Matches any string that is a valid UUID.
811
+ * @example
812
+ * expect(value).toEqual(expect.toBeUUID());
813
+ */
814
+ toBeUUID(version?: 'v1' | 'v4' | 'v5'): any;
815
+
816
+ /**
817
+ * Matches any string that is a valid ISO 8601 date.
818
+ * @example
819
+ * expect(value).toEqual(expect.toBeISODate());
820
+ */
821
+ toBeISODate(): any;
822
+
823
+ /**
824
+ * Matches any string that follows the specified date format.
825
+ * @example
826
+ * expect(value).toEqual(expect.toBeDateString('YYYY-MM-DD'));
827
+ */
828
+ toBeDateString(format: string): any;
829
+
830
+ /**
831
+ * Matches any string that is a valid email address.
832
+ * @example
833
+ * expect(value).toEqual(expect.toBeEmail());
834
+ */
835
+ toBeEmail(): any;
836
+
837
+ /**
838
+ * Matches any string that is a valid URL.
839
+ * @example
840
+ * expect(value).toEqual(expect.toBeURL());
841
+ */
842
+ toBeURL(options?: any): any;
843
+
844
+ /**
845
+ * Matches any string that is valid JSON.
846
+ * @example
847
+ * expect(value).toEqual(expect.toBeJSON());
848
+ */
849
+ toBeJSON(): any;
850
+
851
+ /**
852
+ * Matches any string starting with the expected prefix.
853
+ * @example
854
+ * expect(value).toEqual(expect.toStartWith('Pre'));
855
+ */
856
+ toStartWith(expected: string): any;
857
+
858
+ /**
859
+ * Matches any string ending with the expected suffix.
860
+ * @example
861
+ * expect(value).toEqual(expect.toEndWith('fix'));
862
+ */
863
+ toEndWith(expected: string): any;
864
+
865
+ /**
866
+ * Matches any string that is uppercase.
867
+ * @example
868
+ * expect(value).toEqual(expect.toBeUpperCase());
869
+ */
870
+ toBeUpperCase(): any;
871
+
872
+ /**
873
+ * Matches any string that is lowercase.
874
+ * @example
875
+ * expect(value).toEqual(expect.toBeLowerCase());
876
+ */
877
+ toBeLowerCase(): any;
878
+
879
+ /**
880
+ * Matches any string that is kebab-case.
881
+ * @example
882
+ * expect(value).toEqual(expect.toBeKebabCase());
883
+ */
884
+ toBeKebabCase(): any;
885
+
886
+ /**
887
+ * Matches any string that is camelCase.
888
+ * @example
889
+ * expect(value).toEqual(expect.toBeCamelCase());
890
+ */
891
+ toBeCamelCase(): any;
892
+
893
+ /**
894
+ * Matches any string that is snake_case.
895
+ * @example
896
+ * expect(value).toEqual(expect.toBeSnakeCase());
897
+ */
898
+ toBeSnakeCase(): any;
899
+
900
+ /**
901
+ * Matches any string that is PascalCase.
902
+ * @example
903
+ * expect(value).toEqual(expect.toBePascalCase());
904
+ */
905
+ toBePascalCase(): any;
906
+ }
544
907
  }
545
908
 
546
-
547
- interface Expect extends ExPwAsymmetricMatchers { }
909
+ // Workaround for Playwright's Expect type limitation:
910
+ // Since Expect is a type alias intersection that cannot be augmented directly,
911
+ // and it is compatible with Function, we add the asymmetric matchers to the
912
+ // global Function interface to make them available on the expect object.
913
+ interface Function extends PlaywrightTest.AsymmetricMatchers { }
548
914
  }
549
915
 
550
916
  declare function toHaveWidth(this: ExpectMatcherState, locator: Locator, expected: number, options?: TimeoutOptions): Promise<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ex-pw",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Extended Playwright expect matchers with auto-waiting and improved developer experience",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,8 +20,8 @@
20
20
  "build": "tsup src/index.ts --format cjs,esm --dts --clean",
21
21
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
22
  "test": "playwright test",
23
- "lint": "eslint src --ext .ts",
24
23
  "prepublishOnly": "npm run build",
24
+ "tsc": "npx tsc --noEmit",
25
25
  "release:patch": "npm version patch -m 'chore: release %s'",
26
26
  "release:minor": "npm version minor -m 'chore: release %s'",
27
27
  "release:major": "npm version major -m 'chore: release %s'",