@c-a-f/testing 1.0.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.
- package/.build/__tests__/react/renderWithCAF.spec.d.ts +1 -0
- package/.build/__tests__/react/renderWithCAF.spec.js +53 -0
- package/.build/index.d.ts +1 -0
- package/.build/index.js +1 -0
- package/.build/src/angular/createTestPloc.d.ts +19 -0
- package/.build/src/angular/createTestPloc.js +21 -0
- package/.build/src/angular/index.d.ts +12 -0
- package/.build/src/angular/index.js +12 -0
- package/.build/src/angular/mockUseCase.d.ts +32 -0
- package/.build/src/angular/mockUseCase.js +40 -0
- package/.build/src/angular/provideTestingCAF.d.ts +29 -0
- package/.build/src/angular/provideTestingCAF.js +26 -0
- package/.build/src/angular/waitForPlocState.d.ts +18 -0
- package/.build/src/angular/waitForPlocState.js +20 -0
- package/.build/src/core/IntegrationTestHelpers.d.ts +77 -0
- package/.build/src/core/IntegrationTestHelpers.js +78 -0
- package/.build/src/core/PlocTestHelpers.d.ts +133 -0
- package/.build/src/core/PlocTestHelpers.js +205 -0
- package/.build/src/core/PulseTestHelpers.d.ts +71 -0
- package/.build/src/core/PulseTestHelpers.js +106 -0
- package/.build/src/core/RepositoryTestHelpers.d.ts +48 -0
- package/.build/src/core/RepositoryTestHelpers.js +76 -0
- package/.build/src/core/RouteTestHelpers.d.ts +67 -0
- package/.build/src/core/RouteTestHelpers.js +94 -0
- package/.build/src/core/UseCaseTestHelpers.d.ts +100 -0
- package/.build/src/core/UseCaseTestHelpers.js +161 -0
- package/.build/src/core/index.d.ts +6 -0
- package/.build/src/core/index.js +6 -0
- package/.build/src/i18n/I18nTestHelpers.d.ts +76 -0
- package/.build/src/i18n/I18nTestHelpers.js +122 -0
- package/.build/src/i18n/index.d.ts +1 -0
- package/.build/src/i18n/index.js +1 -0
- package/.build/src/index.d.ts +5 -0
- package/.build/src/index.js +10 -0
- package/.build/src/permission/PermissionTestHelpers.d.ts +75 -0
- package/.build/src/permission/PermissionTestHelpers.js +121 -0
- package/.build/src/permission/index.d.ts +1 -0
- package/.build/src/permission/index.js +1 -0
- package/.build/src/react/createTestPloc.d.ts +19 -0
- package/.build/src/react/createTestPloc.js +21 -0
- package/.build/src/react/index.d.ts +12 -0
- package/.build/src/react/index.js +12 -0
- package/.build/src/react/mockUseCase.d.ts +36 -0
- package/.build/src/react/mockUseCase.js +44 -0
- package/.build/src/react/renderWithCAF.d.ts +31 -0
- package/.build/src/react/renderWithCAF.js +23 -0
- package/.build/src/react/waitForPlocState.d.ts +22 -0
- package/.build/src/react/waitForPlocState.js +24 -0
- package/.build/src/validation/ValidationTestHelpers.d.ts +66 -0
- package/.build/src/validation/ValidationTestHelpers.js +118 -0
- package/.build/src/validation/index.d.ts +1 -0
- package/.build/src/validation/index.js +1 -0
- package/.build/src/vue/createTestPloc.d.ts +19 -0
- package/.build/src/vue/createTestPloc.js +21 -0
- package/.build/src/vue/index.d.ts +12 -0
- package/.build/src/vue/index.js +12 -0
- package/.build/src/vue/mockUseCase.d.ts +34 -0
- package/.build/src/vue/mockUseCase.js +42 -0
- package/.build/src/vue/mountWithCAF.d.ts +31 -0
- package/.build/src/vue/mountWithCAF.js +40 -0
- package/.build/src/vue/waitForPlocState.d.ts +19 -0
- package/.build/src/vue/waitForPlocState.js +21 -0
- package/.build/src/workflow/WorkflowTestHelpers.d.ts +75 -0
- package/.build/src/workflow/WorkflowTestHelpers.js +146 -0
- package/.build/src/workflow/index.d.ts +1 -0
- package/.build/src/workflow/index.js +1 -0
- package/.build/vitest.config.d.ts +7 -0
- package/.build/vitest.config.js +6 -0
- package/README.md +598 -0
- package/package.json +127 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for UseCase.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for testing UseCase implementations.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockUseCase, createUseCaseTester } from '@c-a-f/testing/core';
|
|
9
|
+
* import { UseCase, RequestResult, pulse } from '@c-a-f/core';
|
|
10
|
+
*
|
|
11
|
+
* // Create a mock use case
|
|
12
|
+
* const mockUseCase = createMockUseCase<User[]>((args) => ({
|
|
13
|
+
* loading: pulse(false),
|
|
14
|
+
* data: pulse([{ id: '1', name: 'John' }]),
|
|
15
|
+
* error: pulse(null! as Error),
|
|
16
|
+
* }));
|
|
17
|
+
*
|
|
18
|
+
* // Test use case
|
|
19
|
+
* const tester = createUseCaseTester(mockUseCase);
|
|
20
|
+
* const result = await tester.execute([], { timeout: 1000 });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import type { UseCase, RequestResult } from '@c-a-f/core';
|
|
24
|
+
/**
|
|
25
|
+
* Mock UseCase implementation for testing.
|
|
26
|
+
*/
|
|
27
|
+
export declare class MockUseCase<A extends any[], T> implements UseCase<A, T> {
|
|
28
|
+
private implementation;
|
|
29
|
+
constructor(implementation: (...args: A) => Promise<RequestResult<T>> | RequestResult<T>);
|
|
30
|
+
execute(...args: A): Promise<RequestResult<T>>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a mock UseCase from an implementation.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createMockUseCase<A extends any[], T>(implementation: (...args: A) => Promise<RequestResult<T>> | RequestResult<T>): UseCase<A, T>;
|
|
36
|
+
/**
|
|
37
|
+
* Create a mock UseCase that always returns success with the given data.
|
|
38
|
+
* Useful for unit tests that do not care about loading/error states.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const useCase = createMockUseCaseSuccess([{ id: '1', name: 'John' }]);
|
|
43
|
+
* const result = await useCase.execute();
|
|
44
|
+
* expect(result.data.value).toEqual([{ id: '1', name: 'John' }]);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function createMockUseCaseSuccess<T>(data: T): UseCase<[], T>;
|
|
48
|
+
/**
|
|
49
|
+
* Create a mock UseCase that always returns the given error.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const useCase = createMockUseCaseError(new Error('Network failed'));
|
|
54
|
+
* const result = await useCase.execute();
|
|
55
|
+
* expect(result.error.value?.message).toBe('Network failed');
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function createMockUseCaseError<T = unknown>(error: Error): UseCase<[], T>;
|
|
59
|
+
/**
|
|
60
|
+
* Create a mock UseCase that returns loading then success (async).
|
|
61
|
+
* Useful for testing loading states.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createMockUseCaseAsync<T>(data: T, delayMs?: number): UseCase<[], T>;
|
|
64
|
+
/**
|
|
65
|
+
* UseCase tester utility.
|
|
66
|
+
*/
|
|
67
|
+
export declare class UseCaseTester<A extends any[], T> {
|
|
68
|
+
readonly useCase: UseCase<A, T>;
|
|
69
|
+
constructor(useCase: UseCase<A, T>);
|
|
70
|
+
/**
|
|
71
|
+
* Execute the use case and wait for completion.
|
|
72
|
+
*/
|
|
73
|
+
execute(args: A, options?: {
|
|
74
|
+
timeout?: number;
|
|
75
|
+
}): Promise<RequestResult<T>>;
|
|
76
|
+
/**
|
|
77
|
+
* Execute the use case and extract data.
|
|
78
|
+
*/
|
|
79
|
+
executeAndGetData(args: A): Promise<T>;
|
|
80
|
+
/**
|
|
81
|
+
* Execute the use case and check if it succeeds.
|
|
82
|
+
*/
|
|
83
|
+
executeAndCheckSuccess(args: A): Promise<boolean>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create a UseCase tester instance.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createUseCaseTester<A extends any[], T>(useCase: UseCase<A, T>): UseCaseTester<A, T>;
|
|
89
|
+
/**
|
|
90
|
+
* Create a successful RequestResult.
|
|
91
|
+
*/
|
|
92
|
+
export declare function createSuccessResult<T>(data: T): RequestResult<T>;
|
|
93
|
+
/**
|
|
94
|
+
* Create a failed RequestResult.
|
|
95
|
+
*/
|
|
96
|
+
export declare function createErrorResult<T>(error: Error): RequestResult<T>;
|
|
97
|
+
/**
|
|
98
|
+
* Create a loading RequestResult.
|
|
99
|
+
*/
|
|
100
|
+
export declare function createLoadingResult<T>(): RequestResult<T>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for UseCase.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for testing UseCase implementations.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockUseCase, createUseCaseTester } from '@c-a-f/testing/core';
|
|
9
|
+
* import { UseCase, RequestResult, pulse } from '@c-a-f/core';
|
|
10
|
+
*
|
|
11
|
+
* // Create a mock use case
|
|
12
|
+
* const mockUseCase = createMockUseCase<User[]>((args) => ({
|
|
13
|
+
* loading: pulse(false),
|
|
14
|
+
* data: pulse([{ id: '1', name: 'John' }]),
|
|
15
|
+
* error: pulse(null! as Error),
|
|
16
|
+
* }));
|
|
17
|
+
*
|
|
18
|
+
* // Test use case
|
|
19
|
+
* const tester = createUseCaseTester(mockUseCase);
|
|
20
|
+
* const result = await tester.execute([], { timeout: 1000 });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { pulse } from '@c-a-f/core';
|
|
24
|
+
/**
|
|
25
|
+
* Mock UseCase implementation for testing.
|
|
26
|
+
*/
|
|
27
|
+
export class MockUseCase {
|
|
28
|
+
implementation;
|
|
29
|
+
constructor(implementation) {
|
|
30
|
+
this.implementation = implementation;
|
|
31
|
+
}
|
|
32
|
+
async execute(...args) {
|
|
33
|
+
return await this.implementation(...args);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create a mock UseCase from an implementation.
|
|
38
|
+
*/
|
|
39
|
+
export function createMockUseCase(implementation) {
|
|
40
|
+
return new MockUseCase(implementation);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create a mock UseCase that always returns success with the given data.
|
|
44
|
+
* Useful for unit tests that do not care about loading/error states.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const useCase = createMockUseCaseSuccess([{ id: '1', name: 'John' }]);
|
|
49
|
+
* const result = await useCase.execute();
|
|
50
|
+
* expect(result.data.value).toEqual([{ id: '1', name: 'John' }]);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function createMockUseCaseSuccess(data) {
|
|
54
|
+
return new MockUseCase(() => createSuccessResult(data));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a mock UseCase that always returns the given error.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* const useCase = createMockUseCaseError(new Error('Network failed'));
|
|
62
|
+
* const result = await useCase.execute();
|
|
63
|
+
* expect(result.error.value?.message).toBe('Network failed');
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function createMockUseCaseError(error) {
|
|
67
|
+
return new MockUseCase(() => createErrorResult(error));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create a mock UseCase that returns loading then success (async).
|
|
71
|
+
* Useful for testing loading states.
|
|
72
|
+
*/
|
|
73
|
+
export function createMockUseCaseAsync(data, delayMs = 0) {
|
|
74
|
+
return new MockUseCase(() => new Promise((resolve) => {
|
|
75
|
+
if (delayMs <= 0) {
|
|
76
|
+
resolve(createSuccessResult(data));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
setTimeout(() => resolve(createSuccessResult(data)), delayMs);
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* UseCase tester utility.
|
|
85
|
+
*/
|
|
86
|
+
export class UseCaseTester {
|
|
87
|
+
useCase;
|
|
88
|
+
constructor(useCase) {
|
|
89
|
+
this.useCase = useCase;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Execute the use case and wait for completion.
|
|
93
|
+
*/
|
|
94
|
+
async execute(args, options) {
|
|
95
|
+
const timeout = options?.timeout || 5000;
|
|
96
|
+
return Promise.race([
|
|
97
|
+
this.useCase.execute(...args),
|
|
98
|
+
new Promise((_, reject) => {
|
|
99
|
+
setTimeout(() => reject(new Error(`UseCase execution timeout (${timeout}ms)`)), timeout);
|
|
100
|
+
}),
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Execute the use case and extract data.
|
|
105
|
+
*/
|
|
106
|
+
async executeAndGetData(args) {
|
|
107
|
+
const result = await this.execute(args);
|
|
108
|
+
if (result.error.value) {
|
|
109
|
+
throw result.error.value;
|
|
110
|
+
}
|
|
111
|
+
return result.data.value;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Execute the use case and check if it succeeds.
|
|
115
|
+
*/
|
|
116
|
+
async executeAndCheckSuccess(args) {
|
|
117
|
+
try {
|
|
118
|
+
const result = await this.execute(args);
|
|
119
|
+
return !result.error.value;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Create a UseCase tester instance.
|
|
128
|
+
*/
|
|
129
|
+
export function createUseCaseTester(useCase) {
|
|
130
|
+
return new UseCaseTester(useCase);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Create a successful RequestResult.
|
|
134
|
+
*/
|
|
135
|
+
export function createSuccessResult(data) {
|
|
136
|
+
return {
|
|
137
|
+
loading: pulse(false),
|
|
138
|
+
data: pulse(data),
|
|
139
|
+
error: pulse(null),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Create a failed RequestResult.
|
|
144
|
+
*/
|
|
145
|
+
export function createErrorResult(error) {
|
|
146
|
+
return {
|
|
147
|
+
loading: pulse(false),
|
|
148
|
+
data: pulse(null),
|
|
149
|
+
error: pulse(error),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create a loading RequestResult.
|
|
154
|
+
*/
|
|
155
|
+
export function createLoadingResult() {
|
|
156
|
+
return {
|
|
157
|
+
loading: pulse(true),
|
|
158
|
+
data: pulse(null),
|
|
159
|
+
error: pulse(null),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for I18n.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for testing translation managers and translators.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockTranslator, createTranslationTester } from '@c-a-f/testing/i18n';
|
|
9
|
+
* import { TranslationManager } from '@c-a-f/i18n';
|
|
10
|
+
*
|
|
11
|
+
* const mockTranslator = createMockTranslator({
|
|
12
|
+
* en: { 'greeting': 'Hello', 'welcome': 'Welcome {{name}}' },
|
|
13
|
+
* fa: { 'greeting': 'سلام', 'welcome': 'خوش آمدید {{name}}' },
|
|
14
|
+
* });
|
|
15
|
+
* const manager = new TranslationManager(mockTranslator);
|
|
16
|
+
* const tester = createTranslationTester(manager);
|
|
17
|
+
*
|
|
18
|
+
* expect(tester.t('greeting')).toBe('Hello');
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import type { ITranslator, TranslationManager } from '@c-a-f/i18n';
|
|
22
|
+
/**
|
|
23
|
+
* Mock Translator implementation for testing.
|
|
24
|
+
*/
|
|
25
|
+
export declare class MockTranslator implements ITranslator {
|
|
26
|
+
private translations;
|
|
27
|
+
private currentLanguage;
|
|
28
|
+
constructor(translations?: Record<string, Record<string, string>>, currentLanguage?: string);
|
|
29
|
+
translate(key: string, options?: Record<string, unknown>): string;
|
|
30
|
+
getCurrentLanguage(): string;
|
|
31
|
+
changeLanguage(language: string): Promise<void>;
|
|
32
|
+
exists(key: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Add translations (for testing).
|
|
35
|
+
*/
|
|
36
|
+
addTranslations(language: string, translations: Record<string, string>): void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a mock Translator.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createMockTranslator(translations?: Record<string, Record<string, string>>, initialLanguage?: string): MockTranslator;
|
|
42
|
+
/**
|
|
43
|
+
* Translation tester utility.
|
|
44
|
+
*/
|
|
45
|
+
export declare class TranslationTester {
|
|
46
|
+
readonly manager: TranslationManager;
|
|
47
|
+
constructor(manager: TranslationManager);
|
|
48
|
+
/**
|
|
49
|
+
* Translate a key.
|
|
50
|
+
*/
|
|
51
|
+
t(key: string, options?: Record<string, unknown>): string;
|
|
52
|
+
/**
|
|
53
|
+
* Translate with values.
|
|
54
|
+
*/
|
|
55
|
+
translateWithValues(key: string, values: Record<string, unknown>): string;
|
|
56
|
+
/**
|
|
57
|
+
* Translate plural.
|
|
58
|
+
*/
|
|
59
|
+
translatePlural(key: string, count: number, options?: Record<string, unknown>): string;
|
|
60
|
+
/**
|
|
61
|
+
* Get current language.
|
|
62
|
+
*/
|
|
63
|
+
getCurrentLanguage(): string;
|
|
64
|
+
/**
|
|
65
|
+
* Change language.
|
|
66
|
+
*/
|
|
67
|
+
changeLanguage(language: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Check if key exists.
|
|
70
|
+
*/
|
|
71
|
+
hasKey(key: string): boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create a Translation tester instance.
|
|
75
|
+
*/
|
|
76
|
+
export declare function createTranslationTester(manager: TranslationManager): TranslationTester;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for I18n.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for testing translation managers and translators.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockTranslator, createTranslationTester } from '@c-a-f/testing/i18n';
|
|
9
|
+
* import { TranslationManager } from '@c-a-f/i18n';
|
|
10
|
+
*
|
|
11
|
+
* const mockTranslator = createMockTranslator({
|
|
12
|
+
* en: { 'greeting': 'Hello', 'welcome': 'Welcome {{name}}' },
|
|
13
|
+
* fa: { 'greeting': 'سلام', 'welcome': 'خوش آمدید {{name}}' },
|
|
14
|
+
* });
|
|
15
|
+
* const manager = new TranslationManager(mockTranslator);
|
|
16
|
+
* const tester = createTranslationTester(manager);
|
|
17
|
+
*
|
|
18
|
+
* expect(tester.t('greeting')).toBe('Hello');
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Mock Translator implementation for testing.
|
|
23
|
+
*/
|
|
24
|
+
export class MockTranslator {
|
|
25
|
+
translations;
|
|
26
|
+
currentLanguage;
|
|
27
|
+
constructor(translations = {}, currentLanguage = 'en') {
|
|
28
|
+
this.translations = translations;
|
|
29
|
+
this.currentLanguage = currentLanguage;
|
|
30
|
+
}
|
|
31
|
+
translate(key, options) {
|
|
32
|
+
const langTranslations = this.translations[this.currentLanguage] || {};
|
|
33
|
+
let text = langTranslations[key] || key;
|
|
34
|
+
// Simple interpolation
|
|
35
|
+
if (options) {
|
|
36
|
+
Object.keys(options).forEach((k) => {
|
|
37
|
+
if (k !== 'ns' && k !== 'defaultValue' && k !== 'count' && k !== 'returnObjects') {
|
|
38
|
+
const value = String(options[k]);
|
|
39
|
+
text = text.replace(new RegExp(`{{${k}}}`, 'g'), value);
|
|
40
|
+
text = text.replace(new RegExp(`\\{${k}\\}`, 'g'), value);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return text;
|
|
45
|
+
}
|
|
46
|
+
getCurrentLanguage() {
|
|
47
|
+
return this.currentLanguage;
|
|
48
|
+
}
|
|
49
|
+
async changeLanguage(language) {
|
|
50
|
+
this.currentLanguage = language;
|
|
51
|
+
}
|
|
52
|
+
exists(key) {
|
|
53
|
+
const langTranslations = this.translations[this.currentLanguage] || {};
|
|
54
|
+
return key in langTranslations;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Add translations (for testing).
|
|
58
|
+
*/
|
|
59
|
+
addTranslations(language, translations) {
|
|
60
|
+
if (!this.translations[language]) {
|
|
61
|
+
this.translations[language] = {};
|
|
62
|
+
}
|
|
63
|
+
this.translations[language] = { ...this.translations[language], ...translations };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create a mock Translator.
|
|
68
|
+
*/
|
|
69
|
+
export function createMockTranslator(translations = {}, initialLanguage = 'en') {
|
|
70
|
+
return new MockTranslator(translations, initialLanguage);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Translation tester utility.
|
|
74
|
+
*/
|
|
75
|
+
export class TranslationTester {
|
|
76
|
+
manager;
|
|
77
|
+
constructor(manager) {
|
|
78
|
+
this.manager = manager;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Translate a key.
|
|
82
|
+
*/
|
|
83
|
+
t(key, options) {
|
|
84
|
+
return this.manager.t(key, options);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Translate with values.
|
|
88
|
+
*/
|
|
89
|
+
translateWithValues(key, values) {
|
|
90
|
+
return this.manager.translateWithValues(key, values);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Translate plural.
|
|
94
|
+
*/
|
|
95
|
+
translatePlural(key, count, options) {
|
|
96
|
+
return this.manager.translatePlural(key, count, options);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get current language.
|
|
100
|
+
*/
|
|
101
|
+
getCurrentLanguage() {
|
|
102
|
+
return this.manager.getCurrentLanguage();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Change language.
|
|
106
|
+
*/
|
|
107
|
+
async changeLanguage(language) {
|
|
108
|
+
await this.manager.changeLanguage(language);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if key exists.
|
|
112
|
+
*/
|
|
113
|
+
hasKey(key) {
|
|
114
|
+
return this.manager.hasKey(key);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create a Translation tester instance.
|
|
119
|
+
*/
|
|
120
|
+
export function createTranslationTester(manager) {
|
|
121
|
+
return new TranslationTester(manager);
|
|
122
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './I18nTestHelpers';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './I18nTestHelpers';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Core testing utilities
|
|
2
|
+
export * from './core';
|
|
3
|
+
// Workflow testing utilities
|
|
4
|
+
export * from './workflow';
|
|
5
|
+
// Permission testing utilities
|
|
6
|
+
export * from './permission';
|
|
7
|
+
// I18n testing utilities
|
|
8
|
+
export * from './i18n';
|
|
9
|
+
// Validation testing utilities
|
|
10
|
+
export * from './validation';
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for Permission.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for testing permission checkers and managers.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockPermissionChecker, createPermissionTester } from '@c-a-f/testing/permission';
|
|
9
|
+
* import { PermissionManager } from '@c-a-f/permission';
|
|
10
|
+
*
|
|
11
|
+
* const mockChecker = createMockPermissionChecker(['user.edit', 'post.create']);
|
|
12
|
+
* const manager = new PermissionManager(mockChecker);
|
|
13
|
+
* const tester = createPermissionTester(manager);
|
|
14
|
+
*
|
|
15
|
+
* expect(await tester.hasPermission('user.edit')).toBe(true);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import type { IPermissionChecker, PermissionResult, PermissionManager } from '@c-a-f/permission';
|
|
19
|
+
/**
|
|
20
|
+
* Mock PermissionChecker implementation for testing.
|
|
21
|
+
*/
|
|
22
|
+
export declare class MockPermissionChecker implements IPermissionChecker {
|
|
23
|
+
private allowedPermissions;
|
|
24
|
+
constructor(allowedPermissions?: string[]);
|
|
25
|
+
check(permission: string): PermissionResult;
|
|
26
|
+
checkAny(permissions: string[]): PermissionResult;
|
|
27
|
+
checkAll(permissions: string[]): PermissionResult;
|
|
28
|
+
/**
|
|
29
|
+
* Add a permission (for testing).
|
|
30
|
+
*/
|
|
31
|
+
addPermission(permission: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Remove a permission (for testing).
|
|
34
|
+
*/
|
|
35
|
+
removePermission(permission: string): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a mock PermissionChecker.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createMockPermissionChecker(allowedPermissions?: string[]): MockPermissionChecker;
|
|
41
|
+
/**
|
|
42
|
+
* Permission tester utility.
|
|
43
|
+
*/
|
|
44
|
+
export declare class PermissionTester {
|
|
45
|
+
readonly manager: PermissionManager;
|
|
46
|
+
constructor(manager: PermissionManager);
|
|
47
|
+
/**
|
|
48
|
+
* Check if permission is granted.
|
|
49
|
+
*/
|
|
50
|
+
hasPermission(permission: string): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if any permission is granted.
|
|
53
|
+
*/
|
|
54
|
+
hasAnyPermission(permissions: string[]): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* Check if all permissions are granted.
|
|
57
|
+
*/
|
|
58
|
+
hasAllPermissions(permissions: string[]): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Require permission (throws if denied).
|
|
61
|
+
*/
|
|
62
|
+
requirePermission(permission: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Require any permission (throws if all denied).
|
|
65
|
+
*/
|
|
66
|
+
requireAnyPermission(permissions: string[]): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Require all permissions (throws if any denied).
|
|
69
|
+
*/
|
|
70
|
+
requireAllPermissions(permissions: string[]): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a Permission tester instance.
|
|
74
|
+
*/
|
|
75
|
+
export declare function createPermissionTester(manager: PermissionManager): PermissionTester;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for Permission.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for testing permission checkers and managers.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockPermissionChecker, createPermissionTester } from '@c-a-f/testing/permission';
|
|
9
|
+
* import { PermissionManager } from '@c-a-f/permission';
|
|
10
|
+
*
|
|
11
|
+
* const mockChecker = createMockPermissionChecker(['user.edit', 'post.create']);
|
|
12
|
+
* const manager = new PermissionManager(mockChecker);
|
|
13
|
+
* const tester = createPermissionTester(manager);
|
|
14
|
+
*
|
|
15
|
+
* expect(await tester.hasPermission('user.edit')).toBe(true);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Mock PermissionChecker implementation for testing.
|
|
20
|
+
*/
|
|
21
|
+
export class MockPermissionChecker {
|
|
22
|
+
allowedPermissions;
|
|
23
|
+
constructor(allowedPermissions = []) {
|
|
24
|
+
this.allowedPermissions = allowedPermissions;
|
|
25
|
+
}
|
|
26
|
+
check(permission) {
|
|
27
|
+
const granted = this.allowedPermissions.includes(permission);
|
|
28
|
+
return {
|
|
29
|
+
granted,
|
|
30
|
+
reason: granted ? undefined : `Permission '${permission}' not granted`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
checkAny(permissions) {
|
|
34
|
+
const granted = permissions.some(p => this.allowedPermissions.includes(p));
|
|
35
|
+
return {
|
|
36
|
+
granted,
|
|
37
|
+
reason: granted ? undefined : 'None of the permissions are granted',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
checkAll(permissions) {
|
|
41
|
+
const missing = permissions.filter(p => !this.allowedPermissions.includes(p));
|
|
42
|
+
return {
|
|
43
|
+
granted: missing.length === 0,
|
|
44
|
+
reason: missing.length > 0 ? `Missing permissions: ${missing.join(', ')}` : undefined,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Add a permission (for testing).
|
|
49
|
+
*/
|
|
50
|
+
addPermission(permission) {
|
|
51
|
+
if (!this.allowedPermissions.includes(permission)) {
|
|
52
|
+
this.allowedPermissions.push(permission);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Remove a permission (for testing).
|
|
57
|
+
*/
|
|
58
|
+
removePermission(permission) {
|
|
59
|
+
const index = this.allowedPermissions.indexOf(permission);
|
|
60
|
+
if (index > -1) {
|
|
61
|
+
this.allowedPermissions.splice(index, 1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a mock PermissionChecker.
|
|
67
|
+
*/
|
|
68
|
+
export function createMockPermissionChecker(allowedPermissions = []) {
|
|
69
|
+
return new MockPermissionChecker(allowedPermissions);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Permission tester utility.
|
|
73
|
+
*/
|
|
74
|
+
export class PermissionTester {
|
|
75
|
+
manager;
|
|
76
|
+
constructor(manager) {
|
|
77
|
+
this.manager = manager;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check if permission is granted.
|
|
81
|
+
*/
|
|
82
|
+
async hasPermission(permission) {
|
|
83
|
+
return await this.manager.hasPermission(permission);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if any permission is granted.
|
|
87
|
+
*/
|
|
88
|
+
async hasAnyPermission(permissions) {
|
|
89
|
+
return await this.manager.hasAnyPermission(permissions);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check if all permissions are granted.
|
|
93
|
+
*/
|
|
94
|
+
async hasAllPermissions(permissions) {
|
|
95
|
+
return await this.manager.hasAllPermissions(permissions);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Require permission (throws if denied).
|
|
99
|
+
*/
|
|
100
|
+
async requirePermission(permission) {
|
|
101
|
+
await this.manager.requirePermission(permission);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Require any permission (throws if all denied).
|
|
105
|
+
*/
|
|
106
|
+
async requireAnyPermission(permissions) {
|
|
107
|
+
await this.manager.requireAnyPermission(permissions);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Require all permissions (throws if any denied).
|
|
111
|
+
*/
|
|
112
|
+
async requireAllPermissions(permissions) {
|
|
113
|
+
await this.manager.requireAllPermissions(permissions);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create a Permission tester instance.
|
|
118
|
+
*/
|
|
119
|
+
export function createPermissionTester(manager) {
|
|
120
|
+
return new PermissionTester(manager);
|
|
121
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PermissionTestHelpers';
|