@entifix/testing-e2e 0.1.0-0

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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/fixtures/entity-backend.d.ts +54 -0
  4. package/dist/fixtures/entity-backend.d.ts.map +1 -0
  5. package/dist/fixtures/entity-backend.js +130 -0
  6. package/dist/fixtures/entity-backend.js.map +1 -0
  7. package/dist/fixtures/entity-handlers.d.ts +32 -0
  8. package/dist/fixtures/entity-handlers.d.ts.map +1 -0
  9. package/dist/fixtures/entity-handlers.js +39 -0
  10. package/dist/fixtures/entity-handlers.js.map +1 -0
  11. package/dist/fixtures/fake-infrastructure.d.ts +61 -0
  12. package/dist/fixtures/fake-infrastructure.d.ts.map +1 -0
  13. package/dist/fixtures/fake-infrastructure.js +77 -0
  14. package/dist/fixtures/fake-infrastructure.js.map +1 -0
  15. package/dist/fixtures/index.d.ts +5 -0
  16. package/dist/fixtures/index.d.ts.map +1 -0
  17. package/dist/fixtures/index.js +6 -0
  18. package/dist/fixtures/index.js.map +1 -0
  19. package/dist/fixtures/signing-key.d.ts +27 -0
  20. package/dist/fixtures/signing-key.d.ts.map +1 -0
  21. package/dist/fixtures/signing-key.js +91 -0
  22. package/dist/fixtures/signing-key.js.map +1 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +3 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/playwright/assert-expected-server.d.ts +43 -0
  28. package/dist/playwright/assert-expected-server.d.ts.map +1 -0
  29. package/dist/playwright/assert-expected-server.js +98 -0
  30. package/dist/playwright/assert-expected-server.js.map +1 -0
  31. package/dist/playwright/config.d.ts +78 -0
  32. package/dist/playwright/config.d.ts.map +1 -0
  33. package/dist/playwright/config.js +96 -0
  34. package/dist/playwright/config.js.map +1 -0
  35. package/dist/playwright/entity-table.d.ts +69 -0
  36. package/dist/playwright/entity-table.d.ts.map +1 -0
  37. package/dist/playwright/entity-table.js +129 -0
  38. package/dist/playwright/entity-table.js.map +1 -0
  39. package/dist/playwright/index.d.ts +6 -0
  40. package/dist/playwright/index.d.ts.map +1 -0
  41. package/dist/playwright/index.js +7 -0
  42. package/dist/playwright/index.js.map +1 -0
  43. package/dist/playwright/session.d.ts +85 -0
  44. package/dist/playwright/session.d.ts.map +1 -0
  45. package/dist/playwright/session.js +250 -0
  46. package/dist/playwright/session.js.map +1 -0
  47. package/dist/playwright/test.d.ts +51 -0
  48. package/dist/playwright/test.d.ts.map +1 -0
  49. package/dist/playwright/test.js +79 -0
  50. package/dist/playwright/test.js.map +1 -0
  51. package/dist/profile/profile.d.ts +43 -0
  52. package/dist/profile/profile.d.ts.map +1 -0
  53. package/dist/profile/profile.js +51 -0
  54. package/dist/profile/profile.js.map +1 -0
  55. package/dist/service/define-service-e2e.d.ts +54 -0
  56. package/dist/service/define-service-e2e.d.ts.map +1 -0
  57. package/dist/service/define-service-e2e.js +57 -0
  58. package/dist/service/define-service-e2e.js.map +1 -0
  59. package/dist/service/index.d.ts +2 -0
  60. package/dist/service/index.d.ts.map +1 -0
  61. package/dist/service/index.js +3 -0
  62. package/dist/service/index.js.map +1 -0
  63. package/package.json +131 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './entity-backend.js';
