@blastlabs/utils 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/routes/auth.d.ts +13 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +14 -0
- package/dist/routes/base.d.ts +7 -0
- package/dist/routes/base.d.ts.map +1 -0
- package/dist/routes/base.js +6 -0
- package/dist/routes/index.d.ts +33 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +22 -0
- package/dist/routes/post.d.ts +7 -0
- package/dist/routes/post.d.ts.map +1 -0
- package/dist/routes/post.js +8 -0
- package/dist/routes/types.d.ts +9 -0
- package/dist/routes/types.d.ts.map +1 -0
- package/dist/routes/types.js +4 -0
- package/dist/routes/users.example.d.ts +19 -0
- package/dist/routes/users.example.d.ts.map +1 -0
- package/dist/routes/users.example.js +20 -0
- package/dist/routes/utils/helpers.d.ts +43 -0
- package/dist/routes/utils/helpers.d.ts.map +1 -0
- package/dist/routes/utils/helpers.js +59 -0
- package/dist/routes/utils/helpers.test.d.ts +2 -0
- package/dist/routes/utils/helpers.test.d.ts.map +1 -0
- package/dist/routes/utils/helpers.test.js +106 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC;AAYvB,cAAc,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 인증 관련 라우트 경로
|
|
3
|
+
*/
|
|
4
|
+
export declare const AUTH_ROUTES: {
|
|
5
|
+
readonly ROOT: "/auth";
|
|
6
|
+
readonly LOGIN: string;
|
|
7
|
+
readonly REGISTER: string;
|
|
8
|
+
readonly FORGOT_PASSWORD: string;
|
|
9
|
+
readonly RESET_PASSWORD: string;
|
|
10
|
+
readonly VERIFY_EMAIL: string;
|
|
11
|
+
readonly VERIFY_OTP: string;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,eAAO,MAAM,WAAW;;;;;;;;CAQd,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 인증 관련 라우트 경로
|
|
3
|
+
*/
|
|
4
|
+
import { createRoute } from './utils/helpers';
|
|
5
|
+
const AUTH_BASE = '/auth';
|
|
6
|
+
export const AUTH_ROUTES = {
|
|
7
|
+
ROOT: AUTH_BASE,
|
|
8
|
+
LOGIN: createRoute(AUTH_BASE, '/login'),
|
|
9
|
+
REGISTER: createRoute(AUTH_BASE, '/register'),
|
|
10
|
+
FORGOT_PASSWORD: createRoute(AUTH_BASE, '/forgot-password'),
|
|
11
|
+
RESET_PASSWORD: createRoute(AUTH_BASE, '/reset-password'),
|
|
12
|
+
VERIFY_EMAIL: createRoute(AUTH_BASE, '/verify-email'),
|
|
13
|
+
VERIFY_OTP: createRoute(AUTH_BASE, '/verify-otp'),
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/routes/base.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,WAAW;;CAEd,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 애플리케이션 라우트 경로 상수
|
|
3
|
+
* Next.js App Router 기준으로 작성되었습니다.
|
|
4
|
+
*
|
|
5
|
+
* 사용 예시:
|
|
6
|
+
* - ROUTE_PATH.HOME
|
|
7
|
+
* - ROUTE_PATH.AUTH.LOGIN
|
|
8
|
+
* - withParam(ROUTE_PATH.USERS.DETAIL, { id: '123' })
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 라우트 경로 상수 객체
|
|
12
|
+
*/
|
|
13
|
+
export declare const ROUTE_PATH: {
|
|
14
|
+
readonly AUTH: {
|
|
15
|
+
readonly ROOT: "/auth";
|
|
16
|
+
readonly LOGIN: string;
|
|
17
|
+
readonly REGISTER: string;
|
|
18
|
+
readonly FORGOT_PASSWORD: string;
|
|
19
|
+
readonly RESET_PASSWORD: string;
|
|
20
|
+
readonly VERIFY_EMAIL: string;
|
|
21
|
+
readonly VERIFY_OTP: string;
|
|
22
|
+
};
|
|
23
|
+
readonly POST: {
|
|
24
|
+
readonly ROOT: "/post";
|
|
25
|
+
readonly LIST: "/post";
|
|
26
|
+
readonly CREATE: string;
|
|
27
|
+
readonly DETAIL: string;
|
|
28
|
+
};
|
|
29
|
+
readonly HOME: "/";
|
|
30
|
+
};
|
|
31
|
+
export { withParam, withQuery } from './utils/helpers';
|
|
32
|
+
export type { RoutePath } from './types';
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAIb,CAAC;AAGX,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGvD,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 애플리케이션 라우트 경로 상수
|
|
3
|
+
* Next.js App Router 기준으로 작성되었습니다.
|
|
4
|
+
*
|
|
5
|
+
* 사용 예시:
|
|
6
|
+
* - ROUTE_PATH.HOME
|
|
7
|
+
* - ROUTE_PATH.AUTH.LOGIN
|
|
8
|
+
* - withParam(ROUTE_PATH.USERS.DETAIL, { id: '123' })
|
|
9
|
+
*/
|
|
10
|
+
import { BASE_ROUTES } from './base';
|
|
11
|
+
import { AUTH_ROUTES } from './auth';
|
|
12
|
+
import { POST_ROUTES } from './post';
|
|
13
|
+
/**
|
|
14
|
+
* 라우트 경로 상수 객체
|
|
15
|
+
*/
|
|
16
|
+
export const ROUTE_PATH = {
|
|
17
|
+
...BASE_ROUTES,
|
|
18
|
+
AUTH: AUTH_ROUTES,
|
|
19
|
+
POST: POST_ROUTES,
|
|
20
|
+
};
|
|
21
|
+
// 유틸리티 함수 재내보내기
|
|
22
|
+
export { withParam, withQuery } from './utils/helpers';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/routes/post.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW;;;;;CAKd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/routes/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,UAAU,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 사용자 관련 라우트 경로 예시
|
|
3
|
+
*
|
|
4
|
+
* 새로운 도메인 라우트를 추가할 때 이 파일을 참고하세요.
|
|
5
|
+
*
|
|
6
|
+
* 사용 방법:
|
|
7
|
+
* 1. 이 파일을 users.ts로 이름 변경
|
|
8
|
+
* 2. routes/index.ts에서 import하여 ROUTE_PATH에 추가
|
|
9
|
+
*/
|
|
10
|
+
export declare const USERS_ROUTES: {
|
|
11
|
+
readonly ROOT: "/users";
|
|
12
|
+
readonly LIST: "/users";
|
|
13
|
+
readonly DETAIL: string;
|
|
14
|
+
readonly CREATE: string;
|
|
15
|
+
readonly EDIT: string;
|
|
16
|
+
readonly SETTINGS: string;
|
|
17
|
+
readonly PROFILE: string;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=users.example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.example.d.ts","sourceRoot":"","sources":["../../src/routes/users.example.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 사용자 관련 라우트 경로 예시
|
|
3
|
+
*
|
|
4
|
+
* 새로운 도메인 라우트를 추가할 때 이 파일을 참고하세요.
|
|
5
|
+
*
|
|
6
|
+
* 사용 방법:
|
|
7
|
+
* 1. 이 파일을 users.ts로 이름 변경
|
|
8
|
+
* 2. routes/index.ts에서 import하여 ROUTE_PATH에 추가
|
|
9
|
+
*/
|
|
10
|
+
import { createRoute } from './utils/helpers';
|
|
11
|
+
const USERS_BASE = '/users';
|
|
12
|
+
export const USERS_ROUTES = {
|
|
13
|
+
ROOT: USERS_BASE,
|
|
14
|
+
LIST: USERS_BASE,
|
|
15
|
+
DETAIL: createRoute(USERS_BASE, '/[id]'),
|
|
16
|
+
CREATE: createRoute(USERS_BASE, '/create'),
|
|
17
|
+
EDIT: createRoute(USERS_BASE, '/[id]/edit'),
|
|
18
|
+
SETTINGS: createRoute(USERS_BASE, '/[id]/settings'),
|
|
19
|
+
PROFILE: createRoute(USERS_BASE, '/profile'),
|
|
20
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 라우트 경로 관련 유틸리티 함수
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 동적 라우트 파라미터를 포함한 경로를 생성하는 헬퍼 함수
|
|
6
|
+
* @param path - 기본 경로 (예: '/users/[id]')
|
|
7
|
+
* @param params - 파라미터 객체 (예: { id: '123' })
|
|
8
|
+
* @returns 실제 경로 (예: '/users/123')
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const userPath = withParam('/users/[id]', { id: '123' });
|
|
13
|
+
* // '/users/123'
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function withParam<T extends string>(path: T, params: Record<string, string | number>): string;
|
|
17
|
+
/**
|
|
18
|
+
* 쿼리 파라미터를 포함한 경로를 생성하는 헬퍼 함수
|
|
19
|
+
* @param path - 기본 경로
|
|
20
|
+
* @param query - 쿼리 파라미터 객체
|
|
21
|
+
* @returns 쿼리 파라미터가 포함된 경로
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const searchPath = withQuery('/search', { q: 'test', page: 1 });
|
|
26
|
+
* // '/search?q=test&page=1'
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function withQuery(path: string, query: Record<string, string | number | boolean | null | undefined>): string;
|
|
30
|
+
/**
|
|
31
|
+
* 라우트 경로를 생성하는 헬퍼 함수
|
|
32
|
+
* @param base - 기본 경로
|
|
33
|
+
* @param path - 추가 경로
|
|
34
|
+
* @returns 합쳐진 경로
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const route = createRoute('/auth', '/login');
|
|
39
|
+
* // '/auth/login'
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function createRoute(base: string, path: string): string;
|
|
43
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/routes/utils/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EACxC,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GACtC,MAAM,CAMR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,GAClE,MAAM,CASR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 라우트 경로 관련 유틸리티 함수
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 동적 라우트 파라미터를 포함한 경로를 생성하는 헬퍼 함수
|
|
6
|
+
* @param path - 기본 경로 (예: '/users/[id]')
|
|
7
|
+
* @param params - 파라미터 객체 (예: { id: '123' })
|
|
8
|
+
* @returns 실제 경로 (예: '/users/123')
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const userPath = withParam('/users/[id]', { id: '123' });
|
|
13
|
+
* // '/users/123'
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function withParam(path, params) {
|
|
17
|
+
let result = path;
|
|
18
|
+
for (const [key, value] of Object.entries(params)) {
|
|
19
|
+
result = result.replace(`[${key}]`, String(value));
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 쿼리 파라미터를 포함한 경로를 생성하는 헬퍼 함수
|
|
25
|
+
* @param path - 기본 경로
|
|
26
|
+
* @param query - 쿼리 파라미터 객체
|
|
27
|
+
* @returns 쿼리 파라미터가 포함된 경로
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const searchPath = withQuery('/search', { q: 'test', page: 1 });
|
|
32
|
+
* // '/search?q=test&page=1'
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function withQuery(path, query) {
|
|
36
|
+
const searchParams = new URLSearchParams();
|
|
37
|
+
for (const [key, value] of Object.entries(query)) {
|
|
38
|
+
if (value !== null && value !== undefined) {
|
|
39
|
+
searchParams.append(key, String(value));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const queryString = searchParams.toString();
|
|
43
|
+
return queryString ? `${path}?${queryString}` : path;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 라우트 경로를 생성하는 헬퍼 함수
|
|
47
|
+
* @param base - 기본 경로
|
|
48
|
+
* @param path - 추가 경로
|
|
49
|
+
* @returns 합쳐진 경로
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const route = createRoute('/auth', '/login');
|
|
54
|
+
* // '/auth/login'
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function createRoute(base, path) {
|
|
58
|
+
return `${base}${path.startsWith('/') ? path : `/${path}`}`;
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.test.d.ts","sourceRoot":"","sources":["../../../src/routes/utils/helpers.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { withParam, withQuery, createRoute } from './helpers';
|
|
3
|
+
describe('routes/utils/helpers', () => {
|
|
4
|
+
describe('withParam', () => {
|
|
5
|
+
it('should replace single parameter', () => {
|
|
6
|
+
expect(withParam('/users/[id]', { id: '123' })).toBe('/users/123');
|
|
7
|
+
expect(withParam('/posts/[postId]', { postId: '456' })).toBe('/posts/456');
|
|
8
|
+
});
|
|
9
|
+
it('should replace multiple parameters', () => {
|
|
10
|
+
expect(withParam('/posts/[postId]/comments/[commentId]', {
|
|
11
|
+
postId: '456',
|
|
12
|
+
commentId: '789',
|
|
13
|
+
})).toBe('/posts/456/comments/789');
|
|
14
|
+
expect(withParam('/users/[userId]/posts/[postId]/comments/[commentId]', {
|
|
15
|
+
userId: '1',
|
|
16
|
+
postId: '2',
|
|
17
|
+
commentId: '3',
|
|
18
|
+
})).toBe('/users/1/posts/2/comments/3');
|
|
19
|
+
});
|
|
20
|
+
it('should handle parameters in any order', () => {
|
|
21
|
+
const path = '/posts/[postId]/comments/[commentId]';
|
|
22
|
+
// 순서대로
|
|
23
|
+
expect(withParam(path, { postId: '456', commentId: '789' })).toBe('/posts/456/comments/789');
|
|
24
|
+
// 반대 순서
|
|
25
|
+
expect(withParam(path, { commentId: '789', postId: '456' })).toBe('/posts/456/comments/789');
|
|
26
|
+
});
|
|
27
|
+
it('should handle nested key names safely', () => {
|
|
28
|
+
// id가 postId의 부분 문자열이지만 정확한 일치만 바꿈
|
|
29
|
+
expect(withParam('/posts/[id]/comments/[postId]', { id: '123', postId: '456' })).toBe('/posts/123/comments/456');
|
|
30
|
+
expect(withParam('/posts/[id]/comments/[postId]', { postId: '456', id: '123' })).toBe('/posts/123/comments/456');
|
|
31
|
+
});
|
|
32
|
+
it('should replace only first occurrence (using replace, not replaceAll)', () => {
|
|
33
|
+
// 현재 구현은 replace()를 사용하므로 첫 번째 매칭만 바뀝니다
|
|
34
|
+
expect(withParam('/[id]/[id]/[id]', { id: '123' })).toBe('/123/[id]/[id]');
|
|
35
|
+
});
|
|
36
|
+
it('should handle numeric values', () => {
|
|
37
|
+
expect(withParam('/users/[id]', { id: 123 })).toBe('/users/123');
|
|
38
|
+
expect(withParam('/posts/[postId]/comments/[commentId]', {
|
|
39
|
+
postId: 1,
|
|
40
|
+
commentId: 2,
|
|
41
|
+
})).toBe('/posts/1/comments/2');
|
|
42
|
+
});
|
|
43
|
+
it('should leave unmatched parameters as is', () => {
|
|
44
|
+
expect(withParam('/users/[id]', { userId: '123' })).toBe('/users/[id]');
|
|
45
|
+
expect(withParam('/posts/[postId]/comments/[commentId]', { id: '123' })).toBe('/posts/[postId]/comments/[commentId]');
|
|
46
|
+
});
|
|
47
|
+
it('should handle values with brackets correctly', () => {
|
|
48
|
+
// 값에 [id]가 있어도 이미 처리된 패턴은 다시 바뀌지 않음
|
|
49
|
+
expect(withParam('/[placeholder]/[actual]', { placeholder: 'fixed', actual: '[id]' })).toBe('/fixed/[id]');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('withQuery', () => {
|
|
53
|
+
it('should add single query parameter', () => {
|
|
54
|
+
expect(withQuery('/search', { q: 'test' })).toBe('/search?q=test');
|
|
55
|
+
expect(withQuery('/users', { page: 1 })).toBe('/users?page=1');
|
|
56
|
+
});
|
|
57
|
+
it('should add multiple query parameters', () => {
|
|
58
|
+
expect(withQuery('/search', { q: 'test', page: 1 })).toBe('/search?q=test&page=1');
|
|
59
|
+
expect(withQuery('/filter', { category: 'tech', sort: 'asc', limit: 10 })).toBe('/filter?category=tech&sort=asc&limit=10');
|
|
60
|
+
});
|
|
61
|
+
it('should handle numeric values', () => {
|
|
62
|
+
expect(withQuery('/users', { page: 1, limit: 20 })).toBe('/users?page=1&limit=20');
|
|
63
|
+
});
|
|
64
|
+
it('should handle boolean values', () => {
|
|
65
|
+
expect(withQuery('/posts', { featured: true, archived: false })).toBe('/posts?featured=true&archived=false');
|
|
66
|
+
});
|
|
67
|
+
it('should filter out null and undefined values', () => {
|
|
68
|
+
expect(withQuery('/search', { q: 'test', page: null, limit: undefined })).toBe('/search?q=test');
|
|
69
|
+
expect(withQuery('/users', { id: undefined })).toBe('/users');
|
|
70
|
+
});
|
|
71
|
+
it('should handle empty object', () => {
|
|
72
|
+
expect(withQuery('/users', {})).toBe('/users');
|
|
73
|
+
});
|
|
74
|
+
it('should append query string (does not merge with existing query)', () => {
|
|
75
|
+
// 현재 구현은 기존 쿼리 스트링을 병합하지 않고 뒤에 붙입니다
|
|
76
|
+
expect(withQuery('/search?existing=1', { new: 'value' })).toBe('/search?existing=1?new=value');
|
|
77
|
+
});
|
|
78
|
+
it('should combine withParam and withQuery', () => {
|
|
79
|
+
const path = withQuery(withParam('/users/[id]', { id: '123' }), { tab: 'profile' });
|
|
80
|
+
expect(path).toBe('/users/123?tab=profile');
|
|
81
|
+
const path2 = withQuery(withParam('/posts/[postId]/comments/[commentId]', {
|
|
82
|
+
postId: '456',
|
|
83
|
+
commentId: '789',
|
|
84
|
+
}), { sort: 'asc', page: 1 });
|
|
85
|
+
expect(path2).toBe('/posts/456/comments/789?sort=asc&page=1');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('createRoute', () => {
|
|
89
|
+
it('should combine base and path', () => {
|
|
90
|
+
expect(createRoute('/auth', '/login')).toBe('/auth/login');
|
|
91
|
+
expect(createRoute('/users', '/create')).toBe('/users/create');
|
|
92
|
+
});
|
|
93
|
+
it('should handle path without leading slash', () => {
|
|
94
|
+
expect(createRoute('/auth', 'login')).toBe('/auth/login');
|
|
95
|
+
expect(createRoute('/users', 'create')).toBe('/users/create');
|
|
96
|
+
});
|
|
97
|
+
it('should handle base with trailing slash', () => {
|
|
98
|
+
expect(createRoute('/auth/', '/login')).toBe('/auth//login');
|
|
99
|
+
expect(createRoute('/auth/', 'login')).toBe('/auth//login');
|
|
100
|
+
});
|
|
101
|
+
it('should handle multiple levels', () => {
|
|
102
|
+
expect(createRoute('/api/v1', '/users')).toBe('/api/v1/users');
|
|
103
|
+
expect(createRoute('/admin', '/settings/profile')).toBe('/admin/settings/profile');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|