Skip to content

Commit b8e9ed8

Browse files
✨ feat(Test): New test API is in development (Beta)
1 parent 6dd4bdf commit b8e9ed8

9 files changed

Lines changed: 120 additions & 119 deletions

File tree

deno.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@murat/yelix",
33
"exports": "./mod.ts",
4-
"version": "0.1.25",
4+
"version": "0.1.26",
55
"license": "MIT",
66
"nodeModulesDir": "auto",
77
"tasks": {
@@ -11,10 +11,10 @@
1111
"bump:minor": "deno run --allow-read --allow-write bump_version.ts minor",
1212
"bump:major": "deno run --allow-read --allow-write bump_version.ts major",
1313
"deploy": "deploy",
14-
"test": "deno test --allow-net --allow-read --allow-env",
14+
"test": "deno test --allow-net --allow-read --allow-env --ignore=./testing/",
1515
"test:testing": "deno test --allow-net --allow-read --allow-env ./testing",
16-
"test:watch": "deno test --watch --allow-net --allow-read --allow-env",
17-
"test:coverage": "deno test --coverage=coverage --allow-net --allow-read --allow-env",
16+
"test:watch": "deno test --watch --allow-net --allow-read --allow-env --ignore=./testing/",
17+
"test:coverage": "deno test --coverage=coverage --allow-net --allow-read --allow-env --ignore=./testing/",
1818
"test:coverage-html": "deno task test:coverage && deno coverage --html"
1919
},
2020
"imports": {

jsr.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@murat/yelix",
3-
"version": "0.1.25",
3+
"version": "0.1.26",
44
"license": "MIT",
55
"exports": {
66
".": "./mod.ts",

mod.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
type RuleResult,
2323
YelixValidationBase,
2424
} from "@/src/validation/ValidationBase.ts";
25-
import { YelixTestClient } from "@/src/test/testClient.ts";
25+
import { request, YelixTestClient } from "@/src/test/testClient.ts";
2626

2727
export {
2828
type CORSOptions,
@@ -33,6 +33,7 @@ export {
3333
inp,
3434
type Middleware,
3535
type OpenAPIDoc,
36+
request,
3637
// middlewares
3738
requestDataValidationMiddleware,
3839
simpleLoggerMiddeware,
@@ -41,7 +42,7 @@ export {
4142
Yelix,
4243
YelixCache,
4344
YelixInput,
45+
YelixTestClient,
4446
YelixValidationBase,
45-
YelixTestClient
4647
};
4748
export type { FailedMessage, InferYelixSchema, Rule, RuleResult };

readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ improve Yelix.
115115

116116
## Early Supporters
117117

118-
[@erenkulaksiz](https://github.com/erenkulaksiz), [@mertssmnoglu](https://github.com/mertssmnoglu)
118+
[@erenkulaksiz](https://github.com/erenkulaksiz),
119+
[@mertssmnoglu](https://github.com/mertssmnoglu)
119120

120121
## License
121122

src/test/store.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export class Store<T = any> {
2929
}
3030
}
3131

32-
3332
interface ExpireableStoreItem<T> {
3433
value: T;
3534
expireAt: number;
@@ -44,7 +43,10 @@ export class ExpireableStore<T = any> {
4443
}
4544

4645
set(key: string, value: T): void {
47-
const item: ExpireableStoreItem<T> = { value, expireAt: Date.now() + this.ttl };
46+
const item: ExpireableStoreItem<T> = {
47+
value,
48+
expireAt: Date.now() + this.ttl,
49+
};
4850
this.storage.set(key, item);
4951
}
5052

@@ -67,4 +69,4 @@ export class ExpireableStore<T = any> {
6769
has(key: string): boolean {
6870
return this.get(key) !== undefined;
6971
}
70-
}
72+
}

src/test/testClient.ts

Lines changed: 53 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,72 @@
11
// deno-lint-ignore-file no-explicit-any
2-
import type { Yelix } from '@/src/core/Yelix.ts';
3-
import { Store } from '@/src/test/store.ts';
4-
5-
type CleanupFuntion = (store?: Store<string | any>) => void | Promise<void>;
2+
import type { Yelix } from "@/src/core/Yelix.ts";
63

74
type Config = {
85
method: string;
96
} & RequestInit;
107

118
class YelixTestClient {
129
private app: Yelix | null = null;
13-
private dbCleanups: {
14-
title: string;
15-
fn: CleanupFuntion;
16-
}[] = [];
17-
18-
constructor() {
19-
this.dbCleanups = [];
20-
}
21-
public GlobalStore = new Store<string | any>();
2210

23-
setApp(app: Yelix) {
24-
this.app = app;
25-
}
11+
debugRoutes() {
12+
const app: any = this.app;
13+
if (!app) {
14+
throw new Error("No app found");
15+
}
16+
console.log("=== DEBUG ROUTE INFORMATION ===");
17+
console.log("Endpoints registered in Yelix:", app.endpointList);
2618

27-
cleanup(title: string, fn: CleanupFuntion) {
28-
this.dbCleanups.push({ title, fn });
19+
// Try to access Hono's internal route registry
20+
if (app.app && typeof app.app.routes === "function") {
21+
console.log("Hono routes:", app.app.routes());
22+
} else if (app.app && app.app._handlers) {
23+
console.log("Hono handlers:", app.app._handlers);
24+
} else {
25+
console.log("Unable to access Hono route registry");
26+
console.log("app.app structure:", Object.keys(app.app || {}));
27+
}
28+
29+
console.log("=== END DEBUG INFO ===");
2930
}
31+
}
3032

31-
async afterAll() {
32-
console.log('Cleaning up...', this.dbCleanups);
33-
for (const cleanup of this.dbCleanups) {
34-
console.log(`Cleaning up: ${cleanup.title}`);
35-
console.group();
36-
await cleanup.fn(this.GlobalStore);
37-
console.groupEnd();
38-
}
33+
async function request(app: Yelix, path: string, config: Config): Promise<any> {
34+
const hono = app.app;
35+
if (!hono) {
36+
throw new Error("No app found");
3937
}
4038

41-
async request(path: string, config?: Config) {
42-
const hono = this.app?.app;
43-
if (!hono) {
44-
throw new Error('No app found');
45-
}
39+
const res = await hono.request(path, config);
4640

47-
const res = await hono.request(path, config);
41+
if (!res) {
42+
throw new Error("No response");
43+
}
4844

49-
if (!res) {
50-
throw new Error('No response');
51-
}
52-
53-
let response;
54-
try {
55-
const clone = res.clone();
56-
response = await clone.json();
57-
} catch {
58-
response = await res.text();
59-
}
60-
61-
console.log(
62-
'REQUEST ',
63-
`${config?.method} ${path}`,
64-
config?.body && typeof config.body === 'string'
65-
? JSON.parse(config?.body)
66-
: {}
67-
);
68-
console.log('RESPONSE ', response);
69-
70-
return {
71-
req: res,
72-
res: {
73-
responseType: typeof response === 'string' ? 'text' : 'json',
74-
text: response,
75-
json: response
76-
},
77-
};
45+
let response;
46+
try {
47+
const clone = res.clone();
48+
response = await clone.json();
49+
} catch {
50+
response = await res.text();
7851
}
79-
52+
53+
console.log(
54+
"REQUEST ",
55+
`${config?.method} ${path}`,
56+
config?.body && typeof config.body === "string"
57+
? JSON.parse(config?.body)
58+
: {},
59+
);
60+
console.log("RESPONSE ", response);
61+
62+
return {
63+
req: res,
64+
res: {
65+
responseType: typeof response === "string" ? "text" : "json",
66+
text: response,
67+
json: response,
68+
},
69+
};
8070
}
8171

82-
export { YelixTestClient };
72+
export { request, YelixTestClient };

testing/main.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import {
44
type Middleware,
55
requestDataValidationMiddleware,
66
Yelix,
7-
} from '@/mod.ts';
8-
import * as path from 'jsr:@std/path@1.0.8';
9-
import type { OptionalAppConfigType } from '@/src/types/types.d.ts';
7+
} from "@/mod.ts";
8+
import * as path from "jsr:@std/path@1.0.8";
9+
import type { OptionalAppConfigType } from "@/src/types/types.d.ts";
1010

1111
type AppConfig = {
1212
yelix?: OptionalAppConfigType;
@@ -17,55 +17,53 @@ type AppConfig = {
1717

1818
export async function main(config?: AppConfig) {
1919
const currentDir = Deno.cwd();
20-
const API_Folder = path.join(currentDir, 'testing', 'api');
21-
22-
console.log('config', config);
20+
const API_Folder = path.join(currentDir, "testing", "api");
2321

2422
const app = new Yelix(
2523
config?.yelix ? config.yelix : {
2624
debug: false,
2725
port: 3030,
2826
watchDir: API_Folder,
29-
}
27+
},
3028
);
3129

3230
await app.loadEndpointsFromFolder(API_Folder);
3331

3432
app.initOpenAPI({
35-
path: '/docs',
36-
title: 'Yelix Testing API',
37-
description: 'This is a testing API for Yelix',
33+
path: "/docs",
34+
title: "Yelix Testing API",
35+
description: "This is a testing API for Yelix",
3836
servers: [
3937
{
40-
url: 'http://localhost:3030',
41-
description: 'Local Server _asd_ *askjads* **asdasda**',
38+
url: "http://localhost:3030",
39+
description: "Local Server _asd_ *askjads* **asdasda**",
4240
},
4341
{
44-
url: 'http://localhost:3080',
45-
description: 'Test Server',
42+
url: "http://localhost:3080",
43+
description: "Test Server",
4644
},
4745
],
4846
});
4947

50-
app.docsManager.YelixOpenAPI?.customValidationDescription('min', () => {
51-
return 'hello world!';
48+
app.docsManager.YelixOpenAPI?.customValidationDescription("min", () => {
49+
return "hello world!";
5250
});
5351

5452
const hello: Endpoint = {
55-
path: '/hello',
53+
path: "/hello",
5654
GET: (ctx: Ctx) => {
57-
return ctx.json({ message: 'Hello World!' });
55+
return ctx.json({ message: "Hello World!" });
5856
},
5957
};
6058
app.loadEndpoints([hello]);
6159

6260
const middleware: Middleware = (ctx, next) => {
63-
console.log('Middleware', ctx);
61+
console.log("Middleware", ctx);
6462
return next();
6563
};
66-
app.setMiddleware('test', middleware);
64+
app.setMiddleware("test", middleware);
6765

68-
app.setMiddleware('dataValidation', requestDataValidationMiddleware);
66+
app.setMiddleware("dataValidation", requestDataValidationMiddleware);
6967

7068
if (config?.app?.serve) {
7169
await app.serve();

testing/test/hello_test.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,47 @@
1-
import { main } from '../main.ts';
2-
import { describe, it, beforeAll, afterAll } from 'jsr:@std/testing/bdd';
3-
import { expect } from 'jsr:@std/expect';
4-
import { YelixTestClient } from "@/mod.ts";
1+
import { main } from "../main.ts";
2+
import { describe, it } from "jsr:@std/testing/bdd";
3+
import { expect } from "jsr:@std/expect";
4+
import { request } from "@/mod.ts";
55

6-
const test = new YelixTestClient();
7-
8-
beforeAll(async () => {
9-
const app = await main({
6+
async function getServer() {
7+
return await main({
108
yelix: {
11-
debug: false,
12-
port: 3030,
9+
noWelcome: true,
1310
},
1411
app: {
15-
serve: false,
12+
serve: true,
1613
},
1714
});
18-
test.setApp(app);
19-
});
15+
}
2016

21-
afterAll(test.afterAll);
17+
describe("Hello endpoint test", () => {
18+
it("GET /api/hello", async () => {
19+
const app = await getServer();
2220

23-
describe('Hello endpoint test', () => {
24-
test.cleanup('Killing email service', () => {
25-
const _data = test.GlobalStore.get('data');
26-
console.log('Data:', _data);
21+
const task = await request(app, "/api/hello?name=world", {
22+
method: "GET",
23+
});
24+
25+
expect(task.req.status).toBe(200);
26+
expect(task.res.responseType).toBe("text");
27+
expect(task.res.text).toBe("Hello, world");
28+
29+
await app.kill();
2730
});
31+
});
32+
33+
describe("Another Hello endpoint test", () => {
34+
it("GET /api/hello", async () => {
35+
const app = await getServer();
2836

29-
it('GET /api/hello', async () => {
30-
const task = await test.request('/api/hello?name=world');
37+
const task = await request(app, "/api/hello?name=world", {
38+
method: "GET",
39+
});
3140

3241
expect(task.req.status).toBe(200);
33-
expect(task.res.responseType).toBe('string');
34-
expect(await task.res.text).toBe('Hello, world');
42+
expect(task.res.responseType).toBe("text");
43+
expect(task.res.text).toBe("Hello, world");
3544

36-
test.GlobalStore.set('data', 'hello, world');
45+
await app.kill();
3746
});
3847
});

version.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const version = '0.1.25';
1+
const version = '0.1.26';
22
export default version;

0 commit comments

Comments
 (0)