@rvoh/psychic-spec-helpers 2.0.0 → 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/src/feature/helpers/launchDevServer.js +1 -1
  3. package/dist/esm/src/feature/helpers/launchPage.js +1 -1
  4. package/dist/esm/src/index.js +3 -4
  5. package/dist/esm/src/unit/OpenapiSpecRequest.js +1 -1
  6. package/dist/esm/src/unit/SpecRequest.js +1 -1
  7. package/dist/esm/src/unit/supersession.js +5 -4
  8. package/dist/types/src/index.d.ts +5 -6
  9. package/package.json +26 -18
  10. package/src/feature/helpers/launchDevServer.ts +1 -1
  11. package/src/feature/helpers/launchPage.ts +1 -1
  12. package/src/index.ts +6 -8
  13. package/src/unit/OpenapiSpecRequest.ts +1 -1
  14. package/src/unit/SpecRequest.ts +1 -1
  15. package/src/unit/supersession.ts +5 -4
  16. package/tsconfig.json +1 -1
  17. package/dist/esm/spec/features/check.spec.js +0 -27
  18. package/dist/esm/spec/features/click.spec.js +0 -12
  19. package/dist/esm/spec/features/clickButton.spec.js +0 -12
  20. package/dist/esm/spec/features/clickLink.spec.js +0 -12
  21. package/dist/esm/spec/features/clickSelector.spec.js +0 -12
  22. package/dist/esm/spec/features/fillIn.spec.js +0 -15
  23. package/dist/esm/spec/features/helpers/getPage.js +0 -10
  24. package/dist/esm/spec/features/matchers/toCheck.spec.js +0 -15
  25. package/dist/esm/spec/features/matchers/toClick.spec.js +0 -13
  26. package/dist/esm/spec/features/matchers/toClickButton.spec.js +0 -12
  27. package/dist/esm/spec/features/matchers/toClickLink.spec.js +0 -12
  28. package/dist/esm/spec/features/matchers/toClickSelector.spec.js +0 -12
  29. package/dist/esm/spec/features/matchers/toFill.spec.js +0 -15
  30. package/dist/esm/spec/features/matchers/toHaveChecked.spec.js +0 -13
  31. package/dist/esm/spec/features/matchers/toHaveLink.spec.js +0 -12
  32. package/dist/esm/spec/features/matchers/toHavePath.spec.js +0 -12
  33. package/dist/esm/spec/features/matchers/toHaveSelector.spec.js +0 -12
  34. package/dist/esm/spec/features/matchers/toHaveUnchecked.spec.js +0 -19
  35. package/dist/esm/spec/features/matchers/toHaveUrl.spec.js +0 -13
  36. package/dist/esm/spec/features/matchers/toMatchTextContent.spec.js +0 -12
  37. package/dist/esm/spec/features/matchers/toNotMatchSelector.spec.js +0 -12
  38. package/dist/esm/spec/features/matchers/toNotMatchTextContent.spec.js +0 -12
  39. package/dist/esm/spec/features/matchers/toSelect.spec.js +0 -12
  40. package/dist/esm/spec/features/matchers/toUncheck.spec.js +0 -20
  41. package/dist/esm/spec/features/select.spec.js +0 -12
  42. package/dist/esm/spec/features/setup/globalSetup.js +0 -8
  43. package/dist/esm/spec/features/setup/hooks.js +0 -36
  44. package/dist/esm/spec/features/uncheck.spec.js +0 -43
  45. package/dist/esm/spec/features/vite.config.js +0 -17
  46. package/dist/esm/spec/helpers/sleep.js +0 -7
  47. package/dist/esm/spec/unit/OpenapiSpecRequest/defaultHeaders.spec.js +0 -31
  48. package/dist/esm/spec/unit/OpenapiSpecRequest/delete.spec.js +0 -42
  49. package/dist/esm/spec/unit/OpenapiSpecRequest/get.spec.js +0 -54
  50. package/dist/esm/spec/unit/OpenapiSpecRequest/patch.spec.js +0 -45
  51. package/dist/esm/spec/unit/OpenapiSpecRequest/post.spec.js +0 -68
  52. package/dist/esm/spec/unit/OpenapiSpecRequest/put.spec.js +0 -32
  53. package/dist/esm/spec/unit/OpenapiSpecRequest/session.spec.js +0 -49
  54. package/dist/esm/spec/unit/OpenapiSpecSession/delete.spec.js +0 -30
  55. package/dist/esm/spec/unit/OpenapiSpecSession/get.spec.js +0 -38
  56. package/dist/esm/spec/unit/OpenapiSpecSession/patch.spec.js +0 -37
  57. package/dist/esm/spec/unit/OpenapiSpecSession/post.spec.js +0 -34
  58. package/dist/esm/spec/unit/OpenapiSpecSession/put.spec.js +0 -37
  59. package/dist/esm/spec/unit/setup/globalSetup.js +0 -3
  60. package/dist/esm/spec/unit/setup/hooks.js +0 -16
  61. package/dist/esm/spec/unit/specRequest/defaultHeaders.spec.js +0 -30
  62. package/dist/esm/spec/unit/specRequest/delete.spec.js +0 -45
  63. package/dist/esm/spec/unit/specRequest/get.spec.js +0 -45
  64. package/dist/esm/spec/unit/specRequest/helpers/fillOpenapiUrlParams.spec.js +0 -11
  65. package/dist/esm/spec/unit/specRequest/patch.spec.js +0 -45
  66. package/dist/esm/spec/unit/specRequest/post.spec.js +0 -45
  67. package/dist/esm/spec/unit/specRequest/put.spec.js +0 -45
  68. package/dist/esm/spec/unit/specRequest/session.spec.js +0 -48
  69. package/dist/esm/spec/unit/vite.config.js +0 -14
  70. package/dist/esm/test-app/client/src/api/openapi.js +0 -5
  71. package/dist/esm/test-app/spec/factories/UserFactory.js +0 -6
  72. package/dist/esm/test-app/spec/unit/models/User.spec.js +0 -4
  73. package/dist/esm/test-app/src/app/controllers/ApplicationController.js +0 -7
  74. package/dist/esm/test-app/src/app/controllers/HeadersController.js +0 -59
  75. package/dist/esm/test-app/src/app/controllers/SpecRequestController.js +0 -103
  76. package/dist/esm/test-app/src/app/controllers/UserController.js +0 -84
  77. package/dist/esm/test-app/src/app/controllers/Users/BalloonsController.js +0 -139
  78. package/dist/esm/test-app/src/app/controllers/Users/BaseController.js +0 -3
  79. package/dist/esm/test-app/src/app/controllers/Users/PostsController.js +0 -101
  80. package/dist/esm/test-app/src/app/controllers/UsersController.js +0 -108
  81. package/dist/esm/test-app/src/app/helpers/importAll.js +0 -3
  82. package/dist/esm/test-app/src/app/helpers/importDefault.js +0 -3
  83. package/dist/esm/test-app/src/app/helpers/srcPath.js +0 -26
  84. package/dist/esm/test-app/src/app/models/ApplicationModel.js +0 -14
  85. package/dist/esm/test-app/src/app/models/Balloon.js +0 -67
  86. package/dist/esm/test-app/src/app/models/User.js +0 -70
  87. package/dist/esm/test-app/src/app/serializers/BalloonSerializer.js +0 -4
  88. package/dist/esm/test-app/src/app/serializers/UserSerializer.js +0 -4
  89. package/dist/esm/test-app/src/cli/helpers/initializePsychicApp.js +0 -7
  90. package/dist/esm/test-app/src/cli/index.js +0 -16
  91. package/dist/esm/test-app/src/conf/app.js +0 -49
  92. package/dist/esm/test-app/src/conf/dream.js +0 -31
  93. package/dist/esm/test-app/src/conf/global.js +0 -1
  94. package/dist/esm/test-app/src/conf/inflections.js +0 -4
  95. package/dist/esm/test-app/src/conf/loadEnv.js +0 -3
  96. package/dist/esm/test-app/src/conf/repl.js +0 -11
  97. package/dist/esm/test-app/src/conf/routeTypes.js +0 -1
  98. package/dist/esm/test-app/src/conf/routes.js +0 -28
  99. package/dist/esm/test-app/src/db/migrations/1737751561543-user.js +0 -14
  100. package/dist/esm/test-app/src/db/migrations/1760239324666-create-balloon.js +0 -18
  101. package/dist/esm/test-app/src/db/seed.js +0 -1
  102. package/dist/esm/test-app/src/types/db.js +0 -9
  103. package/dist/esm/test-app/src/types/dream.globals.js +0 -8
  104. package/dist/esm/test-app/src/types/dream.js +0 -195
  105. package/dist/esm/test-app/src/types/psychic.js +0 -8
  106. package/dist/types/spec/features/check.spec.d.ts +0 -1
  107. package/dist/types/spec/features/click.spec.d.ts +0 -1
  108. package/dist/types/spec/features/clickButton.spec.d.ts +0 -1
  109. package/dist/types/spec/features/clickLink.spec.d.ts +0 -1
  110. package/dist/types/spec/features/clickSelector.spec.d.ts +0 -1
  111. package/dist/types/spec/features/fillIn.spec.d.ts +0 -1
  112. package/dist/types/spec/features/helpers/getPage.d.ts +0 -2
  113. package/dist/types/spec/features/matchers/toCheck.spec.d.ts +0 -1
  114. package/dist/types/spec/features/matchers/toClick.spec.d.ts +0 -1
  115. package/dist/types/spec/features/matchers/toClickButton.spec.d.ts +0 -1
  116. package/dist/types/spec/features/matchers/toClickLink.spec.d.ts +0 -1
  117. package/dist/types/spec/features/matchers/toClickSelector.spec.d.ts +0 -1
  118. package/dist/types/spec/features/matchers/toFill.spec.d.ts +0 -1
  119. package/dist/types/spec/features/matchers/toHaveChecked.spec.d.ts +0 -1
  120. package/dist/types/spec/features/matchers/toHaveLink.spec.d.ts +0 -1
  121. package/dist/types/spec/features/matchers/toHavePath.spec.d.ts +0 -1
  122. package/dist/types/spec/features/matchers/toHaveSelector.spec.d.ts +0 -1
  123. package/dist/types/spec/features/matchers/toHaveUnchecked.spec.d.ts +0 -1
  124. package/dist/types/spec/features/matchers/toHaveUrl.spec.d.ts +0 -1
  125. package/dist/types/spec/features/matchers/toMatchTextContent.spec.d.ts +0 -1
  126. package/dist/types/spec/features/matchers/toNotMatchSelector.spec.d.ts +0 -1
  127. package/dist/types/spec/features/matchers/toNotMatchTextContent.spec.d.ts +0 -1
  128. package/dist/types/spec/features/matchers/toSelect.spec.d.ts +0 -1
  129. package/dist/types/spec/features/matchers/toUncheck.spec.d.ts +0 -1
  130. package/dist/types/spec/features/select.spec.d.ts +0 -1
  131. package/dist/types/spec/features/setup/globalSetup.d.ts +0 -3
  132. package/dist/types/spec/features/setup/hooks.d.ts +0 -1
  133. package/dist/types/spec/features/uncheck.spec.d.ts +0 -1
  134. package/dist/types/spec/features/vite.config.d.ts +0 -2
  135. package/dist/types/spec/helpers/sleep.d.ts +0 -1
  136. package/dist/types/spec/unit/OpenapiSpecRequest/defaultHeaders.spec.d.ts +0 -1
  137. package/dist/types/spec/unit/OpenapiSpecRequest/delete.spec.d.ts +0 -1
  138. package/dist/types/spec/unit/OpenapiSpecRequest/get.spec.d.ts +0 -1
  139. package/dist/types/spec/unit/OpenapiSpecRequest/patch.spec.d.ts +0 -1
  140. package/dist/types/spec/unit/OpenapiSpecRequest/post.spec.d.ts +0 -1
  141. package/dist/types/spec/unit/OpenapiSpecRequest/put.spec.d.ts +0 -1
  142. package/dist/types/spec/unit/OpenapiSpecRequest/session.spec.d.ts +0 -1
  143. package/dist/types/spec/unit/OpenapiSpecSession/delete.spec.d.ts +0 -1
  144. package/dist/types/spec/unit/OpenapiSpecSession/get.spec.d.ts +0 -1
  145. package/dist/types/spec/unit/OpenapiSpecSession/patch.spec.d.ts +0 -1
  146. package/dist/types/spec/unit/OpenapiSpecSession/post.spec.d.ts +0 -1
  147. package/dist/types/spec/unit/OpenapiSpecSession/put.spec.d.ts +0 -1
  148. package/dist/types/spec/unit/setup/globalSetup.d.ts +0 -3
  149. package/dist/types/spec/unit/setup/hooks.d.ts +0 -1
  150. package/dist/types/spec/unit/specRequest/defaultHeaders.spec.d.ts +0 -1
  151. package/dist/types/spec/unit/specRequest/delete.spec.d.ts +0 -1
  152. package/dist/types/spec/unit/specRequest/get.spec.d.ts +0 -1
  153. package/dist/types/spec/unit/specRequest/helpers/fillOpenapiUrlParams.spec.d.ts +0 -1
  154. package/dist/types/spec/unit/specRequest/patch.spec.d.ts +0 -1
  155. package/dist/types/spec/unit/specRequest/post.spec.d.ts +0 -1
  156. package/dist/types/spec/unit/specRequest/put.spec.d.ts +0 -1
  157. package/dist/types/spec/unit/specRequest/session.spec.d.ts +0 -1
  158. package/dist/types/spec/unit/vite.config.d.ts +0 -2
  159. package/dist/types/test-app/client/src/api/openapi.d.ts +0 -81
  160. package/dist/types/test-app/spec/factories/UserFactory.d.ts +0 -3
  161. package/dist/types/test-app/spec/unit/models/User.spec.d.ts +0 -1
  162. package/dist/types/test-app/src/app/controllers/ApplicationController.d.ts +0 -6
  163. package/dist/types/test-app/src/app/controllers/HeadersController.d.ts +0 -4
  164. package/dist/types/test-app/src/app/controllers/SpecRequestController.d.ts +0 -10
  165. package/dist/types/test-app/src/app/controllers/UserController.d.ts +0 -8
  166. package/dist/types/test-app/src/app/controllers/Users/BalloonsController.d.ts +0 -11
  167. package/dist/types/test-app/src/app/controllers/Users/BaseController.d.ts +0 -3
  168. package/dist/types/test-app/src/app/controllers/Users/PostsController.d.ts +0 -10
  169. package/dist/types/test-app/src/app/controllers/UsersController.d.ts +0 -9
  170. package/dist/types/test-app/src/app/helpers/importAll.d.ts +0 -1
  171. package/dist/types/test-app/src/app/helpers/importDefault.d.ts +0 -1
  172. package/dist/types/test-app/src/app/helpers/srcPath.d.ts +0 -1
  173. package/dist/types/test-app/src/app/models/ApplicationModel.d.ts +0 -145
  174. package/dist/types/test-app/src/app/models/Balloon.d.ts +0 -13
  175. package/dist/types/test-app/src/app/models/User.d.ts +0 -12
  176. package/dist/types/test-app/src/app/serializers/BalloonSerializer.d.ts +0 -3
  177. package/dist/types/test-app/src/app/serializers/UserSerializer.d.ts +0 -3
  178. package/dist/types/test-app/src/cli/helpers/initializePsychicApp.d.ts +0 -4
  179. package/dist/types/test-app/src/cli/index.d.ts +0 -2
  180. package/dist/types/test-app/src/conf/app.d.ts +0 -3
  181. package/dist/types/test-app/src/conf/dream.d.ts +0 -2
  182. package/dist/types/test-app/src/conf/global.d.ts +0 -1
  183. package/dist/types/test-app/src/conf/inflections.d.ts +0 -1
  184. package/dist/types/test-app/src/conf/loadEnv.d.ts +0 -2
  185. package/dist/types/test-app/src/conf/repl.d.ts +0 -3
  186. package/dist/types/test-app/src/conf/routeTypes.d.ts +0 -1
  187. package/dist/types/test-app/src/conf/routes.d.ts +0 -3
  188. package/dist/types/test-app/src/db/migrations/1737751561543-user.d.ts +0 -3
  189. package/dist/types/test-app/src/db/migrations/1760239324666-create-balloon.d.ts +0 -3
  190. package/dist/types/test-app/src/db/seed.d.ts +0 -1
  191. package/dist/types/test-app/src/types/db.d.ts +0 -32
  192. package/dist/types/test-app/src/types/dream.d.ts +0 -139
  193. package/dist/types/test-app/src/types/dream.globals.d.ts +0 -3
  194. package/dist/types/test-app/src/types/psychic.d.ts +0 -4