2
+ export * from './entity-handlers.js';
3
+ export * from './fake-infrastructure.js';
4
+ export * from './signing-key.js';
5
+
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/fixtures/index.ts"],"sourcesContent":["export * from './entity-backend.js';\nexport * from './entity-handlers.js';\nexport * from './fake-infrastructure.js';\nexport * from './signing-key.js';\n"],"names":[],"mappings":"AAAA,cAAc,sBAAsB;AACpC,cAAc,uBAAuB;AACrC,cAAc,2BAA2B;AACzC,cAAc,mBAAmB"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A throwaway RSA pair the e2e suites sign and verify test tokens with.
3
+ *
4
+ * It lives here, in one place, because two sides need *the same* pair: the
5
+ * `mock` composition root is configured to verify with the public half, and the
6
+ * spec helpers sign with the private half. Generating one per file would make
7
+ * every token the other side cannot verify.
8
+ *
9
+ * Deliberately **not** the development pair config-service seeds. A suite that
10
+ * happened to verify a real dev token would be passing for the wrong reason,
11
+ * and a fixture that doubles as a live credential is one copy-paste away from
12
+ * becoming one.
13
+ */
14
+ export declare const E2E_KEY_ID = "e2e-key";
15
+ export declare const E2E_PRIVATE_KEY_PEM = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCOQ+cUUN5cVpHo\nwv8SRQYNzGLS6jrEXxzCRggsKvwZS6aa13lJpneB4M5m1K+SXK5aedOeSOl/FyQM\ncLzK/xSMF/CIscZWt5mRFQO75bKyNysUWk2WFUT0e4IZkaAypJdN1pK75XF6OaCI\nvjrP8OuBfDQ61STTzlekLyMA+ZNzwUBR29LhB1Zuh1COocLyyXYry8Tg97njZHSp\nWnmtfKg3WVgHpHLcYiQDUnD0nmjhuJXor/1samgb87k+yxXMuJWTu++sxESQMmpV\ni1iJ4zPQn7IzS799pEn/zFJgRGyIowka3f2DOY8u7O/5JDn5XCI/Qcq4rq9ky1Qa\nH901dkXPAgMBAAECggEAA26GHOp0srLbAxLRGMgrPakUfoZsXkL1+qKd1hLqe6jW\nLVbpuvgyWrEFkLEBmzXJIK9ev3JFelEgle4ECoNPXOjf0IGniWDcaiIvMcNb0Cbz\npGmZPYYE7um4PM2otWVcyeGqvOkkbPQieBu+oFSX4NkSJ7BEjHzCox9BvcryF59d\nc9oFzS97YryD8g94qH6SqgF90qxnxD5oSqz3yRuON6o6SiBwSdsT5yCTiiBIsBSb\nyZP7KN/4LPZnFaPcHJ6UtlMOPae47Z7UBdiuP8/isSyIbnU7j1+TrpXUBqqG6JFI\nEJx3rRW4yYy/syt8BkkLnKa9idbZfCgii+C/X6FNgQKBgQDAd00/+ZIp5HwRkJ7M\ne4SSPxEW9kdCdNwCG9D6GvWZO9d/eeidnM+eoTRPx9NdvfiP5ztsZEtDDfXzMQFp\nJd7Loq5Nc3ZQBchPOIoFGIruUVWlUVawgneRKggfRzDEJLlKBjbVNsPPJFEPkMyO\nXShRKR0cnY4pNen6ug6YRQn7kQKBgQC9OkqCeqVftgi5gE0VkBRf1i1bRIIClw9z\nK08XYej54JcMdYqlTdpsRK0QQYye+wVH3V0Oe2p40leDeVbQMx4W4C1/Rl+Hk05r\nQF9yvgIBPccE/D63ufcKdagj1QLHDXIHUhoMVqtaZIodBSenAV0uOtPKS+6vlVH6\nOlM+Zo+7XwKBgQCOAbiCwn7g4A/W2fEBCQXY7iWK3q3XT+fgumtnjiq2JBwtl2JV\noJTkAydY0iSXHwreCouivyF02UEmbXsP/Pw1HdQjm1SpWIriQOI9Pk2L54Ec2DXx\nSGI2Pl/9zAYkQsBf6NPeX2j8Vlxk8r6rL/sGXyJ2sZ1ptLjt4QfRu+bQsQKBgQCy\niHHOQ3sOH4iBxIx2ALdIaKHoj21+lhnMlpsLu6P9RiodZjUGm7quFemXAdF0GfA0\niqWGyWh+UC6ja/M9gk0sVhx3DeWJ27DMPjMP5jesBiZlDLz7yWhMpQ+bpxj0xznD\nsHHFHGyVX3Bzyu5LglzxBi3Wmue7H831odvybv/DTwKBgETuVvv5b2EhMbKahtnf\ndNrT9ZivoiRD4OaZBXffTG0I2HMu20a7nthKbv2o4pxztDcpW8s6UMU87N8YAK4W\nGX3DjBMHIELxRE96tjifpW9MGQijLCI+jteq4lX0Pxf6HiUB+T1jZ1KDQQfvWJpH\ncAvNvxF+Tev5A4GaIKwmahLI\n-----END PRIVATE KEY-----\n";
16
+ export declare const E2E_PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjkPnFFDeXFaR6ML/EkUG\nDcxi0uo6xF8cwkYILCr8GUummtd5SaZ3geDOZtSvklyuWnnTnkjpfxckDHC8yv8U\njBfwiLHGVreZkRUDu+WysjcrFFpNlhVE9HuCGZGgMqSXTdaSu+VxejmgiL46z/Dr\ngXw0OtUk085XpC8jAPmTc8FAUdvS4QdWbodQjqHC8sl2K8vE4Pe542R0qVp5rXyo\nN1lYB6Ry3GIkA1Jw9J5o4biV6K/9bGpoG/O5PssVzLiVk7vvrMREkDJqVYtYieMz\n0J+yM0u/faRJ/8xSYERsiKMJGt39gzmPLuzv+SQ5+VwiP0HKuK6vZMtUGh/dNXZF\nzwIDAQAB\n-----END PUBLIC KEY-----\n";
17
+ /**
18
+ * A key nothing in the fleet trusts, for the suites that assert a forged token
19
+ * is refused.
20
+ *
21
+ * A separate pair rather than a mangled signature, because they fail for
22
+ * different reasons: a corrupt signature could plausibly be caught by a
23
+ * structural check, while a *validly signed token from the wrong issuer's key*
24
+ * is the actual attack, and only a real verification catches it.
25
+ */
26
+ export declare const E2E_FOREIGN_PRIVATE_KEY_PEM = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgkVvRRzabj1gS\nZylt4+H7vMIL/nlCC/WoCLegBia3b9RaOkfCdXi+N99oFkcwwjywRsXmotNyPhEi\nrqFEvvxUCZQmk9Cdo2+DYzFZq/6k2/5+e3Tr3NDlvYHVaqp6CRC+DqMIorQ6TT3D\nSV/pu/Gz1U1MgE9TeB/Zw5yUjenknyjWzxeRwJjKvn10Jg2/YJzcvcsKeiED6+LU\nFVkiJsvnxUvuJWnjGmtXocb85PbN4oD54eERLGL/cxZB4p8K6P/KTQrQV207qL+m\nRqYjTj2Wu/ct4FSdGPKm5mhMP87sqioXU14t2R/nltIgiom0FajqyrR15krLkXSy\n0PrGIqbHAgMBAAECggEAT1aTrkxIRMQm6ez0cRqFOoyRuzhxtPtQ1kb8aIMxlTka\nDb03YPQHhcH4zycW5RZMw3Ms7SGuZggaEm+EOwI9js6u2AL4tTOg8aRNKbhNGiuj\ny953ruWMiMBDS28priQVlDuKPkWa1SX+aySx0j2uF8RBLhhGWgGEh2ba0yJuHCrq\nN+l7wU26loDjlwS7dTQYc8z2WvGnKBbJVUJzJaLeUyMftVCd86sgjiYX9nnVuqxo\nT9kE7/GhLOeP1vSjYj3Tk6CrQQlEanIUrSrogMt0LXVtek5sDyFPqTKnhd+bjNtl\nsTfibYU7Yq4xlV/Bu3ntJYXh0hiL4VS1bOWc1rh6oQKBgQDLtiMbPuREXwJwgYKP\nSB72RhGiT1fvklWyq43CGMsVgE43ncJAtrGb6A0fBVspYnS7YKIaUAVTyboNrycD\nJzgFaVF/m75GeQDKOoRoPRfke/ytA3NIEeAy2Vo+1ZD60SLVdvFgusuJbwrg0Vn7\noxbigMi39Bif5ADz/+nupDgoJwKBgQDJyEFLq0CSiltScR7GzkCM9rSNs2ntSNOL\nGVM7iZ32AP+UukFa02CC/s+6p660JUtFuZ6ax8npb+TAwWc2BydcRuqMQVmDMZ0j\nl1A/PNZS9myvgy+RpwCtWPJc0k2AIrMIJM6pcj/ZByxV1tJcKj19CyM03phlg9Py\nTtmkSX8QYQKBgQCnyDoeBKzJy18c/u5jyMkHmiqH/sW0olhHMpktVnJeITFLCXqn\nBlI+0N+Nv0GYUmlGs46QEXxxyGKfRrXhGPpBKr9fVQ1gyeTmq0/G8xqsq5ovffoD\nUAXSm8aCnjAtBPelzbN9MhzV80mIZaWxZmBA6kVnjXqCpq5KSWuJjGRcXQKBgBLe\n4IRkGqDZwZqfK6KqDU1hkRcjbUecpPQARVFvGE+2XjCZjp0g4Yi+rcyl++erCTQX\nHOcawh5LsZf5Pl7GIn81vp+pSObFEA4RC5cuaFjP5PAxE5TKinyrsdbOcCMIm7eq\nQY2FOsVgL1xDv96QsLlt/jfmjVgJERw7FY2QtgphAoGAcbrPfjRrDMqthf3LJsFu\nZH3hkadfbsCLld6UvAva0Vkugv5kOx0wB6+Bbk3rEGUPUxpaq1+iFhr7gUlghAA3\nlRKwXGJZJc5PIUuHoxCYg/W4rKbYlrlYAwYQaNIucTT/bUgXw6Ra5rxEqnpgKiqJ\nMUzrkxXjBuapqxOF4QzIySg=\n-----END PRIVATE KEY-----\n";
27
+ //# sourceMappingURL=signing-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing-key.d.ts","sourceRoot":"","sources":["../../src/fixtures/signing-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,YAAY,CAAC;AAEpC,eAAO,MAAM,mBAAmB,ysDA4B/B,CAAC;AAEF,eAAO,MAAM,kBAAkB,idAS9B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,ysDA4BvC,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * A throwaway RSA pair the e2e suites sign and verify test tokens with.
3
+ *
4
+ * It lives here, in one place, because two sides need *the same* pair: the
5
+ * `mock` composition root is configured to verify with the public half, and the
6
+ * spec helpers sign with the private half. Generating one per file would make
7
+ * every token the other side cannot verify.
8
+ *
9
+ * Deliberately **not** the development pair config-service seeds. A suite that
10
+ * happened to verify a real dev token would be passing for the wrong reason,
11
+ * and a fixture that doubles as a live credential is one copy-paste away from
12
+ * becoming one.
13
+ */ export const E2E_KEY_ID = 'e2e-key';
14
+ export const E2E_PRIVATE_KEY_PEM = `-----BEGIN PRIVATE KEY-----
15
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCOQ+cUUN5cVpHo
16
+ wv8SRQYNzGLS6jrEXxzCRggsKvwZS6aa13lJpneB4M5m1K+SXK5aedOeSOl/FyQM
17
+ cLzK/xSMF/CIscZWt5mRFQO75bKyNysUWk2WFUT0e4IZkaAypJdN1pK75XF6OaCI
18
+ vjrP8OuBfDQ61STTzlekLyMA+ZNzwUBR29LhB1Zuh1COocLyyXYry8Tg97njZHSp
19
+ WnmtfKg3WVgHpHLcYiQDUnD0nmjhuJXor/1samgb87k+yxXMuJWTu++sxESQMmpV
20
+ i1iJ4zPQn7IzS799pEn/zFJgRGyIowka3f2DOY8u7O/5JDn5XCI/Qcq4rq9ky1Qa
21
+ H901dkXPAgMBAAECggEAA26GHOp0srLbAxLRGMgrPakUfoZsXkL1+qKd1hLqe6jW
22
+ LVbpuvgyWrEFkLEBmzXJIK9ev3JFelEgle4ECoNPXOjf0IGniWDcaiIvMcNb0Cbz
23
+ pGmZPYYE7um4PM2otWVcyeGqvOkkbPQieBu+oFSX4NkSJ7BEjHzCox9BvcryF59d
24
+ c9oFzS97YryD8g94qH6SqgF90qxnxD5oSqz3yRuON6o6SiBwSdsT5yCTiiBIsBSb
25
+ yZP7KN/4LPZnFaPcHJ6UtlMOPae47Z7UBdiuP8/isSyIbnU7j1+TrpXUBqqG6JFI
26
+ EJx3rRW4yYy/syt8BkkLnKa9idbZfCgii+C/X6FNgQKBgQDAd00/+ZIp5HwRkJ7M
27
+ e4SSPxEW9kdCdNwCG9D6GvWZO9d/eeidnM+eoTRPx9NdvfiP5ztsZEtDDfXzMQFp
28
+ Jd7Loq5Nc3ZQBchPOIoFGIruUVWlUVawgneRKggfRzDEJLlKBjbVNsPPJFEPkMyO
29
+ XShRKR0cnY4pNen6ug6YRQn7kQKBgQC9OkqCeqVftgi5gE0VkBRf1i1bRIIClw9z
30
+ K08XYej54JcMdYqlTdpsRK0QQYye+wVH3V0Oe2p40leDeVbQMx4W4C1/Rl+Hk05r
31
+ QF9yvgIBPccE/D63ufcKdagj1QLHDXIHUhoMVqtaZIodBSenAV0uOtPKS+6vlVH6
32
+ OlM+Zo+7XwKBgQCOAbiCwn7g4A/W2fEBCQXY7iWK3q3XT+fgumtnjiq2JBwtl2JV
33
+ oJTkAydY0iSXHwreCouivyF02UEmbXsP/Pw1HdQjm1SpWIriQOI9Pk2L54Ec2DXx
34
+ SGI2Pl/9zAYkQsBf6NPeX2j8Vlxk8r6rL/sGXyJ2sZ1ptLjt4QfRu+bQsQKBgQCy
35
+ iHHOQ3sOH4iBxIx2ALdIaKHoj21+lhnMlpsLu6P9RiodZjUGm7quFemXAdF0GfA0
36
+ iqWGyWh+UC6ja/M9gk0sVhx3DeWJ27DMPjMP5jesBiZlDLz7yWhMpQ+bpxj0xznD
37
+ sHHFHGyVX3Bzyu5LglzxBi3Wmue7H831odvybv/DTwKBgETuVvv5b2EhMbKahtnf
38
+ dNrT9ZivoiRD4OaZBXffTG0I2HMu20a7nthKbv2o4pxztDcpW8s6UMU87N8YAK4W
39
+ GX3DjBMHIELxRE96tjifpW9MGQijLCI+jteq4lX0Pxf6HiUB+T1jZ1KDQQfvWJpH
40
+ cAvNvxF+Tev5A4GaIKwmahLI
41
+ -----END PRIVATE KEY-----
42
+ `;
43
+ export const E2E_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
44
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjkPnFFDeXFaR6ML/EkUG
45
+ Dcxi0uo6xF8cwkYILCr8GUummtd5SaZ3geDOZtSvklyuWnnTnkjpfxckDHC8yv8U
46
+ jBfwiLHGVreZkRUDu+WysjcrFFpNlhVE9HuCGZGgMqSXTdaSu+VxejmgiL46z/Dr
47
+ gXw0OtUk085XpC8jAPmTc8FAUdvS4QdWbodQjqHC8sl2K8vE4Pe542R0qVp5rXyo
48
+ N1lYB6Ry3GIkA1Jw9J5o4biV6K/9bGpoG/O5PssVzLiVk7vvrMREkDJqVYtYieMz
49
+ 0J+yM0u/faRJ/8xSYERsiKMJGt39gzmPLuzv+SQ5+VwiP0HKuK6vZMtUGh/dNXZF
50
+ zwIDAQAB
51
+ -----END PUBLIC KEY-----
52
+ `;
53
+ /**
54
+ * A key nothing in the fleet trusts, for the suites that assert a forged token
55
+ * is refused.
56
+ *
57
+ * A separate pair rather than a mangled signature, because they fail for
58
+ * different reasons: a corrupt signature could plausibly be caught by a
59
+ * structural check, while a *validly signed token from the wrong issuer's key*
60
+ * is the actual attack, and only a real verification catches it.
61
+ */ export const E2E_FOREIGN_PRIVATE_KEY_PEM = `-----BEGIN PRIVATE KEY-----
62
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgkVvRRzabj1gS
63
+ Zylt4+H7vMIL/nlCC/WoCLegBia3b9RaOkfCdXi+N99oFkcwwjywRsXmotNyPhEi
64
+ rqFEvvxUCZQmk9Cdo2+DYzFZq/6k2/5+e3Tr3NDlvYHVaqp6CRC+DqMIorQ6TT3D
65
+ SV/pu/Gz1U1MgE9TeB/Zw5yUjenknyjWzxeRwJjKvn10Jg2/YJzcvcsKeiED6+LU
66
+ FVkiJsvnxUvuJWnjGmtXocb85PbN4oD54eERLGL/cxZB4p8K6P/KTQrQV207qL+m
67
+ RqYjTj2Wu/ct4FSdGPKm5mhMP87sqioXU14t2R/nltIgiom0FajqyrR15krLkXSy
68
+ 0PrGIqbHAgMBAAECggEAT1aTrkxIRMQm6ez0cRqFOoyRuzhxtPtQ1kb8aIMxlTka
69
+ Db03YPQHhcH4zycW5RZMw3Ms7SGuZggaEm+EOwI9js6u2AL4tTOg8aRNKbhNGiuj
70
+ y953ruWMiMBDS28priQVlDuKPkWa1SX+aySx0j2uF8RBLhhGWgGEh2ba0yJuHCrq
71
+ N+l7wU26loDjlwS7dTQYc8z2WvGnKBbJVUJzJaLeUyMftVCd86sgjiYX9nnVuqxo
72
+ T9kE7/GhLOeP1vSjYj3Tk6CrQQlEanIUrSrogMt0LXVtek5sDyFPqTKnhd+bjNtl
73
+ sTfibYU7Yq4xlV/Bu3ntJYXh0hiL4VS1bOWc1rh6oQKBgQDLtiMbPuREXwJwgYKP
74
+ SB72RhGiT1fvklWyq43CGMsVgE43ncJAtrGb6A0fBVspYnS7YKIaUAVTyboNrycD
75
+ JzgFaVF/m75GeQDKOoRoPRfke/ytA3NIEeAy2Vo+1ZD60SLVdvFgusuJbwrg0Vn7
76
+ oxbigMi39Bif5ADz/+nupDgoJwKBgQDJyEFLq0CSiltScR7GzkCM9rSNs2ntSNOL
77
+ GVM7iZ32AP+UukFa02CC/s+6p660JUtFuZ6ax8npb+TAwWc2BydcRuqMQVmDMZ0j
78
+ l1A/PNZS9myvgy+RpwCtWPJc0k2AIrMIJM6pcj/ZByxV1tJcKj19CyM03phlg9Py
79
+ TtmkSX8QYQKBgQCnyDoeBKzJy18c/u5jyMkHmiqH/sW0olhHMpktVnJeITFLCXqn
80
+ BlI+0N+Nv0GYUmlGs46QEXxxyGKfRrXhGPpBKr9fVQ1gyeTmq0/G8xqsq5ovffoD
81
+ UAXSm8aCnjAtBPelzbN9MhzV80mIZaWxZmBA6kVnjXqCpq5KSWuJjGRcXQKBgBLe
82
+ 4IRkGqDZwZqfK6KqDU1hkRcjbUecpPQARVFvGE+2XjCZjp0g4Yi+rcyl++erCTQX
83
+ HOcawh5LsZf5Pl7GIn81vp+pSObFEA4RC5cuaFjP5PAxE5TKinyrsdbOcCMIm7eq
84
+ QY2FOsVgL1xDv96QsLlt/jfmjVgJERw7FY2QtgphAoGAcbrPfjRrDMqthf3LJsFu
85
+ ZH3hkadfbsCLld6UvAva0Vkugv5kOx0wB6+Bbk3rEGUPUxpaq1+iFhr7gUlghAA3
86
+ lRKwXGJZJc5PIUuHoxCYg/W4rKbYlrlYAwYQaNIucTT/bUgXw6Ra5rxEqnpgKiqJ
87
+ MUzrkxXjBuapqxOF4QzIySg=
88
+ -----END PRIVATE KEY-----
89
+ `;
90
+
91
+ //# sourceMappingURL=signing-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/fixtures/signing-key.ts"],"sourcesContent":["/**\n * A throwaway RSA pair the e2e suites sign and verify test tokens with.\n *\n * It lives here, in one place, because two sides need *the same* pair: the\n * `mock` composition root is configured to verify with the public half, and the\n * spec helpers sign with the private half. Generating one per file would make\n * every token the other side cannot verify.\n *\n * Deliberately **not** the development pair config-service seeds. A suite that\n * happened to verify a real dev token would be passing for the wrong reason,\n * and a fixture that doubles as a live credential is one copy-paste away from\n * becoming one.\n */\nexport const E2E_KEY_ID = 'e2e-key';\n\nexport const E2E_PRIVATE_KEY_PEM = `-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCOQ+cUUN5cVpHo\nwv8SRQYNzGLS6jrEXxzCRggsKvwZS6aa13lJpneB4M5m1K+SXK5aedOeSOl/FyQM\ncLzK/xSMF/CIscZWt5mRFQO75bKyNysUWk2WFUT0e4IZkaAypJdN1pK75XF6OaCI\nvjrP8OuBfDQ61STTzlekLyMA+ZNzwUBR29LhB1Zuh1COocLyyXYry8Tg97njZHSp\nWnmtfKg3WVgHpHLcYiQDUnD0nmjhuJXor/1samgb87k+yxXMuJWTu++sxESQMmpV\ni1iJ4zPQn7IzS799pEn/zFJgRGyIowka3f2DOY8u7O/5JDn5XCI/Qcq4rq9ky1Qa\nH901dkXPAgMBAAECggEAA26GHOp0srLbAxLRGMgrPakUfoZsXkL1+qKd1hLqe6jW\nLVbpuvgyWrEFkLEBmzXJIK9ev3JFelEgle4ECoNPXOjf0IGniWDcaiIvMcNb0Cbz\npGmZPYYE7um4PM2otWVcyeGqvOkkbPQieBu+oFSX4NkSJ7BEjHzCox9BvcryF59d\nc9oFzS97YryD8g94qH6SqgF90qxnxD5oSqz3yRuON6o6SiBwSdsT5yCTiiBIsBSb\nyZP7KN/4LPZnFaPcHJ6UtlMOPae47Z7UBdiuP8/isSyIbnU7j1+TrpXUBqqG6JFI\nEJx3rRW4yYy/syt8BkkLnKa9idbZfCgii+C/X6FNgQKBgQDAd00/+ZIp5HwRkJ7M\ne4SSPxEW9kdCdNwCG9D6GvWZO9d/eeidnM+eoTRPx9NdvfiP5ztsZEtDDfXzMQFp\nJd7Loq5Nc3ZQBchPOIoFGIruUVWlUVawgneRKggfRzDEJLlKBjbVNsPPJFEPkMyO\nXShRKR0cnY4pNen6ug6YRQn7kQKBgQC9OkqCeqVftgi5gE0VkBRf1i1bRIIClw9z\nK08XYej54JcMdYqlTdpsRK0QQYye+wVH3V0Oe2p40leDeVbQMx4W4C1/Rl+Hk05r\nQF9yvgIBPccE/D63ufcKdagj1QLHDXIHUhoMVqtaZIodBSenAV0uOtPKS+6vlVH6\nOlM+Zo+7XwKBgQCOAbiCwn7g4A/W2fEBCQXY7iWK3q3XT+fgumtnjiq2JBwtl2JV\noJTkAydY0iSXHwreCouivyF02UEmbXsP/Pw1HdQjm1SpWIriQOI9Pk2L54Ec2DXx\nSGI2Pl/9zAYkQsBf6NPeX2j8Vlxk8r6rL/sGXyJ2sZ1ptLjt4QfRu+bQsQKBgQCy\niHHOQ3sOH4iBxIx2ALdIaKHoj21+lhnMlpsLu6P9RiodZjUGm7quFemXAdF0GfA0\niqWGyWh+UC6ja/M9gk0sVhx3DeWJ27DMPjMP5jesBiZlDLz7yWhMpQ+bpxj0xznD\nsHHFHGyVX3Bzyu5LglzxBi3Wmue7H831odvybv/DTwKBgETuVvv5b2EhMbKahtnf\ndNrT9ZivoiRD4OaZBXffTG0I2HMu20a7nthKbv2o4pxztDcpW8s6UMU87N8YAK4W\nGX3DjBMHIELxRE96tjifpW9MGQijLCI+jteq4lX0Pxf6HiUB+T1jZ1KDQQfvWJpH\ncAvNvxF+Tev5A4GaIKwmahLI\n-----END PRIVATE KEY-----\n`;\n\nexport const E2E_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjkPnFFDeXFaR6ML/EkUG\nDcxi0uo6xF8cwkYILCr8GUummtd5SaZ3geDOZtSvklyuWnnTnkjpfxckDHC8yv8U\njBfwiLHGVreZkRUDu+WysjcrFFpNlhVE9HuCGZGgMqSXTdaSu+VxejmgiL46z/Dr\ngXw0OtUk085XpC8jAPmTc8FAUdvS4QdWbodQjqHC8sl2K8vE4Pe542R0qVp5rXyo\nN1lYB6Ry3GIkA1Jw9J5o4biV6K/9bGpoG/O5PssVzLiVk7vvrMREkDJqVYtYieMz\n0J+yM0u/faRJ/8xSYERsiKMJGt39gzmPLuzv+SQ5+VwiP0HKuK6vZMtUGh/dNXZF\nzwIDAQAB\n-----END PUBLIC KEY-----\n`;\n\n/**\n * A key nothing in the fleet trusts, for the suites that assert a forged token\n * is refused.\n *\n * A separate pair rather than a mangled signature, because they fail for\n * different reasons: a corrupt signature could plausibly be caught by a\n * structural check, while a *validly signed token from the wrong issuer's key*\n * is the actual attack, and only a real verification catches it.\n */\nexport const E2E_FOREIGN_PRIVATE_KEY_PEM = `-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgkVvRRzabj1gS\nZylt4+H7vMIL/nlCC/WoCLegBia3b9RaOkfCdXi+N99oFkcwwjywRsXmotNyPhEi\nrqFEvvxUCZQmk9Cdo2+DYzFZq/6k2/5+e3Tr3NDlvYHVaqp6CRC+DqMIorQ6TT3D\nSV/pu/Gz1U1MgE9TeB/Zw5yUjenknyjWzxeRwJjKvn10Jg2/YJzcvcsKeiED6+LU\nFVkiJsvnxUvuJWnjGmtXocb85PbN4oD54eERLGL/cxZB4p8K6P/KTQrQV207qL+m\nRqYjTj2Wu/ct4FSdGPKm5mhMP87sqioXU14t2R/nltIgiom0FajqyrR15krLkXSy\n0PrGIqbHAgMBAAECggEAT1aTrkxIRMQm6ez0cRqFOoyRuzhxtPtQ1kb8aIMxlTka\nDb03YPQHhcH4zycW5RZMw3Ms7SGuZggaEm+EOwI9js6u2AL4tTOg8aRNKbhNGiuj\ny953ruWMiMBDS28priQVlDuKPkWa1SX+aySx0j2uF8RBLhhGWgGEh2ba0yJuHCrq\nN+l7wU26loDjlwS7dTQYc8z2WvGnKBbJVUJzJaLeUyMftVCd86sgjiYX9nnVuqxo\nT9kE7/GhLOeP1vSjYj3Tk6CrQQlEanIUrSrogMt0LXVtek5sDyFPqTKnhd+bjNtl\nsTfibYU7Yq4xlV/Bu3ntJYXh0hiL4VS1bOWc1rh6oQKBgQDLtiMbPuREXwJwgYKP\nSB72RhGiT1fvklWyq43CGMsVgE43ncJAtrGb6A0fBVspYnS7YKIaUAVTyboNrycD\nJzgFaVF/m75GeQDKOoRoPRfke/ytA3NIEeAy2Vo+1ZD60SLVdvFgusuJbwrg0Vn7\noxbigMi39Bif5ADz/+nupDgoJwKBgQDJyEFLq0CSiltScR7GzkCM9rSNs2ntSNOL\nGVM7iZ32AP+UukFa02CC/s+6p660JUtFuZ6ax8npb+TAwWc2BydcRuqMQVmDMZ0j\nl1A/PNZS9myvgy+RpwCtWPJc0k2AIrMIJM6pcj/ZByxV1tJcKj19CyM03phlg9Py\nTtmkSX8QYQKBgQCnyDoeBKzJy18c/u5jyMkHmiqH/sW0olhHMpktVnJeITFLCXqn\nBlI+0N+Nv0GYUmlGs46QEXxxyGKfRrXhGPpBKr9fVQ1gyeTmq0/G8xqsq5ovffoD\nUAXSm8aCnjAtBPelzbN9MhzV80mIZaWxZmBA6kVnjXqCpq5KSWuJjGRcXQKBgBLe\n4IRkGqDZwZqfK6KqDU1hkRcjbUecpPQARVFvGE+2XjCZjp0g4Yi+rcyl++erCTQX\nHOcawh5LsZf5Pl7GIn81vp+pSObFEA4RC5cuaFjP5PAxE5TKinyrsdbOcCMIm7eq\nQY2FOsVgL1xDv96QsLlt/jfmjVgJERw7FY2QtgphAoGAcbrPfjRrDMqthf3LJsFu\nZH3hkadfbsCLld6UvAva0Vkugv5kOx0wB6+Bbk3rEGUPUxpaq1+iFhr7gUlghAA3\nlRKwXGJZJc5PIUuHoxCYg/W4rKbYlrlYAwYQaNIucTT/bUgXw6Ra5rxEqnpgKiqJ\nMUzrkxXjBuapqxOF4QzIySg=\n-----END PRIVATE KEY-----\n`;\n"],"names":["E2E_KEY_ID","E2E_PRIVATE_KEY_PEM","E2E_PUBLIC_KEY_PEM","E2E_FOREIGN_PRIVATE_KEY_PEM"],"mappings":"AAAA;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMA,aAAa,UAAU;AAEpC,OAAO,MAAMC,sBAAsB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BpC,CAAC,CAAC;AAEF,OAAO,MAAMC,qBAAqB,CAAC;;;;;;;;;AASnC,CAAC,CAAC;AAEF;;;;;;;;CAQC,GACD,OAAO,MAAMC,8BAA8B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4B5C,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './profile/profile.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './profile/profile.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './profile/profile.js';\n"],"names":[],"mappings":"AAAA,cAAc,uBAAuB"}
@@ -0,0 +1,43 @@
1
+ import { type E2eEnv } from '../profile/profile.js';
2
+ /** Opts out of the guard, for a developer who knows what they are attaching to. */
3
+ export declare const ALLOW_DEV_SERVER_VAR = "R10C_E2E_ALLOW_DEV_SERVER";
4
+ export interface AssertExpectedServerOptions {
5
+ /** Where the suite is pointed, e.g. `http://localhost:3001`. */
6
+ readonly baseURL: string;
7
+ readonly env?: E2eEnv;
8
+ readonly fetchImpl?: typeof fetch;
9
+ readonly warn?: (message: string) => void;
10
+ }
11
+ /**
12
+ * Refuses to run the hermetic suite against a development server.
13
+ *
14
+ * `reuseExistingServer` is what makes a local run fast, and turning it off costs
15
+ * a production build every time. So the reuse stays and the *assumption* is
16
+ * checked instead: the `mock` profile's whole claim is that it is hermetic, and
17
+ * attached to a dev server it is not. Turning a silent wrong answer into a loud
18
+ * failure is the trade — see issue #69.
19
+ *
20
+ * `live` is exempt on purpose: it expects an already-running app and makes no
21
+ * hermeticity claim, so which build answers is the operator's business.
22
+ *
23
+ * Only when **both** signals are unreadable does the run continue, with a
24
+ * warning: an app that exposes neither is not a reason to refuse to test it.
25
+ */
26
+ export declare const assertExpectedServer: ({ baseURL, env, fetchImpl, warn, }: AssertExpectedServerOptions) => Promise<void>;
27
+ /**
28
+ * The form `defineEntifixE2eTest` calls, from an auto fixture.
29
+ *
30
+ * A fixture rather than `globalSetup`, which is where this naturally belongs:
31
+ * Playwright loads a `globalSetup` file through a different module path than
32
+ * the config and the specs, and this package is `"type": "module"` while an
33
+ * app's `playwright.config.ts` is CJS — the same file transpiles for one and
34
+ * throws `exports is not defined in ES module scope` for the other. The
35
+ * fixture rides the path that already works, at the cost of reporting the
36
+ * refusal once per test rather than once per run.
37
+ *
38
+ * The promise is cached, so the probe happens once and every subsequent test
39
+ * rejects with the same error instead of re-asking a server that will not have
40
+ * changed mid-run.
41
+ */
42
+ export declare const assertExpectedServerOnce: (baseURL: string | undefined) => Promise<void>;
43
+ //# sourceMappingURL=assert-expected-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-expected-server.d.ts","sourceRoot":"","sources":["../../src/playwright/assert-expected-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAEnE,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,8BAA8B,CAAC;AA0BhE,MAAM,WAAW,2BAA2B;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAiBD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAU,oCAKxC,2BAA2B,KAAG,OAAO,CAAC,IAAI,CAiC5C,CAAC;AAKF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS,MAAM,GAAG,SAAS,KAC1B,OAAO,CAAC,IAAI,CAKd,CAAC"}
@@ -0,0 +1,98 @@
1
+ import { isMockProfile } from '../profile/profile.js';
2
+ /** Opts out of the guard, for a developer who knows what they are attaching to. */ export const ALLOW_DEV_SERVER_VAR = 'R10C_E2E_ALLOW_DEV_SERVER';
3
+ /**
4
+ * Liveness, not the config's `readyPath`: every app answers it, it answers from
5
+ * the process alone, and it carries the one field this check needs. `readyPath`
6
+ * differs per app and defaults to `/`, which returns HTML.
7
+ */ const LIVENESS_PATH = '/api/health/live';
8
+ /**
9
+ * The second signal, which needs no cooperation from the app at all.
10
+ *
11
+ * `next dev` serves its static assets under the literal segment `development`;
12
+ * a production build uses a hashed build id, so this 404s under `next start`.
13
+ * It is a Next internal and therefore the *fallback*, but it is the one that
14
+ * survives the case that motivates it: an `nx e2e` run builds into the same
15
+ * `.next` the running dev server owns, which corrupts that server's Turbopack
16
+ * cache and makes every app route — liveness included — answer `500`. A guard
17
+ * that only asked the app would degrade to "cannot tell" at exactly the moment
18
+ * it is needed.
19
+ */ const DEV_ASSET_PATH = '/_next/static/development/_buildManifest.js';
20
+ /** A probe that hangs must not hold the whole run hostage. */ const PROBE_TIMEOUT_MS = 5000;
21
+ const describeMismatch = (baseURL)=>[
22
+ `The hermetic e2e profile attached to a DEVELOPMENT server at ${baseURL}.`,
23
+ '',
24
+ 'Playwright reuses whatever already listens on the app port, so this run would',
25
+ 'test `next dev` — a different bundle, no prerender, and with the dev fleet',
26
+ "behind it the real services instead of this profile's fakes. It can fail, or",
27
+ 'pass, for reasons that have nothing to do with the code under test. The build',
28
+ 'this run just made also writes the same `.next` the dev server owns, which',
29
+ 'corrupts its Turbopack cache on the way past.',
30
+ '',
31
+ 'Stop the dev server on that port and run again, or set',
32
+ `${ALLOW_DEV_SERVER_VAR}=1 to accept the risk.`
33
+ ].join('\n');
34
+ /**
35
+ * Refuses to run the hermetic suite against a development server.
36
+ *
37
+ * `reuseExistingServer` is what makes a local run fast, and turning it off costs
38
+ * a production build every time. So the reuse stays and the *assumption* is
39
+ * checked instead: the `mock` profile's whole claim is that it is hermetic, and
40
+ * attached to a dev server it is not. Turning a silent wrong answer into a loud
41
+ * failure is the trade — see issue #69.
42
+ *
43
+ * `live` is exempt on purpose: it expects an already-running app and makes no
44
+ * hermeticity claim, so which build answers is the operator's business.
45
+ *
46
+ * Only when **both** signals are unreadable does the run continue, with a
47
+ * warning: an app that exposes neither is not a reason to refuse to test it.
48
+ */ export const assertExpectedServer = async ({ baseURL, env = process.env, fetchImpl = fetch, warn = (message)=>console.warn(message) })=>{
49
+ if (!isMockProfile(env)) return;
50
+ const override = env[ALLOW_DEV_SERVER_VAR];
51
+ if (override !== undefined && override !== '') return;
52
+ const get = async (path)=>{
53
+ try {
54
+ return await fetchImpl(`${baseURL}${path}`, {
55
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
56
+ });
57
+ } catch (unused) {
58
+ return undefined;
59
+ }
60
+ };
61
+ const liveness = await get(LIVENESS_PATH);
62
+ if ((liveness == null ? void 0 : liveness.ok) === true) {
63
+ const mode = (await liveness.json()).mode;
64
+ if (mode === 'production') return;
65
+ if (mode === 'development') throw new Error(describeMismatch(baseURL));
66
+ }
67
+ // The app could not answer for itself. Ask Next directly.
68
+ const devAsset = await get(DEV_ASSET_PATH);
69
+ if (devAsset === undefined) {
70
+ warn(`e2e: could not reach ${baseURL}; cannot tell which build is serving.`);
71
+ return;
72
+ }
73
+ if (devAsset.ok) throw new Error(describeMismatch(baseURL));
74
+ };
75
+ /** One probe per worker process, whatever the outcome. */ let verdict;
76
+ /**
77
+ * The form `defineEntifixE2eTest` calls, from an auto fixture.
78
+ *
79
+ * A fixture rather than `globalSetup`, which is where this naturally belongs:
80
+ * Playwright loads a `globalSetup` file through a different module path than
81
+ * the config and the specs, and this package is `"type": "module"` while an
82
+ * app's `playwright.config.ts` is CJS — the same file transpiles for one and
83
+ * throws `exports is not defined in ES module scope` for the other. The
84
+ * fixture rides the path that already works, at the cost of reporting the
85
+ * refusal once per test rather than once per run.
86
+ *
87
+ * The promise is cached, so the probe happens once and every subsequent test
88
+ * rejects with the same error instead of re-asking a server that will not have
89
+ * changed mid-run.
90
+ */ export const assertExpectedServerOnce = (baseURL)=>{
91
+ if (baseURL === undefined || baseURL === '') return Promise.resolve();
92
+ verdict != null ? verdict : verdict = assertExpectedServer({
93
+ baseURL
94
+ });
95
+ return verdict;
96
+ };
97
+
98
+ //# sourceMappingURL=assert-expected-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/playwright/assert-expected-server.ts"],"sourcesContent":["import { type E2eEnv, isMockProfile } from '../profile/profile.js';\n\n/** Opts out of the guard, for a developer who knows what they are attaching to. */\nexport const ALLOW_DEV_SERVER_VAR = 'R10C_E2E_ALLOW_DEV_SERVER';\n\n/**\n * Liveness, not the config's `readyPath`: every app answers it, it answers from\n * the process alone, and it carries the one field this check needs. `readyPath`\n * differs per app and defaults to `/`, which returns HTML.\n */\nconst LIVENESS_PATH = '/api/health/live';\n\n/**\n * The second signal, which needs no cooperation from the app at all.\n *\n * `next dev` serves its static assets under the literal segment `development`;\n * a production build uses a hashed build id, so this 404s under `next start`.\n * It is a Next internal and therefore the *fallback*, but it is the one that\n * survives the case that motivates it: an `nx e2e` run builds into the same\n * `.next` the running dev server owns, which corrupts that server's Turbopack\n * cache and makes every app route — liveness included — answer `500`. A guard\n * that only asked the app would degrade to \"cannot tell\" at exactly the moment\n * it is needed.\n */\nconst DEV_ASSET_PATH = '/_next/static/development/_buildManifest.js';\n\n/** A probe that hangs must not hold the whole run hostage. */\nconst PROBE_TIMEOUT_MS = 5_000;\n\nexport interface AssertExpectedServerOptions {\n /** Where the suite is pointed, e.g. `http://localhost:3001`. */\n readonly baseURL: string;\n readonly env?: E2eEnv;\n readonly fetchImpl?: typeof fetch;\n readonly warn?: (message: string) => void;\n}\n\nconst describeMismatch = (baseURL: string): string =>\n [\n `The hermetic e2e profile attached to a DEVELOPMENT server at ${baseURL}.`,\n '',\n 'Playwright reuses whatever already listens on the app port, so this run would',\n 'test `next dev` — a different bundle, no prerender, and with the dev fleet',\n \"behind it the real services instead of this profile's fakes. It can fail, or\",\n 'pass, for reasons that have nothing to do with the code under test. The build',\n 'this run just made also writes the same `.next` the dev server owns, which',\n 'corrupts its Turbopack cache on the way past.',\n '',\n 'Stop the dev server on that port and run again, or set',\n `${ALLOW_DEV_SERVER_VAR}=1 to accept the risk.`,\n ].join('\\n');\n\n/**\n * Refuses to run the hermetic suite against a development server.\n *\n * `reuseExistingServer` is what makes a local run fast, and turning it off costs\n * a production build every time. So the reuse stays and the *assumption* is\n * checked instead: the `mock` profile's whole claim is that it is hermetic, and\n * attached to a dev server it is not. Turning a silent wrong answer into a loud\n * failure is the trade — see issue #69.\n *\n * `live` is exempt on purpose: it expects an already-running app and makes no\n * hermeticity claim, so which build answers is the operator's business.\n *\n * Only when **both** signals are unreadable does the run continue, with a\n * warning: an app that exposes neither is not a reason to refuse to test it.\n */\nexport const assertExpectedServer = async ({\n baseURL,\n env = process.env,\n fetchImpl = fetch,\n warn = message => console.warn(message),\n}: AssertExpectedServerOptions): Promise<void> => {\n if (!isMockProfile(env)) return;\n\n const override = env[ALLOW_DEV_SERVER_VAR];\n if (override !== undefined && override !== '') return;\n\n const get = async (path: string): Promise<Response | undefined> => {\n try {\n return await fetchImpl(`${baseURL}${path}`, {\n signal: AbortSignal.timeout(PROBE_TIMEOUT_MS),\n });\n } catch {\n return undefined;\n }\n };\n\n const liveness = await get(LIVENESS_PATH);\n if (liveness?.ok === true) {\n const mode = ((await liveness.json()) as { mode?: unknown }).mode;\n if (mode === 'production') return;\n if (mode === 'development') throw new Error(describeMismatch(baseURL));\n }\n\n // The app could not answer for itself. Ask Next directly.\n const devAsset = await get(DEV_ASSET_PATH);\n if (devAsset === undefined) {\n warn(\n `e2e: could not reach ${baseURL}; cannot tell which build is serving.`,\n );\n return;\n }\n\n if (devAsset.ok) throw new Error(describeMismatch(baseURL));\n};\n\n/** One probe per worker process, whatever the outcome. */\nlet verdict: Promise<void> | undefined;\n\n/**\n * The form `defineEntifixE2eTest` calls, from an auto fixture.\n *\n * A fixture rather than `globalSetup`, which is where this naturally belongs:\n * Playwright loads a `globalSetup` file through a different module path than\n * the config and the specs, and this package is `\"type\": \"module\"` while an\n * app's `playwright.config.ts` is CJS — the same file transpiles for one and\n * throws `exports is not defined in ES module scope` for the other. The\n * fixture rides the path that already works, at the cost of reporting the\n * refusal once per test rather than once per run.\n *\n * The promise is cached, so the probe happens once and every subsequent test\n * rejects with the same error instead of re-asking a server that will not have\n * changed mid-run.\n */\nexport const assertExpectedServerOnce = (\n baseURL: string | undefined,\n): Promise<void> => {\n if (baseURL === undefined || baseURL === '') return Promise.resolve();\n\n verdict ??= assertExpectedServer({ baseURL });\n return verdict;\n};\n"],"names":["isMockProfile","ALLOW_DEV_SERVER_VAR","LIVENESS_PATH","DEV_ASSET_PATH","PROBE_TIMEOUT_MS","describeMismatch","baseURL","join","assertExpectedServer","env","process","fetchImpl","fetch","warn","message","console","override","undefined","get","path","signal","AbortSignal","timeout","liveness","ok","mode","json","Error","devAsset","verdict","assertExpectedServerOnce","Promise","resolve"],"mappings":"AAAA,SAAsBA,aAAa,QAAQ,wBAAwB;AAEnE,iFAAiF,GACjF,OAAO,MAAMC,uBAAuB,4BAA4B;AAEhE;;;;CAIC,GACD,MAAMC,gBAAgB;AAEtB;;;;;;;;;;;CAWC,GACD,MAAMC,iBAAiB;AAEvB,4DAA4D,GAC5D,MAAMC,mBAAmB;AAUzB,MAAMC,mBAAmB,CAACC,UACxB;QACE,CAAC,6DAA6D,EAAEA,QAAQ,CAAC,CAAC;QAC1E;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,GAAGL,qBAAqB,sBAAsB,CAAC;KAChD,CAACM,IAAI,CAAC;AAET;;;;;;;;;;;;;;CAcC,GACD,OAAO,MAAMC,uBAAuB,OAAO,EACzCF,OAAO,EACPG,MAAMC,QAAQD,GAAG,EACjBE,YAAYC,KAAK,EACjBC,OAAOC,CAAAA,UAAWC,QAAQF,IAAI,CAACC,QAAQ,EACX;IAC5B,IAAI,CAACd,cAAcS,MAAM;IAEzB,MAAMO,WAAWP,GAAG,CAACR,qBAAqB;IAC1C,IAAIe,aAAaC,aAAaD,aAAa,IAAI;IAE/C,MAAME,MAAM,OAAOC;QACjB,IAAI;YACF,OAAO,MAAMR,UAAU,GAAGL,UAAUa,MAAM,EAAE;gBAC1CC,QAAQC,YAAYC,OAAO,CAAClB;YAC9B;QACF,EAAE,eAAM;YACN,OAAOa;QACT;IACF;IAEA,MAAMM,WAAW,MAAML,IAAIhB;IAC3B,IAAIqB,CAAAA,4BAAAA,SAAUC,EAAE,MAAK,MAAM;QACzB,MAAMC,OAAO,AAAE,CAAA,MAAMF,SAASG,IAAI,EAAC,EAA0BD,IAAI;QACjE,IAAIA,SAAS,cAAc;QAC3B,IAAIA,SAAS,eAAe,MAAM,IAAIE,MAAMtB,iBAAiBC;IAC/D;IAEA,0DAA0D;IAC1D,MAAMsB,WAAW,MAAMV,IAAIf;IAC3B,IAAIyB,aAAaX,WAAW;QAC1BJ,KACE,CAAC,qBAAqB,EAAEP,QAAQ,qCAAqC,CAAC;QAExE;IACF;IAEA,IAAIsB,SAASJ,EAAE,EAAE,MAAM,IAAIG,MAAMtB,iBAAiBC;AACpD,EAAE;AAEF,wDAAwD,GACxD,IAAIuB;AAEJ;;;;;;;;;;;;;;CAcC,GACD,OAAO,MAAMC,2BAA2B,CACtCxB;IAEA,IAAIA,YAAYW,aAAaX,YAAY,IAAI,OAAOyB,QAAQC,OAAO;IAEnEH,kBAAAA,UAAAA,UAAYrB,qBAAqB;QAAEF;IAAQ;IAC3C,OAAOuB;AACT,EAAE"}
@@ -0,0 +1,78 @@
1
+ import { type PlaywrightTestConfig } from '@playwright/test';
2
+ import { requireLiveUrl, resolveE2eProfile } from '../profile/profile.js';
3
+ export interface EntifixE2eConfigOptions {
4
+ /** The playwright config file — pass `__filename`, as the Nx preset wants. */
5
+ configFile: string;
6
+ /**
7
+ * The app's directory, relative to the workspace root, e.g.
8
+ * `apps/back-office-app`. The server is started from there.
9
+ */
10
+ appDir: string;
11
+ /** The port that app serves on (the `300N` convention). */
12
+ port: number;
13
+ /** Spec directory, relative to the config file. */
14
+ testDir?: string;
15
+ /**
16
+ * Path Playwright polls to decide the server is up, relative to the base URL.
17
+ *
18
+ * A gated app needs one, and it must be **exempt from the auth middleware and
19
+ * free of backend dependencies**: a cold probe against `/` gets a redirect to
20
+ * a sign-in origin that is not running, and one against `/api/config` gets a
21
+ * 500 until config-service is up. Either way the run dies on `Timed out
22
+ * waiting for config.webServer` before a single spec starts. Defaults to the
23
+ * base URL, which is right for an app with no gate.
24
+ */
25
+ readyPath?: string;
26
+ /**
27
+ * What Playwright runs to serve the app, when `next start` alone is not
28
+ * enough.
29
+ *
30
+ * The one caller so far is the storefront, whose reads happen in **server
31
+ * components**: `page.route()` cannot see a fetch the Next process makes, so
32
+ * its `mock` profile launches the server under a `--import` preload that
33
+ * installs msw inside that process instead. Expressed here rather than
34
+ * through `overrides` so the cwd, the readiness URL and the reuse rule stay
35
+ * in one place — an override would have to restate all three to change one.
36
+ *
37
+ * Ignored outside `mock`: a `live` run talks to real services and must not
38
+ * start a faked one.
39
+ */
40
+ mockServerCommand?: string;
41
+ /** Anything else to merge in, for a project with a genuine special case. */
42
+ overrides?: PlaywrightTestConfig;
43
+ }
44
+ /**
45
+ * The shared Playwright configuration for an entifix app e2e project.
46
+ *
47
+ * The profile decides three things, and specs decide none of them:
48
+ *
49
+ * - **which specs run** — by filename (`*.mock.spec.ts` / `*.live.spec.ts`).
50
+ * Selection by `testIgnore` rather than by an in-spec `test.skip` means a
51
+ * run with the wrong environment fails instead of quietly reporting green.
52
+ * - **the base URL** — the local app in `mock`; in `live` the app is expected
53
+ * to already be running (started with its real backend), so Playwright
54
+ * reuses it rather than racing a second one.
55
+ * - **whether a reused server is acceptable** — `mock` refuses a development
56
+ * one, `live` accepts whatever is there. Enforced by an auto fixture in
57
+ * `defineEntifixE2eTest`, not from here: Playwright loads `globalSetup`
58
+ * through a different module path than the one it uses for the config and the
59
+ * specs, and this package is `"type": "module"` while an app's
60
+ * `playwright.config.ts` is CJS — a file reached both ways transpiles for one
61
+ * and fails for the other. See `assertExpectedServer`.
62
+ *
63
+ * Browsers are chromium in both profiles unless `E2E_BROWSERS=all`.
64
+ */
65
+ export declare const defineEntifixE2eConfig: ({ configFile, appDir, port, testDir, readyPath, mockServerCommand, overrides, }: EntifixE2eConfigOptions) => PlaywrightTestConfig;
66
+ /**
67
+ * Re-exported so a Playwright suite reaches both from this entry point.
68
+ *
69
+ * ⚠️ Not only for convenience. `@nx/enforce-module-boundaries` treats a package
70
+ * that any file in the consuming project loads with a dynamic `import()` as
71
+ * lazy-loaded, and then refuses every *static* import of it — and
72
+ * `marketplace-app-e2e` has one: its msw preload must call `register()` for the
73
+ * resolver hook before it resolves anything, so its imports cannot be hoisted.
74
+ * The rule keys on the specifier, so a `live` spec there can reach
75
+ * `requireLiveUrl` through `/playwright` and not through the root entry.
76
+ */
77
+ export { requireLiveUrl, resolveE2eProfile };
78
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/playwright/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAEL,cAAc,EACd,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACtC,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC;AAuBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,sBAAsB,GAAI,iFAQpC,uBAAuB,KAAG,oBAuC5B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { join } from 'node:path';
3
+ import { workspaceRoot } from '@nx/devkit';
4
+ import { nxE2EPreset } from '@nx/playwright/preset';
5
+ import { defineConfig, devices } from '@playwright/test';
6
+ import { isMockProfile, requireLiveUrl, resolveE2eProfile } from '../profile/profile.js';
7
+ /**
8
+ * Every browser Playwright can drive.
9
+ *
10
+ * Chromium is the default in **both** profiles. Interception happens through
11
+ * `page.route()`, which behaves the same everywhere, so `mock` would triple the
12
+ * pull-request time to re-assert identical wire traffic; and a normal dev
13
+ * machine has only chromium installed, so a `live` run that insisted on all
14
+ * three failed on a missing engine rather than on the code. Cross-browser
15
+ * rendering is worth checking deliberately, not on every run.
16
+ */ const ALL_BROWSERS = [
17
+ {
18
+ name: 'chromium',
19
+ use: _extends({}, devices['Desktop Chrome'])
20
+ },
21
+ {
22
+ name: 'firefox',
23
+ use: _extends({}, devices['Desktop Firefox'])
24
+ },
25
+ {
26
+ name: 'webkit',
27
+ use: _extends({}, devices['Desktop Safari'])
28
+ }
29
+ ];
30
+ const CHROMIUM_ONLY = ALL_BROWSERS.slice(0, 1);
31
+ /** Opts into firefox and webkit; needs `pnpm exec playwright install` first. */ const ALL_BROWSERS_VAR = 'E2E_BROWSERS';
32
+ /**
33
+ * The shared Playwright configuration for an entifix app e2e project.
34
+ *
35
+ * The profile decides three things, and specs decide none of them:
36
+ *
37
+ * - **which specs run** — by filename (`*.mock.spec.ts` / `*.live.spec.ts`).
38
+ * Selection by `testIgnore` rather than by an in-spec `test.skip` means a
39
+ * run with the wrong environment fails instead of quietly reporting green.
40
+ * - **the base URL** — the local app in `mock`; in `live` the app is expected
41
+ * to already be running (started with its real backend), so Playwright
42
+ * reuses it rather than racing a second one.
43
+ * - **whether a reused server is acceptable** — `mock` refuses a development
44
+ * one, `live` accepts whatever is there. Enforced by an auto fixture in
45
+ * `defineEntifixE2eTest`, not from here: Playwright loads `globalSetup`
46
+ * through a different module path than the one it uses for the config and the
47
+ * specs, and this package is `"type": "module"` while an app's
48
+ * `playwright.config.ts` is CJS — a file reached both ways transpiles for one
49
+ * and fails for the other. See `assertExpectedServer`.
50
+ *
51
+ * Browsers are chromium in both profiles unless `E2E_BROWSERS=all`.
52
+ */ export const defineEntifixE2eConfig = ({ configFile, appDir, port, testDir = './src', readyPath = '', mockServerCommand, overrides = {} })=>{
53
+ var _process_env_BASE_URL;
54
+ const mock = isMockProfile();
55
+ const baseURL = (_process_env_BASE_URL = process.env['BASE_URL']) != null ? _process_env_BASE_URL : `http://localhost:${port}`;
56
+ return defineConfig(_extends({}, nxE2EPreset(configFile, {
57
+ testDir
58
+ }), {
59
+ // The other profile's specs are not skipped, they are not collected: a
60
+ // spec that cannot run here has nothing to say about this run.
61
+ testIgnore: mock ? '**/*.live.spec.ts' : '**/*.mock.spec.ts'
62
+ }, mock ? {} : {
63
+ timeout: 90000
64
+ }, {
65
+ use: {
66
+ baseURL,
67
+ trace: 'on-first-retry'
68
+ },
69
+ // Playwright starts the server itself, with `next start` rather than
70
+ // `nx run <app>:start`. An nx invocation here is inferred by
71
+ // `@nx/playwright/plugin` as a *continuous task dependency* of `e2e`, and
72
+ // the run then waits on a server that never signals completion — the e2e
73
+ // task never starts. The build the server needs is expressed instead as a
74
+ // plain `dependsOn` on the e2e target.
75
+ webServer: {
76
+ command: mock && mockServerCommand !== undefined ? mockServerCommand : `pnpm exec next start -p ${port}`,
77
+ cwd: join(workspaceRoot, appDir),
78
+ url: `${baseURL}${readyPath}`,
79
+ reuseExistingServer: true
80
+ },
81
+ projects: process.env[ALL_BROWSERS_VAR] === 'all' ? ALL_BROWSERS : CHROMIUM_ONLY
82
+ }, overrides));
83
+ };
84
+ /**
85
+ * Re-exported so a Playwright suite reaches both from this entry point.
86
+ *
87
+ * ⚠️ Not only for convenience. `@nx/enforce-module-boundaries` treats a package
88
+ * that any file in the consuming project loads with a dynamic `import()` as
89
+ * lazy-loaded, and then refuses every *static* import of it — and
90
+ * `marketplace-app-e2e` has one: its msw preload must call `register()` for the
91
+ * resolver hook before it resolves anything, so its imports cannot be hoisted.
92
+ * The rule keys on the specifier, so a `live` spec there can reach
93
+ * `requireLiveUrl` through `/playwright` and not through the root entry.
94
+ */ export { requireLiveUrl, resolveE2eProfile };
95
+
96
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/playwright/config.ts"],"sourcesContent":["import { join } from 'node:path';\n\nimport { workspaceRoot } from '@nx/devkit';\nimport { nxE2EPreset } from '@nx/playwright/preset';\nimport {\n defineConfig,\n devices,\n type PlaywrightTestConfig,\n} from '@playwright/test';\n\nimport {\n isMockProfile,\n requireLiveUrl,\n resolveE2eProfile,\n} from '../profile/profile.js';\n\nexport interface EntifixE2eConfigOptions {\n /** The playwright config file — pass `__filename`, as the Nx preset wants. */\n configFile: string;\n /**\n * The app's directory, relative to the workspace root, e.g.\n * `apps/back-office-app`. The server is started from there.\n */\n appDir: string;\n /** The port that app serves on (the `300N` convention). */\n port: number;\n /** Spec directory, relative to the config file. */\n testDir?: string;\n /**\n * Path Playwright polls to decide the server is up, relative to the base URL.\n *\n * A gated app needs one, and it must be **exempt from the auth middleware and\n * free of backend dependencies**: a cold probe against `/` gets a redirect to\n * a sign-in origin that is not running, and one against `/api/config` gets a\n * 500 until config-service is up. Either way the run dies on `Timed out\n * waiting for config.webServer` before a single spec starts. Defaults to the\n * base URL, which is right for an app with no gate.\n */\n readyPath?: string;\n /**\n * What Playwright runs to serve the app, when `next start` alone is not\n * enough.\n *\n * The one caller so far is the storefront, whose reads happen in **server\n * components**: `page.route()` cannot see a fetch the Next process makes, so\n * its `mock` profile launches the server under a `--import` preload that\n * installs msw inside that process instead. Expressed here rather than\n * through `overrides` so the cwd, the readiness URL and the reuse rule stay\n * in one place — an override would have to restate all three to change one.\n *\n * Ignored outside `mock`: a `live` run talks to real services and must not\n * start a faked one.\n */\n mockServerCommand?: string;\n /** Anything else to merge in, for a project with a genuine special case. */\n overrides?: PlaywrightTestConfig;\n}\n\n/**\n * Every browser Playwright can drive.\n *\n * Chromium is the default in **both** profiles. Interception happens through\n * `page.route()`, which behaves the same everywhere, so `mock` would triple the\n * pull-request time to re-assert identical wire traffic; and a normal dev\n * machine has only chromium installed, so a `live` run that insisted on all\n * three failed on a missing engine rather than on the code. Cross-browser\n * rendering is worth checking deliberately, not on every run.\n */\nconst ALL_BROWSERS = [\n { name: 'chromium', use: { ...devices['Desktop Chrome'] } },\n { name: 'firefox', use: { ...devices['Desktop Firefox'] } },\n { name: 'webkit', use: { ...devices['Desktop Safari'] } },\n];\n\nconst CHROMIUM_ONLY = ALL_BROWSERS.slice(0, 1);\n\n/** Opts into firefox and webkit; needs `pnpm exec playwright install` first. */\nconst ALL_BROWSERS_VAR = 'E2E_BROWSERS';\n\n/**\n * The shared Playwright configuration for an entifix app e2e project.\n *\n * The profile decides three things, and specs decide none of them:\n *\n * - **which specs run** — by filename (`*.mock.spec.ts` / `*.live.spec.ts`).\n * Selection by `testIgnore` rather than by an in-spec `test.skip` means a\n * run with the wrong environment fails instead of quietly reporting green.\n * - **the base URL** — the local app in `mock`; in `live` the app is expected\n * to already be running (started with its real backend), so Playwright\n * reuses it rather than racing a second one.\n * - **whether a reused server is acceptable** — `mock` refuses a development\n * one, `live` accepts whatever is there. Enforced by an auto fixture in\n * `defineEntifixE2eTest`, not from here: Playwright loads `globalSetup`\n * through a different module path than the one it uses for the config and the\n * specs, and this package is `\"type\": \"module\"` while an app's\n * `playwright.config.ts` is CJS — a file reached both ways transpiles for one\n * and fails for the other. See `assertExpectedServer`.\n *\n * Browsers are chromium in both profiles unless `E2E_BROWSERS=all`.\n */\nexport const defineEntifixE2eConfig = ({\n configFile,\n appDir,\n port,\n testDir = './src',\n readyPath = '',\n mockServerCommand,\n overrides = {},\n}: EntifixE2eConfigOptions): PlaywrightTestConfig => {\n const mock = isMockProfile();\n const baseURL = process.env['BASE_URL'] ?? `http://localhost:${port}`;\n\n return defineConfig({\n ...nxE2EPreset(configFile, { testDir }),\n // The other profile's specs are not skipped, they are not collected: a\n // spec that cannot run here has nothing to say about this run.\n testIgnore: mock ? '**/*.live.spec.ts' : '**/*.mock.spec.ts',\n // `live` pays for a real sign-in before its first assertion: `seedSession`\n // drives the provider's hosted login for real — three page loads across two\n // origins, each a Next app that hydrates before it will accept a keystroke.\n // Playwright's 30s default is spent on the fixture alone, and the failure it\n // produces points at whatever action was in flight rather than at the clock.\n // `mock` keeps the default: it fabricates the cookie and never leaves the app.\n ...(mock ? {} : { timeout: 90_000 }),\n use: {\n baseURL,\n trace: 'on-first-retry',\n },\n // Playwright starts the server itself, with `next start` rather than\n // `nx run <app>:start`. An nx invocation here is inferred by\n // `@nx/playwright/plugin` as a *continuous task dependency* of `e2e`, and\n // the run then waits on a server that never signals completion — the e2e\n // task never starts. The build the server needs is expressed instead as a\n // plain `dependsOn` on the e2e target.\n webServer: {\n command:\n mock && mockServerCommand !== undefined\n ? mockServerCommand\n : `pnpm exec next start -p ${port}`,\n cwd: join(workspaceRoot, appDir),\n url: `${baseURL}${readyPath}`,\n reuseExistingServer: true,\n },\n projects:\n process.env[ALL_BROWSERS_VAR] === 'all' ? ALL_BROWSERS : CHROMIUM_ONLY,\n ...overrides,\n });\n};\n\n/**\n * Re-exported so a Playwright suite reaches both from this entry point.\n *\n * ⚠️ Not only for convenience. `@nx/enforce-module-boundaries` treats a package\n * that any file in the consuming project loads with a dynamic `import()` as\n * lazy-loaded, and then refuses every *static* import of it — and\n * `marketplace-app-e2e` has one: its msw preload must call `register()` for the\n * resolver hook before it resolves anything, so its imports cannot be hoisted.\n * The rule keys on the specifier, so a `live` spec there can reach\n * `requireLiveUrl` through `/playwright` and not through the root entry.\n */\nexport { requireLiveUrl, resolveE2eProfile };\n"],"names":["join","workspaceRoot","nxE2EPreset","defineConfig","devices","isMockProfile","requireLiveUrl","resolveE2eProfile","ALL_BROWSERS","name","use","CHROMIUM_ONLY","slice","ALL_BROWSERS_VAR","defineEntifixE2eConfig","configFile","appDir","port","testDir","readyPath","mockServerCommand","overrides","process","mock","baseURL","env","testIgnore","timeout","trace","webServer","command","undefined","cwd","url","reuseExistingServer","projects"],"mappings":";AAAA,SAASA,IAAI,QAAQ,YAAY;AAEjC,SAASC,aAAa,QAAQ,aAAa;AAC3C,SAASC,WAAW,QAAQ,wBAAwB;AACpD,SACEC,YAAY,EACZC,OAAO,QAEF,mBAAmB;AAE1B,SACEC,aAAa,EACbC,cAAc,EACdC,iBAAiB,QACZ,wBAAwB;AA4C/B;;;;;;;;;CASC,GACD,MAAMC,eAAe;IACnB;QAAEC,MAAM;QAAYC,KAAK,aAAKN,OAAO,CAAC,iBAAiB;IAAG;IAC1D;QAAEK,MAAM;QAAWC,KAAK,aAAKN,OAAO,CAAC,kBAAkB;IAAG;IAC1D;QAAEK,MAAM;QAAUC,KAAK,aAAKN,OAAO,CAAC,iBAAiB;IAAG;CACzD;AAED,MAAMO,gBAAgBH,aAAaI,KAAK,CAAC,GAAG;AAE5C,8EAA8E,GAC9E,MAAMC,mBAAmB;AAEzB;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,MAAMC,yBAAyB,CAAC,EACrCC,UAAU,EACVC,MAAM,EACNC,IAAI,EACJC,UAAU,OAAO,EACjBC,YAAY,EAAE,EACdC,iBAAiB,EACjBC,YAAY,CAAC,CAAC,EACU;QAERC;IADhB,MAAMC,OAAOlB;IACb,MAAMmB,WAAUF,wBAAAA,QAAQG,GAAG,CAAC,WAAW,YAAvBH,wBAA2B,CAAC,iBAAiB,EAAEL,MAAM;IAErE,OAAOd,aAAa,aACfD,YAAYa,YAAY;QAAEG;IAAQ;QACrC,uEAAuE;QACvE,+DAA+D;QAC/DQ,YAAYH,OAAO,sBAAsB;OAOrCA,OAAO,CAAC,IAAI;QAAEI,SAAS;IAAO;QAClCjB,KAAK;YACHc;YACAI,OAAO;QACT;QACA,qEAAqE;QACrE,6DAA6D;QAC7D,0EAA0E;QAC1E,yEAAyE;QACzE,0EAA0E;QAC1E,uCAAuC;QACvCC,WAAW;YACTC,SACEP,QAAQH,sBAAsBW,YAC1BX,oBACA,CAAC,wBAAwB,EAAEH,MAAM;YACvCe,KAAKhC,KAAKC,eAAee;YACzBiB,KAAK,GAAGT,UAAUL,WAAW;YAC7Be,qBAAqB;QACvB;QACAC,UACEb,QAAQG,GAAG,CAACZ,iBAAiB,KAAK,QAAQL,eAAeG;OACxDU;AAEP,EAAE;AAEF;;;;;;;;;;CAUC,GACD,SAASf,cAAc,EAAEC,iBAAiB,GAAG"}
@@ -0,0 +1,69 @@
1
+ import { type Locator, type Page } from '@playwright/test';
2
+ /** How a filter row is filled in. */
3
+ export interface FilterClause {
4
+ member: string;
5
+ operator: string;
6
+ value: string;
7
+ }
8
+ export interface SortClause {
9
+ member: string;
10
+ direction?: 'asc' | 'desc';
11
+ }
12
+ /**
13
+ * A driver for the `EntityTable` organism: filters, sorting, paging and the
14
+ * rendered rows.
15
+ *
16
+ * Every entity listing in the workspace is the same component, so its selectors
17
+ * belong in one place rather than being re-declared as local helpers in each
18
+ * suite — which is what the two admin specs did, with two different sets of
19
+ * conventions for the same widget.
20
+ *
21
+ * The wide (grid) layout is what is asserted on. Both layouts always render —
22
+ * the pivot is CSS-only, so there is no SSR hydration mismatch — and the table
23
+ * is the one carrying column semantics.
24
+ */
25
+ export declare class EntityTablePage {
26
+ private readonly page;
27
+ constructor(page: Page);
28
+ /** Rows of the wide layout. */
29
+ get rows(): Locator;
30
+ /** Waits until the listing has painted at least one row. */
31
+ waitForRows(): Promise<void>;
32
+ /** Column headers, in render order. */
33
+ headers(): Promise<string[]>;
34
+ /**
35
+ * The values of one column, addressed by its header label rather than by
36
+ * position: a column added to the entity — or reordered by the user's saved
37
+ * preferences — must not silently shift what a spec is asserting on.
38
+ */
39
+ columnValues(header: string): Promise<string[]>;
40
+ /** The distinct values of a column, sorted — the usual assertion subject. */
41
+ distinctColumnValues(header: string): Promise<string[]>;
42
+ openFilters(): Promise<void>;
43
+ /** `and` (default) or `or` across the rows of the panel. */
44
+ matchAny(match: 'and' | 'or'): Promise<void>;
45
+ /**
46
+ * Adds a filter row and fills it in.
47
+ *
48
+ * The member is always selected explicitly, never left at the default: a new
49
+ * row defaults to the entity's *first filterable* member, so a spec relying
50
+ * on it would break the moment a member is declared ahead of that one.
51
+ */
52
+ addFilter({ member, operator, value }: FilterClause): Promise<void>;
53
+ /** Filtering is emitted on Apply, not per keystroke — each emission is a request. */
54
+ applyFilters(): Promise<void>;
55
+ clearFilters(): Promise<void>;
56
+ /** Opens the panel, adds every clause, applies. */
57
+ filterBy(...clauses: FilterClause[]): Promise<void>;
58
+ openSorting(): Promise<void>;
59
+ addSort({ member, direction }: SortClause): Promise<void>;
60
+ applySorting(): Promise<void>;
61
+ /** Opens the panel, adds every term in precedence order, applies. */
62
+ sortBy(...clauses: SortClause[]): Promise<void>;
63
+ /**
64
+ * `exact` matters: Next.js' dev-tools button also matches a loose "Siguiente".
65
+ */
66
+ nextPage(): Promise<void>;
67
+ previousPage(): Promise<void>;
68
+ }
69
+ //# sourceMappingURL=entity-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-table.d.ts","sourceRoot":"","sources":["../../src/playwright/entity-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEnE,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEvC,+BAA+B;IAC/B,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,4DAA4D;IACtD,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlC,uCAAuC;IACjC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIlC;;;;OAIG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAcrD,6EAA6E;IACvE,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAMvD,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAMlC,4DAA4D;IACtD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD;;;;;;OAMG;IACG,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAczE,qFAAqF;IAC/E,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAInC,mDAAmD;IAC7C,QAAQ,CAAC,GAAG,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnD,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,EAAE,MAAM,EAAE,SAAiB,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAajE,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAInC,qEAAqE;IAC/D,MAAM,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAMzB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAKpC"}