@stone-js/starters 0.8.8 → 0.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/basic-react-declarative/app/Application.tsx +0 -2
- package/basic-react-declarative/package.json +7 -7
- package/basic-react-declarative/public/favicon.svg +16 -0
- package/basic-react-declarative/tests/Application.spec.ts +25 -100
- package/basic-react-imperative/app/Application.tsx +2 -17
- package/basic-react-imperative/package.json +7 -7
- package/basic-react-imperative/public/favicon.svg +16 -0
- package/basic-react-imperative/tests/Application.spec.ts +25 -86
- package/basic-service-declarative/app/Application.ts +0 -2
- package/basic-service-declarative/package.json +6 -6
- package/basic-service-declarative/tests/Application.spec.ts +20 -53
- package/basic-service-imperative/app/Application.ts +2 -14
- package/basic-service-imperative/package.json +6 -6
- package/basic-service-imperative/tests/Application.spec.ts +19 -44
- package/continuum-showcase/package.json +11 -10
- package/continuum-showcase/public/favicon.svg +16 -0
- package/continuum-showcase/stone.config.mjs +2 -2
- package/continuum-showcase/tests/application.spec.ts +30 -0
- package/full-react-declarative/app/Application.ts +0 -4
- package/full-react-declarative/package.json +12 -12
- package/full-react-declarative/public/favicon.svg +16 -0
- package/full-react-declarative/stone.config.mjs +2 -2
- package/full-react-declarative/tests/application.spec.ts +30 -0
- package/full-react-imperative/app/Application.ts +1 -3
- package/full-react-imperative/package.json +12 -12
- package/full-react-imperative/public/favicon.svg +16 -0
- package/full-react-imperative/stone.config.mjs +2 -2
- package/full-react-imperative/tests/application.spec.ts +30 -0
- package/full-service-declarative/app/Application.ts +5 -2
- package/full-service-declarative/app/configurations/AppConfiguration.ts +1 -3
- package/full-service-declarative/package.json +13 -12
- package/full-service-declarative/stone.config.mjs +2 -2
- package/full-service-declarative/tests/application.spec.ts +30 -0
- package/full-service-imperative/app/Application.ts +8 -2
- package/full-service-imperative/app/configurations/AppConfiguration.ts +1 -3
- package/full-service-imperative/package.json +13 -12
- package/full-service-imperative/stone.config.mjs +2 -2
- package/full-service-imperative/tests/application.spec.ts +30 -0
- package/package.json +1 -1
- package/standard-react-declarative/package.json +11 -10
- package/standard-react-declarative/public/favicon.svg +16 -0
- package/standard-react-declarative/tests/application.spec.ts +30 -0
- package/standard-react-imperative/package.json +11 -10
- package/standard-react-imperative/public/favicon.svg +16 -0
- package/standard-react-imperative/tests/application.spec.ts +30 -0
- package/standard-service-declarative/package.json +9 -8
- package/standard-service-declarative/tests/Application.spec.ts +22 -94
- package/standard-service-imperative/package.json +9 -8
- package/standard-service-imperative/tests/Application.spec.ts +22 -78
- package/basic-react-declarative/vitest.config.ts +0 -24
- package/basic-react-imperative/vitest.config.ts +0 -24
- package/basic-service-declarative/vitest.config.ts +0 -24
- package/basic-service-imperative/vitest.config.ts +0 -24
- package/continuum-showcase/tests/HomePage.spec.tsx +0 -41
- package/continuum-showcase/vitest.config.ts +0 -31
- package/full-react-declarative/tests/AppLayout.spec.ts +0 -51
- package/full-react-declarative/tests/HomePage.spec.ts +0 -38
- package/full-react-declarative/vitest.config.ts +0 -24
- package/full-react-imperative/tests/HomePage.spec.ts +0 -45
- package/full-react-imperative/tests/LayoutHeader.spec.ts +0 -39
- package/full-react-imperative/vitest.config.ts +0 -24
- package/full-service-declarative/tests/PostService.spec.ts +0 -56
- package/full-service-declarative/tests/WelcomeEventHandler.spec.ts +0 -54
- package/full-service-declarative/vitest.config.ts +0 -24
- package/full-service-imperative/tests/PostService.spec.ts +0 -47
- package/full-service-imperative/tests/WelcomeEventHandler.spec.ts +0 -31
- package/full-service-imperative/vitest.config.ts +0 -24
- package/standard-react-declarative/tests/WelcomePage.spec.ts +0 -71
- package/standard-react-declarative/vitest.config.ts +0 -24
- package/standard-react-imperative/tests/WelcomePage.spec.ts +0 -53
- package/standard-react-imperative/vitest.config.ts +0 -24
- package/standard-service-declarative/vitest.config.ts +0 -24
- package/standard-service-imperative/vitest.config.ts +0 -24
|
@@ -17,28 +17,29 @@
|
|
|
17
17
|
"db:setup": "drizzle-kit push",
|
|
18
18
|
"db:generate": "drizzle-kit generate",
|
|
19
19
|
"db:migrate": "drizzle-kit migrate",
|
|
20
|
-
"test": "
|
|
21
|
-
"test:cvg": "
|
|
20
|
+
"test": "stone test",
|
|
21
|
+
"test:cvg": "stone test --coverage"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@libsql/client": "^0.14.0",
|
|
25
|
-
"@stone-js/core": "^0.8.
|
|
26
|
-
"@stone-js/env": "^0.8.
|
|
27
|
-
"@stone-js/filesystem": "^0.8.
|
|
28
|
-
"@stone-js/http-core": "^0.8.
|
|
29
|
-
"@stone-js/node-cli-adapter": "^0.8.
|
|
30
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
31
|
-
"@stone-js/pipeline": "^0.8.
|
|
32
|
-
"@stone-js/router": "^0.8.
|
|
25
|
+
"@stone-js/core": "^0.8.9",
|
|
26
|
+
"@stone-js/env": "^0.8.9",
|
|
27
|
+
"@stone-js/filesystem": "^0.8.9",
|
|
28
|
+
"@stone-js/http-core": "^0.8.9",
|
|
29
|
+
"@stone-js/node-cli-adapter": "^0.8.9",
|
|
30
|
+
"@stone-js/node-http-adapter": "^0.8.9",
|
|
31
|
+
"@stone-js/pipeline": "^0.8.9",
|
|
32
|
+
"@stone-js/router": "^0.8.9",
|
|
33
33
|
"bcryptjs": "^3.0.2",
|
|
34
|
-
"drizzle-orm": "^0.
|
|
34
|
+
"drizzle-orm": "^0.45.2",
|
|
35
35
|
"jsonwebtoken": "^9.0.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
39
39
|
"@babel/preset-env": "^7.26.9",
|
|
40
40
|
"@babel/preset-typescript": "^7.27.0",
|
|
41
|
-
"@stone-js/cli": "^0.8.
|
|
41
|
+
"@stone-js/cli": "^0.8.9",
|
|
42
|
+
"@stone-js/testing": "^0.8.9",
|
|
42
43
|
"@types/jsonwebtoken": "^9.0.8",
|
|
43
44
|
"@types/node": "^24.0.3",
|
|
44
45
|
"@vitest/coverage-v8": "^3.0.9",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineBuilderConfig } from '@stone-js/cli'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Stone build configuration.
|
|
5
5
|
*/
|
|
6
|
-
export default
|
|
6
|
+
export default defineBuilderConfig({
|
|
7
7
|
rollup: {
|
|
8
8
|
bundle: {
|
|
9
9
|
external: ['@libsql/client'],
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Application', () => {
|
|
12
|
+
it('answers on the public welcome route', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
expect(response.json()).toMatchObject({ message: expect.stringContaining('Stone.js') })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('refuses an unauthenticated request to a protected route', async () => {
|
|
22
|
+
// Substitute a repository with `bindings` when a route needs data:
|
|
23
|
+
// createTestApp({ bindings: { userRepository: fakeRepository } })
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/users' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBeGreaterThanOrEqual(400)
|
|
29
|
+
})
|
|
30
|
+
})
|
package/package.json
CHANGED
|
@@ -14,25 +14,26 @@
|
|
|
14
14
|
"build": "stone build",
|
|
15
15
|
"preview": "stone preview",
|
|
16
16
|
"typings": "stone typings",
|
|
17
|
-
"test": "
|
|
18
|
-
"test:cvg": "
|
|
17
|
+
"test": "stone test",
|
|
18
|
+
"test:cvg": "stone test --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0",
|
|
23
|
-
"@stone-js/use-react": "^0.8.
|
|
24
|
-
"@stone-js/browser-adapter": "^0.8.
|
|
25
|
-
"@stone-js/pipeline": "^0.8.
|
|
26
|
-
"@stone-js/http-core": "^0.8.
|
|
27
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
28
|
-
"@stone-js/router": "^0.8.
|
|
29
|
-
"@stone-js/core": "^0.8.
|
|
23
|
+
"@stone-js/use-react": "^0.8.9",
|
|
24
|
+
"@stone-js/browser-adapter": "^0.8.9",
|
|
25
|
+
"@stone-js/pipeline": "^0.8.9",
|
|
26
|
+
"@stone-js/http-core": "^0.8.9",
|
|
27
|
+
"@stone-js/node-http-adapter": "^0.8.9",
|
|
28
|
+
"@stone-js/router": "^0.8.9",
|
|
29
|
+
"@stone-js/core": "^0.8.9"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
33
33
|
"@babel/preset-env": "^7.26.9",
|
|
34
34
|
"@babel/preset-typescript": "^7.27.0",
|
|
35
|
-
"@stone-js/cli": "^0.8.
|
|
35
|
+
"@stone-js/cli": "^0.8.9",
|
|
36
|
+
"@stone-js/testing": "^0.8.9",
|
|
36
37
|
"@types/node": "^24.0.7",
|
|
37
38
|
"@types/react": "^19.0.7",
|
|
38
39
|
"@types/react-dom": "^19.0.3",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="96" height="96" role="img" aria-label="Stone.js">
|
|
2
|
+
<title>Stone.js</title>
|
|
3
|
+
<style>
|
|
4
|
+
.ink { stroke: #1B1613; }
|
|
5
|
+
@media (prefers-color-scheme: dark) { .ink { stroke: #EFE8DC; } }
|
|
6
|
+
</style>
|
|
7
|
+
<defs>
|
|
8
|
+
<linearGradient id="braise" gradientUnits="userSpaceOnUse" x1="22" y1="14" x2="74" y2="26.1">
|
|
9
|
+
<stop offset="0" stop-color="#FFC46B" />
|
|
10
|
+
<stop offset="1" stop-color="#FF5A1F" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
<path class="ink" d="M 79.96 36.4 A 34 34 0 0 1 53.9 81.5" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
14
|
+
<path class="ink" d="M 42.1 81.5 A 34 34 0 0 1 16.05 36.4" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
15
|
+
<path d="M 22 26.1 A 34 34 0 0 1 74 26.1" fill="none" stroke="url(#braise)" stroke-width="11" stroke-linecap="round" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Pages', () => {
|
|
12
|
+
it('renders the home page, data included', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
// A page is a handler, so a rendered page is a response whose body is HTML. Query that HTML with
|
|
19
|
+
// whatever you already use (happy-dom, jsdom, Testing Library): none is bundled here.
|
|
20
|
+
expect(response.html()).toContain('Ada')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders without a name', async () => {
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBe(200)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -14,25 +14,26 @@
|
|
|
14
14
|
"build": "stone build",
|
|
15
15
|
"preview": "stone preview",
|
|
16
16
|
"typings": "stone typings",
|
|
17
|
-
"test": "
|
|
18
|
-
"test:cvg": "
|
|
17
|
+
"test": "stone test",
|
|
18
|
+
"test:cvg": "stone test --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0",
|
|
23
|
-
"@stone-js/use-react": "^0.8.
|
|
24
|
-
"@stone-js/browser-adapter": "^0.8.
|
|
25
|
-
"@stone-js/pipeline": "^0.8.
|
|
26
|
-
"@stone-js/http-core": "^0.8.
|
|
27
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
28
|
-
"@stone-js/router": "^0.8.
|
|
29
|
-
"@stone-js/core": "^0.8.
|
|
23
|
+
"@stone-js/use-react": "^0.8.9",
|
|
24
|
+
"@stone-js/browser-adapter": "^0.8.9",
|
|
25
|
+
"@stone-js/pipeline": "^0.8.9",
|
|
26
|
+
"@stone-js/http-core": "^0.8.9",
|
|
27
|
+
"@stone-js/node-http-adapter": "^0.8.9",
|
|
28
|
+
"@stone-js/router": "^0.8.9",
|
|
29
|
+
"@stone-js/core": "^0.8.9"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
33
33
|
"@babel/preset-env": "^7.26.9",
|
|
34
34
|
"@babel/preset-typescript": "^7.27.0",
|
|
35
|
-
"@stone-js/cli": "^0.8.
|
|
35
|
+
"@stone-js/cli": "^0.8.9",
|
|
36
|
+
"@stone-js/testing": "^0.8.9",
|
|
36
37
|
"@types/node": "^24.0.7",
|
|
37
38
|
"@types/react": "^19.0.7",
|
|
38
39
|
"@types/react-dom": "^19.0.3",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="96" height="96" role="img" aria-label="Stone.js">
|
|
2
|
+
<title>Stone.js</title>
|
|
3
|
+
<style>
|
|
4
|
+
.ink { stroke: #1B1613; }
|
|
5
|
+
@media (prefers-color-scheme: dark) { .ink { stroke: #EFE8DC; } }
|
|
6
|
+
</style>
|
|
7
|
+
<defs>
|
|
8
|
+
<linearGradient id="braise" gradientUnits="userSpaceOnUse" x1="22" y1="14" x2="74" y2="26.1">
|
|
9
|
+
<stop offset="0" stop-color="#FFC46B" />
|
|
10
|
+
<stop offset="1" stop-color="#FF5A1F" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
<path class="ink" d="M 79.96 36.4 A 34 34 0 0 1 53.9 81.5" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
14
|
+
<path class="ink" d="M 42.1 81.5 A 34 34 0 0 1 16.05 36.4" fill="none" stroke-width="11" stroke-linecap="round" opacity=".85" />
|
|
15
|
+
<path d="M 22 26.1 A 34 34 0 0 1 74 26.1" fill="none" stroke="url(#braise)" stroke-width="11" stroke-linecap="round" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Pages', () => {
|
|
12
|
+
it('renders the home page, data included', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
// A page is a handler, so a rendered page is a response whose body is HTML. Query that HTML with
|
|
19
|
+
// whatever you already use (happy-dom, jsdom, Testing Library): none is bundled here.
|
|
20
|
+
expect(response.html()).toContain('Ada')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders without a name', async () => {
|
|
24
|
+
const app = await createTestApp()
|
|
25
|
+
|
|
26
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
27
|
+
|
|
28
|
+
expect(response.statusCode).toBe(200)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -14,21 +14,22 @@
|
|
|
14
14
|
"build": "stone build",
|
|
15
15
|
"preview": "stone preview dist/server.mjs",
|
|
16
16
|
"typings": "stone typings",
|
|
17
|
-
"test": "
|
|
18
|
-
"test:cvg": "
|
|
17
|
+
"test": "stone test",
|
|
18
|
+
"test:cvg": "stone test --coverage"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@stone-js/pipeline": "^0.8.
|
|
22
|
-
"@stone-js/http-core": "^0.8.
|
|
23
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
24
|
-
"@stone-js/router": "^0.8.
|
|
25
|
-
"@stone-js/core": "^0.8.
|
|
21
|
+
"@stone-js/pipeline": "^0.8.9",
|
|
22
|
+
"@stone-js/http-core": "^0.8.9",
|
|
23
|
+
"@stone-js/node-http-adapter": "^0.8.9",
|
|
24
|
+
"@stone-js/router": "^0.8.9",
|
|
25
|
+
"@stone-js/core": "^0.8.9"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
29
29
|
"@babel/preset-env": "^7.26.9",
|
|
30
30
|
"@babel/preset-typescript": "^7.27.0",
|
|
31
|
-
"@stone-js/cli": "^0.8.
|
|
31
|
+
"@stone-js/cli": "^0.8.9",
|
|
32
|
+
"@stone-js/testing": "^0.8.9",
|
|
32
33
|
"@types/node": "^24.0.7",
|
|
33
34
|
"@vitest/coverage-v8": "^3.0.9",
|
|
34
35
|
"vitest": "^3.0.9"
|
|
@@ -1,100 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
...actual,
|
|
20
|
-
EventHandler: vi.fn(() => vi.fn()),
|
|
21
|
-
Get: vi.fn(() => vi.fn())
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
// We must mock decorators to lighten the test environment
|
|
26
|
-
vi.mock(import('@stone-js/http-core'), async (importOriginal) => {
|
|
27
|
-
const actual = await importOriginal()
|
|
28
|
-
return {
|
|
29
|
-
...actual,
|
|
30
|
-
JsonHttpResponse: vi.fn(() => vi.fn())
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
describe('WelcomeService', () => {
|
|
35
|
-
let mockedLogger: ILogger
|
|
36
|
-
let service: WelcomeService
|
|
37
|
-
|
|
38
|
-
beforeEach(() => {
|
|
39
|
-
mockedLogger = {
|
|
40
|
-
info: vi.fn()
|
|
41
|
-
} as unknown as ILogger
|
|
42
|
-
|
|
43
|
-
service = new WelcomeService({ logger: mockedLogger })
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('should build a branded welcome message for the given name', () => {
|
|
47
|
-
// Act
|
|
48
|
-
const response = service.welcome('Stone')
|
|
49
|
-
|
|
50
|
-
// Assert
|
|
51
|
-
expect(response.message).toBe('Hello Stone! Welcome to Stone.js.')
|
|
52
|
-
expect(response.framework.name).toBe('Stone.js')
|
|
53
|
-
expect(response.framework).toMatchObject({
|
|
54
|
-
name: 'Stone.js',
|
|
55
|
-
tagline: 'The continuum framework',
|
|
56
|
-
docs: 'https://stonejs.dev',
|
|
57
|
-
github: 'https://github.com/stone-foundation/stone-js-framework'
|
|
58
|
-
})
|
|
59
|
-
expect(mockedLogger.info).toHaveBeenCalledWith('Welcome Stone')
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
describe('WelcomeEventHandler', () => {
|
|
64
|
-
let mockedLogger: ILogger
|
|
65
|
-
let handler: WelcomeEventHandler
|
|
66
|
-
|
|
67
|
-
beforeEach(() => {
|
|
68
|
-
mockedLogger = {
|
|
69
|
-
info: vi.fn()
|
|
70
|
-
} as unknown as ILogger
|
|
71
|
-
|
|
72
|
-
handler = new WelcomeEventHandler({ welcomeService: new WelcomeService({ logger: mockedLogger }) })
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('should welcome the name carried by the event', () => {
|
|
76
|
-
// Arrange
|
|
77
|
-
const event = { get: () => 'World' } as unknown as IncomingHttpEvent
|
|
78
|
-
|
|
79
|
-
// Act
|
|
80
|
-
const response = handler.welcome(event)
|
|
81
|
-
|
|
82
|
-
// Assert
|
|
83
|
-
expect(response.message).toBe('Hello World! Welcome to Stone.js.')
|
|
84
|
-
expect(response.framework.name).toBe('Stone.js')
|
|
85
|
-
expect(mockedLogger.info).toHaveBeenCalledWith('Welcome World')
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Application', () => {
|
|
12
|
+
it('answers the caller', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
expect(response.json()).toMatchObject({ message: expect.stringContaining('Ada') })
|
|
86
19
|
})
|
|
87
20
|
|
|
88
|
-
it('
|
|
89
|
-
|
|
90
|
-
const event = { get: (_key: string, fallback: string) => fallback } as unknown as IncomingHttpEvent
|
|
21
|
+
it('answers when nobody says who they are', async () => {
|
|
22
|
+
const app = await createTestApp()
|
|
91
23
|
|
|
92
|
-
|
|
93
|
-
const response = handler.welcome(event)
|
|
24
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
94
25
|
|
|
95
|
-
|
|
96
|
-
expect(response.message).toBe('Hello World! Welcome to Stone.js.')
|
|
97
|
-
expect(response.framework.name).toBe('Stone.js')
|
|
98
|
-
expect(mockedLogger.info).toHaveBeenCalledWith('Welcome World')
|
|
26
|
+
expect(response.statusCode).toBe(200)
|
|
99
27
|
})
|
|
100
28
|
})
|
|
@@ -13,21 +13,22 @@
|
|
|
13
13
|
"build": "stone build",
|
|
14
14
|
"preview": "stone preview dist/server.mjs",
|
|
15
15
|
"typings": "stone typings",
|
|
16
|
-
"test": "
|
|
17
|
-
"test:cvg": "
|
|
16
|
+
"test": "stone test",
|
|
17
|
+
"test:cvg": "stone test --coverage"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@stone-js/pipeline": "^0.8.
|
|
21
|
-
"@stone-js/http-core": "^0.8.
|
|
22
|
-
"@stone-js/node-http-adapter": "^0.8.
|
|
23
|
-
"@stone-js/router": "^0.8.
|
|
24
|
-
"@stone-js/core": "^0.8.
|
|
20
|
+
"@stone-js/pipeline": "^0.8.9",
|
|
21
|
+
"@stone-js/http-core": "^0.8.9",
|
|
22
|
+
"@stone-js/node-http-adapter": "^0.8.9",
|
|
23
|
+
"@stone-js/router": "^0.8.9",
|
|
24
|
+
"@stone-js/core": "^0.8.9"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
28
28
|
"@babel/preset-env": "^7.26.9",
|
|
29
29
|
"@babel/preset-typescript": "^7.27.0",
|
|
30
|
-
"@stone-js/cli": "^0.8.
|
|
30
|
+
"@stone-js/cli": "^0.8.9",
|
|
31
|
+
"@stone-js/testing": "^0.8.9",
|
|
31
32
|
"@types/node": "^24.0.7",
|
|
32
33
|
"@vitest/coverage-v8": "^3.0.9",
|
|
33
34
|
"vitest": "^3.0.9"
|
|
@@ -1,84 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// Act
|
|
20
|
-
const response = service.welcome('Stone')
|
|
21
|
-
|
|
22
|
-
// Assert
|
|
23
|
-
expect(response.message).toBe('Hello Stone! Welcome to Stone.js.')
|
|
24
|
-
expect(response.framework.name).toBe('Stone.js')
|
|
25
|
-
expect(response.framework).toMatchObject({
|
|
26
|
-
name: 'Stone.js',
|
|
27
|
-
tagline: 'The continuum framework',
|
|
28
|
-
docs: 'https://stonejs.dev',
|
|
29
|
-
github: 'https://github.com/stone-foundation/stone-js-framework'
|
|
30
|
-
})
|
|
31
|
-
expect(mockedLogger.info).toHaveBeenCalledWith('Welcome Stone')
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
describe('WelcomeEventHandler', () => {
|
|
36
|
-
let mockedLogger: ILogger
|
|
37
|
-
|
|
38
|
-
beforeEach(() => {
|
|
39
|
-
mockedLogger = {
|
|
40
|
-
info: vi.fn()
|
|
41
|
-
} as unknown as ILogger
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('should create a functional event handler', () => {
|
|
45
|
-
// Arrange
|
|
46
|
-
const welcomeService = WelcomeService({ logger: mockedLogger })
|
|
47
|
-
|
|
48
|
-
// Act
|
|
49
|
-
const handler = WelcomeEventHandler({ welcomeService })
|
|
50
|
-
|
|
51
|
-
// Assert
|
|
52
|
-
expect(handler).toBeTypeOf('function')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should welcome the name carried by the event', () => {
|
|
56
|
-
// Arrange
|
|
57
|
-
const welcomeService = WelcomeService({ logger: mockedLogger })
|
|
58
|
-
const handler = WelcomeEventHandler({ welcomeService })
|
|
59
|
-
const event = { get: () => 'World' } as unknown as IncomingHttpEvent
|
|
60
|
-
|
|
61
|
-
// Act
|
|
62
|
-
const response = handler(event)
|
|
63
|
-
|
|
64
|
-
// Assert
|
|
65
|
-
expect(response.message).toBe('Hello World! Welcome to Stone.js.')
|
|
66
|
-
expect(response.framework.name).toBe('Stone.js')
|
|
67
|
-
expect(mockedLogger.info).toHaveBeenCalledWith('Welcome World')
|
|
1
|
+
import { createTestApp, makeIncomingHttpEvent } from '@stone-js/testing'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The whole application, booted in memory and asked a real question.
|
|
5
|
+
*
|
|
6
|
+
* Nothing is mocked and nothing is listed: `createTestApp()` discovers `app/**`, and the event goes
|
|
7
|
+
* through the same kernel production runs. If this passes the application works; if it fails the
|
|
8
|
+
* application is broken. That is the only kind of test worth shipping in a starter — the previous one
|
|
9
|
+
* stubbed out the framework's own decorators, which meant it could pass while nothing worked.
|
|
10
|
+
*/
|
|
11
|
+
describe('Application', () => {
|
|
12
|
+
it('answers the caller', async () => {
|
|
13
|
+
const app = await createTestApp()
|
|
14
|
+
|
|
15
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/?name=Ada' }))
|
|
16
|
+
|
|
17
|
+
expect(response.statusCode).toBe(200)
|
|
18
|
+
expect(response.json()).toMatchObject({ message: expect.stringContaining('Ada') })
|
|
68
19
|
})
|
|
69
20
|
|
|
70
|
-
it('
|
|
71
|
-
|
|
72
|
-
const welcomeService = WelcomeService({ logger: mockedLogger })
|
|
73
|
-
const handler = WelcomeEventHandler({ welcomeService })
|
|
74
|
-
const event = { get: (_key: string, fallback: string) => fallback } as unknown as IncomingHttpEvent
|
|
21
|
+
it('answers when nobody says who they are', async () => {
|
|
22
|
+
const app = await createTestApp()
|
|
75
23
|
|
|
76
|
-
|
|
77
|
-
const response = handler(event)
|
|
24
|
+
const response = await app.send(makeIncomingHttpEvent({ method: 'GET', url: '/' }))
|
|
78
25
|
|
|
79
|
-
|
|
80
|
-
expect(response.message).toBe('Hello World! Welcome to Stone.js.')
|
|
81
|
-
expect(response.framework.name).toBe('Stone.js')
|
|
82
|
-
expect(mockedLogger.info).toHaveBeenCalledWith('Welcome World')
|
|
26
|
+
expect(response.statusCode).toBe(200)
|
|
83
27
|
})
|
|
84
28
|
})
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
include: ['./tests/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: 'v8',
|
|
10
|
-
include: ['app/**/*.ts', 'app/**/*.tsx'],
|
|
11
|
-
reporter: ['text', 'html'],
|
|
12
|
-
reportsDirectory: './coverage',
|
|
13
|
-
thresholds: {
|
|
14
|
-
100: true
|
|
15
|
-
},
|
|
16
|
-
watermarks: {
|
|
17
|
-
statements: [60, 80],
|
|
18
|
-
functions: [60, 80],
|
|
19
|
-
branches: [60, 80],
|
|
20
|
-
lines: [60, 80]
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
include: ['./tests/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: 'v8',
|
|
10
|
-
include: ['app/**/*.ts', 'app/**/*.tsx'],
|
|
11
|
-
reporter: ['text', 'html'],
|
|
12
|
-
reportsDirectory: './coverage',
|
|
13
|
-
thresholds: {
|
|
14
|
-
100: true
|
|
15
|
-
},
|
|
16
|
-
watermarks: {
|
|
17
|
-
statements: [60, 80],
|
|
18
|
-
functions: [60, 80],
|
|
19
|
-
branches: [60, 80],
|
|
20
|
-
lines: [60, 80]
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
include: ['./tests/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: 'v8',
|
|
10
|
-
include: ['app/**/*.ts'],
|
|
11
|
-
reporter: ['text', 'html'],
|
|
12
|
-
reportsDirectory: './coverage',
|
|
13
|
-
thresholds: {
|
|
14
|
-
100: true
|
|
15
|
-
},
|
|
16
|
-
watermarks: {
|
|
17
|
-
statements: [60, 80],
|
|
18
|
-
functions: [60, 80],
|
|
19
|
-
branches: [60, 80],
|
|
20
|
-
lines: [60, 80]
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
});
|