package/README.md CHANGED
@@ -7,7 +7,7 @@ This repo provides spec helpers to be used in conjunction with the [psychic web
7
7
  1. Add this repo as a dev dependency in your psychic project (this is done by default for psychic apps, but worth mentioning in case it has been removed from your repo).
8
8
 
9
9
  ```bash
10
- yarn add --dev @rvoh/psychic-spec-helpers
10
+ pnpm add --dev @rvoh/psychic-spec-helpers
11
11
  ```
12
12
 
13
13
  2. import psychic spec helpers in your jest setup. This is automatically set up when provisioning a new psychic app, so you should only need to do this with an a-typical setup.
@@ -2,7 +2,7 @@ import { spawn } from 'child_process';
2
2
  import { createServer } from 'net';
3
3
  import sleep from '../../shared/sleep.js';
4
4
  const devServerProcesses = {};
5
- export default async function launchDevServer(key, { port = 3000, cmd = 'yarn client', timeout = 5000, } = {}) {
5
+ export default async function launchDevServer(key, { port = 3000, cmd = 'pnpm client', timeout = 5000, } = {}) {
6
6
  if (devServerProcesses[key])
7
7
  return;
8
8
  if (process.env.DEBUG === '1')
@@ -1,5 +1,5 @@
1
1
  import launchBrowser from './launchBrowser.js';
2
2
  export default async function launchPage(opts) {
3
3
  const browser = await launchBrowser(opts);
4
- return browser.newPage();
4
+ return await browser.newPage();
5
5
  }
@@ -1,14 +1,13 @@
1
1
  // unit spec helpers
2
- export { default as specRequest } from './unit/SpecRequest.js';
3
2
  export { default as createPsychicServer } from './unit/createPsychicServer.js';
4
3
  export { OpenapiSpecRequest } from './unit/OpenapiSpecRequest.js';
5
4
  export { OpenapiSpecSession } from './unit/OpenapiSpecSession.js';
6
- export { SpecRequest } from './unit/SpecRequest.js';
5
+ export { default as specRequest, SpecRequest } from './unit/SpecRequest.js';
7
6
  export { SpecSession } from './unit/SpecSession.js';
8
7
  // feature spec helpers
9
- export { default as providePuppeteerViteMatchers } from './feature/helpers/providePuppeteerViteMatchers.js';
10
8
  export { default as launchBrowser } from './feature/helpers/launchBrowser.js';
9
+ export { default as launchDevServer, stopDevServer, stopDevServers, } from './feature/helpers/launchDevServer.js';
11
10
  export { default as launchPage } from './feature/helpers/launchPage.js';
12
- export { default as launchDevServer, stopDevServers, stopDevServer, } from './feature/helpers/launchDevServer.js';
11
+ export { default as providePuppeteerViteMatchers } from './feature/helpers/providePuppeteerViteMatchers.js';
13
12
  export { default as visit } from './feature/helpers/visit.js';
14
13
  export default {};
@@ -405,7 +405,7 @@ export class OpenapiSpecRequest {
405
405
  process.env.PSYCHIC_EXPECTING_INTERNAL_SERVER_ERROR = '1';
406
406
  }
407
407
  // eslint-disable-next-line
408
- const req = supertest.agent(this.server.expressApp);
408
+ const req = supertest.agent(this.server.koaApp.callback());
409
409
  let request = req[method](`/${uri.replace(/^\//, '')}`);
410
410
  request = request.set({ ...this._defaultHeaders, ...opts.headers });
411
411
  if (opts.query)
@@ -74,7 +74,7 @@ export class SpecRequest {
74
74
  process.env.PSYCHIC_EXPECTING_INTERNAL_SERVER_ERROR = '1';
75
75
  }
76
76
  // eslint-disable-next-line
77
- const req = supertest.agent(this.server.expressApp);
77
+ const req = supertest.agent(this.server.koaApp.callback());
78
78
  let request = req[method](`/${uri.replace(/^\//, '')}`);
79
79
  request = request.set({ ...this._defaultHeaders, ...opts.headers });
80
80
  if (opts.query)
@@ -13,13 +13,14 @@ class Supersession {
13
13
  server, options = {}) {
14
14
  this.options = options;
15
15
  // eslint-disable-next-line
16
- if (!server.expressApp) {
17
- throw new Error('Supersession requires an `app`');
16
+ if (!server.koaApp) {
17
+ throw new Error('Supersession requires a Koa `app`');
18
18
  }
19
19
  // eslint-disable-next-line
20
- this.agent = request.agent(server.expressApp, options);
20
+ const callback = server.koaApp.callback();
21
+ this.agent = request.agent(callback, options);
21
22
  // eslint-disable-next-line
22
- const app = http.createServer(server.expressApp);
23
+ const app = http.createServer(callback);
23
24
  // eslint-disable-next-line
24
25
  const url = request.Test.prototype.serverAddress(app, '/');
25
26
  this.app = app;
@@ -1,19 +1,18 @@
1
- import { ExpectToEvaluateOpts } from './feature/internal/evaluateWithRetryAndTimeout.js';
2
- import { CustomMatcherResult } from './feature/helpers/providePuppeteerViteMatchers.js';
3
1
  import { Page, WaitForSelectorOptions } from 'puppeteer';
2
+ import { CustomMatcherResult } from './feature/helpers/providePuppeteerViteMatchers.js';
3
+ import { ExpectToEvaluateOpts } from './feature/internal/evaluateWithRetryAndTimeout.js';
4
4
  import { ToFillMatcherOpts } from './feature/matchers/toFill.js';
5
5
  export { RequestBody as OpenapiRequestBody, RequestQueryParameters as OpenapiRequestQuery, ResponseBody as OpenapiResponseBody, ResponseCodeForUri as OpenapiResponseCodeForUri, } from './unit/helpers/openapiTypeHelpers.js';
6
6
  export { DreamRequestAttributes } from './unit/helpers/typeHelpers.js';
7
- export { default as specRequest } from './unit/SpecRequest.js';
8
7
  export { default as createPsychicServer } from './unit/createPsychicServer.js';
9
8
  export { OpenapiSpecRequest } from './unit/OpenapiSpecRequest.js';
10
9
  export { OpenapiSpecSession } from './unit/OpenapiSpecSession.js';
11
- export { SpecRequest } from './unit/SpecRequest.js';
10
+ export { default as specRequest, SpecRequest } from './unit/SpecRequest.js';
12
11
  export { SpecSession } from './unit/SpecSession.js';
13
- export { default as providePuppeteerViteMatchers } from './feature/helpers/providePuppeteerViteMatchers.js';
14
12
  export { default as launchBrowser } from './feature/helpers/launchBrowser.js';
13
+ export { default as launchDevServer, stopDevServer, stopDevServers, } from './feature/helpers/launchDevServer.js';
15
14
  export { default as launchPage } from './feature/helpers/launchPage.js';
16
- export { default as launchDevServer, stopDevServers, stopDevServer, } from './feature/helpers/launchDevServer.js';
15
+ export { default as providePuppeteerViteMatchers } from './feature/helpers/providePuppeteerViteMatchers.js';
17
16
  export { default as visit } from './feature/helpers/visit.js';
18
17
  declare global {
19
18
  const context: (typeof import('vitest'))['describe'];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@rvoh/psychic-spec-helpers",
4
- "version": "2.0.0",
4
+ "version": "3.0.0-alpha.1",
5
5
  "description": "psychic framework spec helpers",
6
6
  "author": "RVO Health",
7
7
  "repository": {
@@ -24,21 +24,20 @@
24
24
  "dist/**/*"
25
25
  ],
26
26
  "scripts": {
27
- "client": "VITE_PSYCHIC_ENV=development yarn --cwd=./client dev",
28
- "client:fspec": "BROWSER=none VITE_PSYCHIC_ENV=test yarn --cwd=./client dev --port 3000",
27
+ "client": "cd client && VITE_PSYCHIC_ENV=development pnpm dev",
28
+ "client:fspec": "cd client && BROWSER=none VITE_PSYCHIC_ENV=test pnpm dev --port 3000",
29
29
  "psy": "NODE_ENV=${NODE_ENV:-test} tsx test-app/src/cli/index.ts",
30
30
  "uspec": "vitest --config ./spec/unit/vite.config.ts",
31
31
  "fspec": "vitest --config ./spec/features/vite.config.ts",
32
32
  "build": "echo \"building psychic-spec-helpers...\" && rm -rf dist && npx tsc -p ./tsconfig.json",
33
33
  "build:test-app": "rm -rf dist && echo \"building test app to esm...\" && npx tsc -p ./tsconfig.esm.build.test-app.json && echo \"building test app to cjs...\" && npx tsc -p ./tsconfig.cjs.build.test-app.json",
34
- "lint": "yarn run eslint --no-warn-ignored \"src/**/*.ts\" \"spec/**/*.ts\" && yarn run prettier . --check",
35
- "format": "yarn run prettier . --write",
36
- "prepack": "yarn build"
34
+ "lint": "pnpm eslint --no-warn-ignored \"src/**/*.ts\" \"spec/**/*.ts\" && pnpm prettier . --check",
35
+ "format": "pnpm prettier . --write",
36
+ "prepack": "pnpm build"
37
37
  },
38
- "packageManager": "yarn@4.4.1",
39
38
  "peerDependencies": {
40
39
  "@rvoh/dream": "*",
41
- "@rvoh/psychic": "*",
40
+ "@rvoh/psychic": "^3.0.0",
42
41
  "@types/node": "*",
43
42
  "@types/supertest": "*",
44
43
  "puppeteer": "*",
@@ -47,31 +46,40 @@
47
46
  },
48
47
  "devDependencies": {
49
48
  "@eslint/js": "=9.0.0",
49
+ "@koa/cors": "^5.0.0",
50
+ "@koa/router": "^15.3.0",
50
51
  "@rvoh/dream": "^2.0.0",
51
52
  "@rvoh/dream-spec-helpers": "^2.0.0",
52
- "@rvoh/psychic": "^2.0.0",
53
+ "@rvoh/psychic": "^3.0.0",
53
54
  "@types/cookiejar": "^2",
54
- "@types/express": "^4",
55
55
  "@types/node": "^22.5.1",
56
56
  "@types/pg": "^8",
57
57
  "@types/supertest": "^6.0.3",
58
- "eslint": "^9.9.1",
59
- "express": "^4.21.2",
58
+ "@typescript-eslint/parser": "^8.48.1",
59
+ "eslint": "^9.39.1",
60
+ "globals": "^16.5.0",
61
+ "koa-bodyparser": "^4.4.1",
62
+ "koa-conditional-get": "^3.0.0",
63
+ "koa-etag": "^5.0.0",
60
64
  "kysely": "^0.28.5",
61
- "kysely-codegen": "~0.17.0",
65
+ "kysely-codegen": "~0.19.0",
62
66
  "luxon-jest-matchers": "^0.1.14",
63
- "openapi-typescript": "^7.8.0",
67
+ "openapi-typescript": "^7.10.1",
64
68
  "pg": "^8.13.1",
65
69
  "prettier": "^3.5.3",
66
70
  "puppeteer": "^24.25.0",
67
71
  "supertest": "^7.1.4",
68
72
  "ts-node": "^10.9.2",
69
- "tsx": "^4.19.3",
73
+ "tsx": "^4.20.6",
70
74
  "typescript": "^5.5.4",
71
- "typescript-eslint": "^8.30.1",
75
+ "typescript-eslint": "^8.48.1",
72
76
  "vitest": "^4.0.10"
73
77
  },
74
78
  "dependencies": {
75
- "cookiejar": "^2.1.4"
76
- }
79
+ "commander": "^14.0.2",
80
+ "cookiejar": "^2.1.4",
81
+ "dotenv": "^17.2.3",
82
+ "pluralize-esm": "^9.0.5"
83
+ },
84
+ "packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a"
77
85
  }
@@ -8,7 +8,7 @@ export default async function launchDevServer(
8
8
  key: string,
9
9
  {
10
10
  port = 3000,
11
- cmd = 'yarn client',
11
+ cmd = 'pnpm client',
12
12
  timeout = 5000,
13
13
  }: { port?: number; cmd?: string; timeout?: number } = {}
14
14
  ) {
@@ -3,5 +3,5 @@ import launchBrowser from './launchBrowser.js'
3
3
 
4
4
  export default async function launchPage(opts?: LaunchOptions) {
5
5
  const browser = await launchBrowser(opts)
6
- return browser.newPage()
6
+ return await browser.newPage()
7
7
  }
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { ExpectToEvaluateOpts } from './feature/internal/evaluateWithRetryAndTimeout.js'
2
- import { CustomMatcherResult } from './feature/helpers/providePuppeteerViteMatchers.js'
3
1
  import { Page, WaitForSelectorOptions } from 'puppeteer'
2
+ import { CustomMatcherResult } from './feature/helpers/providePuppeteerViteMatchers.js'
3
+ import { ExpectToEvaluateOpts } from './feature/internal/evaluateWithRetryAndTimeout.js'
4
4
  import { ToFillMatcherOpts } from './feature/matchers/toFill.js'
5
5
  export {
6
6
  RequestBody as OpenapiRequestBody,
@@ -13,26 +13,24 @@ export {
13
13
  export { DreamRequestAttributes } from './unit/helpers/typeHelpers.js'
14
14
 
15
15
  // unit spec helpers
16
- export { default as specRequest } from './unit/SpecRequest.js'
17
16
  export { default as createPsychicServer } from './unit/createPsychicServer.js'
18
17
  export { OpenapiSpecRequest } from './unit/OpenapiSpecRequest.js'
19
18
  export { OpenapiSpecSession } from './unit/OpenapiSpecSession.js'
20
- export { SpecRequest } from './unit/SpecRequest.js'
19
+ export { default as specRequest, SpecRequest } from './unit/SpecRequest.js'
21
20
  export { SpecSession } from './unit/SpecSession.js'
22
21
 
23
22
  // feature spec helpers
24
- export { default as providePuppeteerViteMatchers } from './feature/helpers/providePuppeteerViteMatchers.js'
25
23
  export { default as launchBrowser } from './feature/helpers/launchBrowser.js'
26
- export { default as launchPage } from './feature/helpers/launchPage.js'
27
24
  export {
28
25
  default as launchDevServer,
29
- stopDevServers,
30
26
  stopDevServer,
27
+ stopDevServers,
31
28
  } from './feature/helpers/launchDevServer.js'
29
+ export { default as launchPage } from './feature/helpers/launchPage.js'
30
+ export { default as providePuppeteerViteMatchers } from './feature/helpers/providePuppeteerViteMatchers.js'
32
31
  export { default as visit } from './feature/helpers/visit.js'
33
32
 
34
33
  declare global {
35
- // @ts-expect-error context redefined
36
34
  const context: (typeof import('vitest'))['describe']
37
35
 
38
36
  const page: InstanceType<typeof Page>
@@ -567,7 +567,7 @@ export class OpenapiSpecRequest<OpenapiPaths = undefined> {
567
567
  }
568
568
 
569
569
  // eslint-disable-next-line
570
- const req = supertest.agent(this.server.expressApp)
570
+ const req = supertest.agent(this.server.koaApp.callback())
571
571
  let request = req[method](`/${uri.replace(/^\//, '')}`)
572
572
  request = request.set({ ...this._defaultHeaders, ...opts.headers })
573
573
  if (opts.query) request = request.query(opts.query)
@@ -120,7 +120,7 @@ export class SpecRequest {
120
120
  }
121
121
 
122
122
  // eslint-disable-next-line
123
- const req = supertest.agent(this.server.expressApp)
123
+ const req = supertest.agent(this.server.koaApp.callback())
124
124
  let request = req[method](`/${uri.replace(/^\//, '')}`)
125
125
  request = request.set({ ...this._defaultHeaders, ...opts.headers })
126
126
  if (opts.query) request = request.query(opts.query)
@@ -22,15 +22,16 @@ class Supersession {
22
22
  private options: AgentOptions = {}
23
23
  ) {
24
24
  // eslint-disable-next-line
25
- if (!server.expressApp) {
26
- throw new Error('Supersession requires an `app`')
25
+ if (!server.koaApp) {
26
+ throw new Error('Supersession requires a Koa `app`')
27
27
  }
28
28
 
29
29
  // eslint-disable-next-line
30
- this.agent = request.agent(server.expressApp, options)
30
+ const callback = server.koaApp.callback()
31
+ this.agent = request.agent(callback, options)
31
32
 
32
33
  // eslint-disable-next-line
33
- const app = http.createServer(server.expressApp)
34
+ const app = http.createServer(callback)
34
35
  // eslint-disable-next-line
35
36
  const url = (request as any).Test.prototype.serverAddress(app, '/')
36
37
 
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "extends": "./tsconfig.esm.build.json",
3
- "include": ["src/**/*", "test-app/**/*", "spec/**/*"],
3
+ "include": ["src/**/*"],
4
4
  "compilerOptions": {
5
5
  "types": ["vitest/globals"]
6
6
  }
@@ -1,27 +0,0 @@
1
- describe('check', () => {
2
- it('succeeds when label for checkbox is found', async () => {
3
- await check('My checkbox');
4
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
5
- const inputValue = await page.$eval('#my-checkbox', input => input.checked).catch(() => null);
6
- expect(inputValue).toBe(true);
7
- });
8
- it('fails when the selector is not found', async () => {
9
- await check('My checkbox', { timeout: 500 });
10
- await expect(async () => {
11
- await check('not found checkbox', { timeout: 500 });
12
- }).rejects.toThrow();
13
- });
14
- it('fails when the label points to an invalid input', async () => {
15
- await check('My checkbox', { timeout: 500 });
16
- await expect(async () => {
17
- await check('My invalid label pointer checkbox', { timeout: 500 });
18
- }).rejects.toThrow();
19
- });
20
- it('fails when the label points to a label with a missing htmlFor statement', async () => {
21
- await check('My checkbox', { timeout: 500 });
22
- await expect(async () => {
23
- await check('My missing htmlFor checkbox', { timeout: 500 });
24
- }).rejects.toThrow();
25
- });
26
- });
27
- export {};
@@ -1,12 +0,0 @@
1
- describe('click', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await click('My div');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await click('My div', { timeout: 500 });
7
- await expect(async () => {
8
- await click('Not found div', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('clickButton', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await clickButton('My button');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await clickButton('My button', { timeout: 500 });
7
- await expect(async () => {
8
- await clickButton('Not found button', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('clickLink', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await clickLink('My link');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await clickLink('My link', { timeout: 500 });
7
- await expect(async () => {
8
- await clickLink('Not found link', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('clickSelector', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await clickSelector('#my-button');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await clickSelector('#my-button', { timeout: 500 });
7
- await expect(async () => {
8
- await clickSelector('#not-found', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,15 +0,0 @@
1
- describe('fillIn', () => {
2
- it('succeeds when the input is fillable', async () => {
3
- await fillIn('#my-input', 'hello');
4
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
5
- const inputValue = await page.$eval('#my-input', input => input.value).catch(() => null);
6
- expect(inputValue).toEqual('hello');
7
- });
8
- it('fails when the selector is not found', async () => {
9
- await fillIn('#my-input', 'hello world', { timeout: 500 });
10
- await expect(async () => {
11
- await fillIn('#not-found-input', 'hello world', { timeout: 500 });
12
- }).rejects.toThrow();
13
- });
14
- });
15
- export {};
@@ -1,10 +0,0 @@
1
- import { launchPage } from '../../../src/index.js';
2
- let page;
3
- export default async function getPage(opts) {
4
- if (!page) {
5
- page = await launchPage({ headless: process.env.HEADLESS !== '0', timeout: 20000, ...opts });
6
- // set the browser dimensions prior to running specs
7
- await page.setViewport({ width: 1200, height: 800 });
8
- }
9
- return page;
10
- }
@@ -1,15 +0,0 @@
1
- describe('toCheck', () => {
2
- it('succeeds when label for checkbox is found', async () => {
3
- await expect(page).toCheck('My checkbox');
4
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
5
- const inputValue = await page.$eval('#my-checkbox', input => input.checked).catch(() => null);
6
- expect(inputValue).toBe(true);
7
- });
8
- it('fails when the selector is not found', async () => {
9
- await expect(page).toCheck('My checkbox', { timeout: 500 });
10
- await expect(async () => {
11
- await expect(page).toCheck('not found checkbox', { timeout: 500 });
12
- }).rejects.toThrow();
13
- });
14
- });
15
- export {};
@@ -1,13 +0,0 @@
1
- describe('toClick', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await expect(page).toClick('My div');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await click('My div', { timeout: 500 });
7
- await expect(page).toClick('My div', { timeout: 500 });
8
- await expect(async () => {
9
- await expect(page).toClick('Not found div', { timeout: 500 });
10
- }).rejects.toThrow();
11
- });
12
- });
13
- export {};
@@ -1,12 +0,0 @@
1
- describe('toClickButton', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await expect(page).toClickButton('My button');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await expect(page).toClickButton('My button', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toClickButton('Not found button', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('clickLink', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await expect(page).toClickLink('My link');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await expect(page).toClickLink('My link', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toClickLink('Not found link', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('toClickSelector', () => {
2
- it('succeeds when the selector is found', async () => {
3
- await expect(page).toClickSelector('#my-button');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await expect(page).toClickSelector('#my-button', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toClickSelector('#not-found', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,15 +0,0 @@
1
- describe('toFill', () => {
2
- it('succeeds when the input is fillable', async () => {
3
- await expect(page).toFill('#my-input', 'hello');
4
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
5
- const inputValue = await page.$eval('#my-input', input => input.value).catch(() => null);
6
- expect(inputValue).toEqual('hello');
7
- });
8
- it('fails when the selector is not found', async () => {
9
- await expect(page).toFill('#my-input', 'hello world', { timeout: 500 });
10
- await expect(async () => {
11
- await expect(page).toFill('#not-found-input', 'hello world', { timeout: 500 });
12
- }).rejects.toThrow();
13
- });
14
- });
15
- export {};
@@ -1,13 +0,0 @@
1
- describe('toHaveChecked', () => {
2
- it('succeeds when label for checkbox is found', async () => {
3
- await check('My checkbox');
4
- await expect(page).toHaveChecked('My checkbox');
5
- });
6
- it('fails when the selector is not found', async () => {
7
- await check('My checkbox', { timeout: 500 });
8
- await expect(async () => {
9
- await expect(page).toHaveChecked('not found checkbox', { timeout: 500 });
10
- }).rejects.toThrow();
11
- });
12
- });
13
- export {};
@@ -1,12 +0,0 @@
1
- describe('toHaveLink', () => {
2
- it('succeeds when link with text is found', async () => {
3
- await expect(page).toHaveLink('My link');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await expect(page).toHaveLink('My link', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toHaveLink('not found link', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('toHavePath', () => {
2
- it('succeeds when the path is correct', async () => {
3
- await expect(page).toHavePath('/');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await expect(page).toHavePath('/', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toHavePath('/not-found', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('toHavePath', () => {
2
- it('succeeds when the path is correct', async () => {
3
- await expect(page).toHaveSelector('#my-button');
4
- });
5
- it('fails when the selector is not found', async () => {
6
- await expect(page).toHaveSelector('#my-button', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toHaveSelector('#not-found-button', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,19 +0,0 @@
1
- describe('toHaveUnchecked', () => {
2
- it('succeeds when the input is unchecked', async () => {
3
- await expect(page).toHaveUnchecked('My checkbox');
4
- });
5
- it('fails when the input is checked', async () => {
6
- await expect(page).toHaveUnchecked('My checkbox');
7
- await expect(async () => {
8
- await check('My checkbox');
9
- await expect(page).toHaveUnchecked('My checkbox');
10
- }).rejects.toThrow();
11
- });
12
- it('fails when the input is not found', async () => {
13
- await check('My checkbox');
14
- await expect(async () => {
15
- await expect(page).toHaveUnchecked('not found checkbox', { timeout: 3000 });
16
- }).rejects.toThrow();
17
- });
18
- });
19
- export {};
@@ -1,13 +0,0 @@
1
- describe('toHaveUrl', () => {
2
- it('succeeds when the page matches the url', async () => {
3
- await expect(page).toHaveUrl('http://localhost:3000/');
4
- await expect(page).toHaveUrl('http://localhost:3000');
5
- });
6
- it('fails when the page does not match the url', async () => {
7
- await expect(page).toHaveUrl('http://localhost:3000/', { timeout: 500 });
8
- await expect(async () => {
9
- await expect(page).toHaveUrl('http://localhost:3000/not-here', { timeout: 500 });
10
- }).rejects.toThrow();
11
- });
12
- });
13
- export {};
@@ -1,12 +0,0 @@
1
- describe('toMatchTextContent', () => {
2
- it('succeeds when the page matches the content', async () => {
3
- await expect(page).toMatchTextContent('My div');
4
- });
5
- it('fails when the page does not match the content', async () => {
6
- await expect(page).toMatchTextContent('My div', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toMatchTextContent('not found div', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};
@@ -1,12 +0,0 @@
1
- describe('toNotHaveSelector', () => {
2
- it('succeeds when the page does not match the selector', async () => {
3
- await expect(page).toNotHaveSelector('#not-found-selector', { timeout: 300 });
4
- });
5
- it('fails when the page does match the selector', async () => {
6
- await expect(page).toNotHaveSelector('#not-found-selector', { timeout: 500 });
7
- await expect(async () => {
8
- await expect(page).toNotHaveSelector('#my-div', { timeout: 500 });
9
- }).rejects.toThrow();
10
- });
11
- });
12
- export {};