test: move tests to src directory (#1075)

* test(react-renderer): move tests to src directory

* test: move tests to src directory

* test: ensure vitest-pool-workers is installed at the root
pull/1031/head
Jonathan Haines 2025-03-28 20:50:19 +11:00 committed by GitHub
parent 5fac2ef09c
commit 4f9bb1dd8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 129 additions and 120 deletions

View File

@ -60,6 +60,7 @@
"devDependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.26.0",
"@cloudflare/vitest-pool-workers": "^0.7.8",
"@cloudflare/workers-types": "^4.20230307.0",
"@ryoppippi/unplugin-typia": "^1.2.0",
"@types/node": "^20.14.8",

View File

@ -1,7 +1,7 @@
import type { JSONSchemaType, type ErrorObject } from 'ajv'
import { Hono } from 'hono'
import type { Equal, Expect } from 'hono/utils/types'
import { ajvValidator } from '../src'
import { ajvValidator } from '.'
type ExtractSchema<T> = T extends Hono<infer _, infer S> ? S : never
@ -193,7 +193,7 @@ describe('With Hook', () => {
{
keyword: 'required',
instancePath: '',
message: 'must have required property \'title\'',
message: "must have required property 'title'",
},
])
})

View File

@ -3,8 +3,8 @@ import type { Adapter } from '@auth/core/adapters'
import Credentials from '@auth/core/providers/credentials'
import { Hono } from 'hono'
import { describe, expect, it, vi } from 'vitest'
import type { AuthConfig } from '../src'
import { authHandler, verifyAuth, initAuthConfig, reqWithEnvUrl } from '../src'
import type { AuthConfig } from '.'
import { authHandler, verifyAuth, initAuthConfig, reqWithEnvUrl } from '.'
describe('Config', () => {
it('Should return 500 if AUTH_SECRET is missing', async () => {

View File

@ -3,8 +3,8 @@ import { Hono } from 'hono'
import { basicAuth } from 'hono/basic-auth'
import { jwt, sign } from 'hono/jwt'
import { describe, it, expect } from 'vitest'
import { casbin } from '../src'
import { basicAuthorizer, jwtAuthorizer } from '../src/helper'
import { basicAuthorizer, jwtAuthorizer } from './helper'
import { casbin } from '.'
describe('Casbin Middleware Tests', () => {
describe('BasicAuthorizer', () => {

View File

@ -4,7 +4,7 @@ import { IsInt, IsString, ValidateNested } from 'class-validator'
import { Hono } from 'hono'
import type { ExtractSchema } from 'hono/types'
import type { Equal, Expect } from 'hono/utils/types'
import { classValidator } from '../src'
import { classValidator } from '.'
describe('Basic', () => {
const app = new Hono()

View File

@ -3,7 +3,7 @@ import { describe, expect, it, vi } from 'vitest'
import crypto from 'crypto'
import { promisify } from 'util'
import { cloudflareAccess } from '../src'
import { cloudflareAccess } from '.'
const generateKeyPair = promisify(crypto.generateKeyPair)

View File

@ -1,7 +1,7 @@
import { parseWithZod } from '@conform-to/zod'
import { Hono } from 'hono'
import { z } from 'zod'
import { conformValidator } from '../src'
import { conformValidator } from '.'
describe('Validate common processing', () => {
const app = new Hono()

View File

@ -3,7 +3,7 @@ import { Hono } from 'hono'
import { hc } from 'hono/client'
import { vi } from 'vitest'
import * as z from 'zod'
import { conformValidator } from '../src'
import { conformValidator } from '.'
describe('Validate the hook option processing', () => {
const app = new Hono()

View File

@ -5,7 +5,7 @@ import type { ExtractSchema, ParsedFormValue } from 'hono/types'
import type { StatusCode } from 'hono/utils/http-status'
import type { Equal, Expect } from 'hono/utils/types'
import * as v from 'valibot'
import { conformValidator } from '../src'
import { conformValidator } from '.'
describe('Validate requests using a Valibot schema', () => {
const app = new Hono()

View File

@ -5,7 +5,7 @@ import type { ExtractSchema, ParsedFormValue } from 'hono/types'
import type { StatusCode } from 'hono/utils/http-status'
import type { Equal, Expect } from 'hono/utils/types'
import * as y from 'yup'
import { conformValidator } from '../src'
import { conformValidator } from '.'
describe('Validate requests using a Yup schema', () => {
const app = new Hono()

View File

@ -5,7 +5,7 @@ import type { ExtractSchema, ParsedFormValue } from 'hono/types'
import type { StatusCode } from 'hono/utils/http-status'
import type { Equal, Expect } from 'hono/utils/types'
import * as z from 'zod'
import { conformValidator } from '../src'
import { conformValidator } from '.'
describe('Validate requests using a Zod schema', () => {
const app = new Hono()

View File

@ -2,7 +2,7 @@ import { Schema as S } from 'effect'
import { Hono } from 'hono'
import type { StatusCode } from 'hono/utils/http-status'
import type { Equal, Expect } from 'hono/utils/types'
import { effectValidator } from '../src'
import { effectValidator } from '.'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type ExtractSchema<T> = T extends Hono<infer _, infer S> ? S : never

View File

@ -1,6 +1,6 @@
import { Hono } from 'hono'
import { describe, it, expect } from 'vitest'
import { esbuildTranspiler } from '../src/transpilers/node'
import { esbuildTranspiler } from './node'
const TS = 'function add(a: number, b: number) { return a + b; }'
const BAD = 'function { !!! !@#$ add(a: INT) return a + b + c; }'

View File

@ -6,8 +6,8 @@ import { setCookie } from 'hono/cookie'
import { HTTPException } from 'hono/http-exception'
import { Miniflare } from 'miniflare'
import { describe, it, expect, beforeAll, vi } from 'vitest'
import type { VerifyFirebaseAuthEnv } from '../src'
import { verifyFirebaseAuth, getFirebaseToken, verifySessionCookieFirebaseAuth } from '../src'
import type { VerifyFirebaseAuthEnv } from '.'
import { verifyFirebaseAuth, getFirebaseToken, verifySessionCookieFirebaseAuth } from '.'
describe('verifyFirebaseAuth middleware', () => {
const emulatorHost = '127.0.0.1:9099'

View File

@ -1,5 +1,5 @@
import { Hono } from 'hono'
import { hello } from '../src'
import { hello } from '.'
describe('Hello middleware', () => {
const app = new Hono()

View File

@ -1,5 +1,5 @@
import { Hono } from 'hono'
import { MedleyRouter } from '../src'
import { MedleyRouter } from '.'
describe('Basic', () => {
const app = new Hono({ router: new MedleyRouter() })

View File

@ -1,17 +1,21 @@
import type { DefaultBodyType, StrictResponse } from 'msw'
import { HttpResponse, http } from 'msw'
import type { DiscordErrorResponse, DiscordTokenResponse } from '../src/providers/discord'
import type { DiscordErrorResponse, DiscordTokenResponse } from './src/providers/discord'
import type {
FacebookErrorResponse,
FacebookTokenResponse,
FacebookUser,
} from '../src/providers/facebook'
import type { GitHubErrorResponse, GitHubTokenResponse } from '../src/providers/github'
import type { GoogleErrorResponse, GoogleTokenResponse, GoogleUser } from '../src/providers/google'
import type { LinkedInErrorResponse, LinkedInTokenResponse } from '../src/providers/linkedin'
import type { TwitchErrorResponse, TwitchTokenResponse, TwitchTokenSuccess } from '../src/providers/twitch'
import type { XErrorResponse, XRevokeResponse, XTokenResponse } from '../src/providers/x'
} from './src/providers/facebook'
import type { GitHubErrorResponse, GitHubTokenResponse } from './src/providers/github'
import type { GoogleErrorResponse, GoogleTokenResponse, GoogleUser } from './src/providers/google'
import type { LinkedInErrorResponse, LinkedInTokenResponse } from './src/providers/linkedin'
import type {
TwitchErrorResponse,
TwitchTokenResponse,
TwitchTokenSuccess,
} from './src/providers/twitch'
import type { XErrorResponse, XRevokeResponse, XTokenResponse } from './src/providers/x'
export const handlers = [
// Google
@ -150,7 +154,9 @@ export const handlers = [
// Twitch
http.post(
'https://id.twitch.tv/oauth2/token',
async ({ request }): Promise<StrictResponse<Partial<TwitchTokenResponse> | TwitchErrorResponse>> => {
async ({
request,
}): Promise<StrictResponse<Partial<TwitchTokenResponse> | TwitchErrorResponse>> => {
const params = new URLSearchParams(await request.text())
const code = params.get('code')
const grant_type = params.get('grant_type')
@ -174,7 +180,9 @@ export const handlers = [
const params = new URLSearchParams(await request.text())
const token = params.get('token')
if (token === 'wrong-token') {
return HttpResponse.json<{ status: number; message?: string }>(twitchRevokeTokenError, { status: 400 })
return HttpResponse.json<{ status: number; message?: string }>(twitchRevokeTokenError, {
status: 400,
})
}
return HttpResponse.json<null>(null, { status: 200 }) // Return 200 with empty body
}
@ -182,17 +190,19 @@ export const handlers = [
// Twitch validate token handler
http.get(
'https://id.twitch.tv/oauth2/validate',
async ({ request }): Promise<StrictResponse<typeof twitchValidateSuccess | typeof twitchValidateError>> => {
async ({
request,
}): Promise<StrictResponse<typeof twitchValidateSuccess | typeof twitchValidateError>> => {
const authHeader = request.headers.get('authorization')
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return HttpResponse.json(twitchValidateError, { status: 401 })
}
const token = authHeader.split(' ')[1]
if (token === 'twitchr4nd0m4cc3sst0k3n') {
return HttpResponse.json(twitchValidateSuccess)
}
return HttpResponse.json(twitchValidateError, { status: 401 })
}
),
@ -509,7 +519,8 @@ export const twitchUser = {
type: '',
broadcaster_type: 'partner',
description: 'Supporting third-party developers building Twitch integrations',
profile_image_url: 'https://static-cdn.jtvnw.net/jtv_user_pictures/example-profile-picture.png',
profile_image_url:
'https://static-cdn.jtvnw.net/jtv_user_pictures/example-profile-picture.png',
offline_image_url: 'https://static-cdn.jtvnw.net/jtv_user_pictures/example-offline-image.png',
view_count: 5980557,
email: 'example@twitch.tv',
@ -540,10 +551,10 @@ export const twitchValidateSuccess = {
login: 'younis',
scopes: ['user:read:email', 'channel:read:subscriptions', 'bits:read'],
user_id: '12345678',
expires_in: 14400
expires_in: 14400,
}
export const twitchValidateError = {
status: 401,
message: 'invalid access token'
message: 'invalid access token',
}

View File

@ -1,29 +1,5 @@
import { Hono } from 'hono'
import { setupServer } from 'msw/node'
import type { DiscordUser } from '../src/providers/discord'
import {
discordAuth,
refreshToken as discordRefresh,
revokeToken as discordRevoke,
} from '../src/providers/discord'
import { facebookAuth } from '../src/providers/facebook'
import type { FacebookUser } from '../src/providers/facebook'
import { githubAuth } from '../src/providers/github'
import type { GitHubUser } from '../src/providers/github'
import { googleAuth } from '../src/providers/google'
import type { GoogleUser } from '../src/providers/google'
import { linkedinAuth } from '../src/providers/linkedin'
import type { LinkedInUser } from '../src/providers/linkedin'
import type { TwitchUser } from '../src/providers/twitch'
import {
twitchAuth,
refreshToken as twitchRefresh,
revokeToken as twitchRevoke,
validateToken as twitchValidate
} from '../src/providers/twitch'
import type { XUser } from '../src/providers/x'
import { refreshToken, revokeToken, xAuth } from '../src/providers/x'
import type { Token } from '../src/types'
import {
discordCodeError,
discordRefreshToken,
@ -57,7 +33,31 @@ import {
twitchUser,
twitchValidateSuccess,
twitchValidateError,
} from './handlers'
} from '../mocks'
import type { DiscordUser } from './providers/discord'
import {
discordAuth,
refreshToken as discordRefresh,
revokeToken as discordRevoke,
} from './providers/discord'
import { facebookAuth } from './providers/facebook'
import type { FacebookUser } from './providers/facebook'
import { githubAuth } from './providers/github'
import type { GitHubUser } from './providers/github'
import { googleAuth } from './providers/google'
import type { GoogleUser } from './providers/google'
import { linkedinAuth } from './providers/linkedin'
import type { LinkedInUser } from './providers/linkedin'
import type { TwitchUser } from './providers/twitch'
import {
twitchAuth,
refreshToken as twitchRefresh,
revokeToken as twitchRevoke,
validateToken as twitchValidate,
} from './providers/twitch'
import type { XUser } from './providers/x'
import { refreshToken, revokeToken, xAuth } from './providers/x'
import type { Token } from './types'
const server = setupServer(...handlers)
server.listen()
@ -405,11 +405,7 @@ describe('OAuth Middleware', () => {
})
})
app.get('/twitch/refresh', async (c) => {
const response = await twitchRefresh(
client_id,
client_secret,
'twitchr4nd0mr3fr3sht0k3n'
)
const response = await twitchRefresh(client_id, client_secret, 'twitchr4nd0mr3fr3sht0k3n')
return c.json(response)
})
app.get('/twitch/refresh/error', async (c) => {
@ -858,14 +854,14 @@ describe('OAuth Middleware', () => {
})
describe('twitchAuth middleware', () => {
it('Should work with custom state', async () => {
const res = await app.request('/twitch-custom-state')
expect(res).not.toBeNull()
expect(res.status).toBe(302)
const redirectLocation = res.headers.get('location')!
const redirectUrl = new URL(redirectLocation)
expect(redirectUrl.searchParams.get('state')).toBe('test-state')
})
it('Should work with custom state', async () => {
const res = await app.request('/twitch-custom-state')
expect(res).not.toBeNull()
expect(res.status).toBe(302)
const redirectLocation = res.headers.get('location')!
const redirectUrl = new URL(redirectLocation)
expect(redirectUrl.searchParams.get('state')).toBe('test-state')
})
})
describe('twitchAuth middleware', () => {
@ -970,7 +966,7 @@ describe('OAuth Middleware', () => {
const res = await twitchValidate('twitchr4nd0m4cc3sst0k3n')
expect(res).toEqual(twitchValidateSuccess)
})
it('Should throw error for invalid token', async () => {
const res = twitchValidate('invalid-token')
await expect(res).rejects.toThrow(twitchValidateError.message)

View File

@ -157,7 +157,14 @@ vi.mock(import('oauth4webapi'), async (importOriginal) => {
}
})
const { oidcAuthMiddleware, getAuth, processOAuthCallback, revokeSession, initOidcAuthMiddleware, getClient } = await import('../src')
const {
oidcAuthMiddleware,
getAuth,
processOAuthCallback,
revokeSession,
initOidcAuthMiddleware,
getClient,
} = await import('.')
const app = new Hono()
app.get('/logout', async (c) => {
@ -516,9 +523,7 @@ describe('processOAuthCallback()', () => {
expect(res).not.toBeNull()
expect(res.status).toBe(302)
expect(res.headers.get('set-cookie')).toMatch(
new RegExp(
`${MOCK_COOKIE_NAME}=[^;]+; Path=${defaultOidcAuthCookiePath}; HttpOnly; Secure`
)
new RegExp(`${MOCK_COOKIE_NAME}=[^;]+; Path=${defaultOidcAuthCookiePath}; HttpOnly; Secure`)
)
})
test('Should return an error if the state parameter does not match', async () => {
@ -600,16 +605,18 @@ describe('initOidcAuthMiddleware()', () => {
const CUSTOM_OIDC_CLIENT_ID = 'custom-client-id'
const CUSTOM_OIDC_CLIENT_SECRET = 'custom-client-secret'
const app = new Hono()
app.use(initOidcAuthMiddleware({
OIDC_CLIENT_ID: CUSTOM_OIDC_CLIENT_ID,
OIDC_CLIENT_SECRET: CUSTOM_OIDC_CLIENT_SECRET
}))
app.use(
initOidcAuthMiddleware({
OIDC_CLIENT_ID: CUSTOM_OIDC_CLIENT_ID,
OIDC_CLIENT_SECRET: CUSTOM_OIDC_CLIENT_SECRET,
})
)
app.use(async (c) => {
client = getClient(c)
return c.text('finished')
})
const req = new Request('http://localhost/', {
method: 'GET'
method: 'GET',
})
const res = await app.request(req, {}, {})
expect(res).not.toBeNull()

View File

@ -9,7 +9,7 @@ import {
ATTR_HTTP_ROUTE,
} from '@opentelemetry/semantic-conventions'
import { Hono } from 'hono'
import { otel } from '../src'
import { otel } from '.'
describe('OpenTelemetry middleware', () => {
const app = new Hono()

View File

@ -1,6 +1,6 @@
import { Hono } from 'hono'
import { reactRenderer, useRequestContext } from '../src/react-renderer'
import { reactRenderer, useRequestContext } from '.'
const RequestUrl = () => {
const c = useRequestContext()

View File

@ -2,11 +2,11 @@ import type { StandardSchemaV1 } from '@standard-schema/spec'
import { Hono } from 'hono'
import type { Equal, Expect, UnionToIntersection } from 'hono/utils/types'
import { vi } from 'vitest'
import { sValidator } from '../src'
import * as arktypeSchemas from './__schemas__/arktype'
import * as valibotSchemas from './__schemas__/valibot'
import * as zodSchemas from './__schemas__/zod'
import { sValidator } from '.'
type ExtractSchema<T> = T extends Hono<infer _, infer S> ? S : never
type MergeDiscriminatedUnion<U> = UnionToIntersection<U> extends infer O

View File

@ -1,5 +1,5 @@
import { Hono } from 'hono'
import { swaggerEditor } from '../src'
import { swaggerEditor } from '.'
describe('Swagger Editor Middleware', () => {
let app: Hono

View File

@ -1,5 +1,5 @@
import { Hono } from 'hono'
import { SwaggerUI, swaggerUI } from '../src'
import { SwaggerUI, swaggerUI } from '.'
describe('SwaggerUI Rendering', () => {
const url = 'https://petstore3.swagger.io/api/v3/openapi.json'

View File

@ -1,7 +1,7 @@
/*eslint quotes: ["off", "single"]*/
import type { DistSwaggerUIOptions } from '../src/swagger/renderer'
import { renderSwaggerUIOptions } from '../src/swagger/renderer'
import type { DistSwaggerUIOptions } from './swagger/renderer'
import { renderSwaggerUIOptions } from './swagger/renderer'
type TestCase = [description: string, config: DistSwaggerUIOptions, expected: string]
@ -189,29 +189,23 @@ describe('SwaggerUIOption Rendering', () => {
],
[
'filters out properties not in RENDER_TYPE_MAP',
{ url: baseUrl, title: 'My API', customProperty: 'value' } as DistSwaggerUIOptions & { title: string },
`url: '${baseUrl}'`
],
[
'filters out undefined values',
{ url: baseUrl, layout: undefined },
`url: '${baseUrl}'`
{ url: baseUrl, title: 'My API', customProperty: 'value' } as DistSwaggerUIOptions & {
title: string
},
`url: '${baseUrl}'`,
],
['filters out undefined values', { url: baseUrl, layout: undefined }, `url: '${baseUrl}'`],
[
'handles multiple invalid properties gracefully',
{
url: baseUrl,
{
url: baseUrl,
title: 'My API', // Not in RENDER_TYPE_MAP but used in HTML <title>
presets: null as unknown, // Invalid type
withCredentials: true
withCredentials: true,
} as DistSwaggerUIOptions & { title: string },
`url: '${baseUrl}',withCredentials: true`
`url: '${baseUrl}',withCredentials: true`,
],
[
'handles empty input gracefully',
{ url: '' },
`url: ''`
]
['handles empty input gracefully', { url: '' }, `url: ''`],
]
it.each(commonTests)('renders correctly with %s', (_, input, expected) => {

View File

@ -1,4 +1,4 @@
import { remoteAssets } from '../src/swagger/resource'
import { remoteAssets } from './swagger/resource'
describe('remoteAssets', () => {
it('should return default assets when no version is provided', () => {

View File

@ -1,6 +1,6 @@
import { initTRPC } from '@trpc/server'
import { Hono } from 'hono'
import { trpcServer } from '../src'
import { trpcServer } from '.'
describe('tRPC Adapter Middleware passing synchronous Context', () => {
type Env = {

View File

@ -1,7 +1,7 @@
import { initTRPC } from '@trpc/server'
import { Hono } from 'hono'
import { z } from 'zod'
import { trpcServer } from '../src'
import { trpcServer } from '.'
describe('tRPC Adapter Middleware', () => {
const t = initTRPC.create()

View File

@ -1,7 +1,7 @@
import 'reflect-metadata'
import { Hono } from 'hono'
import { injectable, inject } from 'tsyringe'
import { tsyringe } from '../src'
import { tsyringe } from '.'
class Config {
constructor(public readonly tenantName: string) {}

View File

@ -1,5 +1,5 @@
import { describe, it, expect, expectTypeOf } from 'vitest'
import { createRoute, z } from '../src/index'
import { createRoute, z } from '.'
describe('createRoute', () => {
it.each([

View File

@ -1,8 +1,8 @@
import type { MiddlewareHandler } from 'hono'
import type { Equal, Expect } from 'hono/utils/types'
import type { MiddlewareToHandlerType, OfHandlerType, RouteHandler } from '../src'
import type { MiddlewareToHandlerType, OfHandlerType, RouteHandler } from '.'
import { OpenAPIHono, createRoute, z } from '../src'
import { OpenAPIHono, createRoute, z } from '.'
describe('supports async handler', () => {
const route = createRoute({

View File

@ -2,8 +2,8 @@ import { createMiddleware } from 'hono/factory'
import type { ExtractSchema } from 'hono/types'
import type { Equal, Expect } from 'hono/utils/types'
import { assertType, describe, it } from 'vitest'
import { OpenAPIHono, createRoute, z } from '../src/index'
import type { MiddlewareToHandlerType, OfHandlerType } from '../src/index'
import { OpenAPIHono, createRoute, z } from './index'
import type { MiddlewareToHandlerType, OfHandlerType } from './index'
describe('Types', () => {
const RequestSchema = z.object({

View File

@ -7,8 +7,8 @@ import type { ServerErrorStatusCode } from 'hono/utils/http-status'
import type { Equal, Expect } from 'hono/utils/types'
import { describe, expect, expectTypeOf, it, vi } from 'vitest'
import { stringify } from 'yaml'
import type { RouteConfigToTypedResponse } from '../src/index'
import { OpenAPIHono, createRoute, z } from '../src/index'
import type { RouteConfigToTypedResponse } from './index'
import { OpenAPIHono, createRoute, z } from './index'
describe('Constructor', () => {
it('Should not require init object', () => {
@ -1073,7 +1073,6 @@ describe('Multi params', () => {
},
responses: {
200: {
// eslint-disable-next-line quotes
description: "Get the user's tag",
},
},
@ -1293,7 +1292,7 @@ describe('basePath()', () => {
return c.json({
param1: c.req.param('param1'),
param2: c.req.param('param2'),
param3: c.req.param('param3')
param3: c.req.param('param3'),
})
}
)
@ -1318,7 +1317,7 @@ describe('basePath()', () => {
expect(await res.json()).toEqual({
param1: 'foo',
param2: 'bar',
param3: 'baz'
param3: 'baz',
})
})
})

View File

@ -2,7 +2,7 @@ import { Hono } from 'hono'
import type { Equal, Expect } from 'hono/utils/types'
import { vi } from 'vitest'
import { z } from 'zod'
import { zValidator } from '../src'
import { zValidator } from '.'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type ExtractSchema<T> = T extends Hono<infer _, infer S> ? S : never

View File

@ -8612,6 +8612,7 @@ __metadata:
dependencies:
"@changesets/changelog-github": "npm:^0.4.8"
"@changesets/cli": "npm:^2.26.0"
"@cloudflare/vitest-pool-workers": "npm:^0.7.8"
"@cloudflare/workers-types": "npm:^4.20230307.0"
"@ryoppippi/unplugin-typia": "npm:^1.2.0"
"@types/node": "npm:^20.14.8"