@nlabs/reaktor 0.10.0 → 0.10.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/.env +1 -0
- package/.env.example +1 -0
- package/DATABASE_I18N_GUIDE.md +434 -0
- package/TEST_UTILITIES_GUIDE.md +360 -0
- package/coverage/index.html +46 -76
- package/index.js +1 -1
- package/jest.config.js +17 -0
- package/jest.setup.js +36 -0
- package/lex.config.cjs +2 -2
- package/lib/actions/apps.js +17 -239
- package/lib/actions/connections.js +6 -89
- package/lib/actions/content.js +17 -0
- package/lib/actions/conversations.js +19 -336
- package/lib/actions/dynamodb.js +2 -150
- package/lib/actions/email.js +2 -152
- package/lib/actions/files.js +5 -283
- package/lib/actions/groups.js +19 -259
- package/lib/actions/images.js +31 -700
- package/lib/actions/index.js +2 -66
- package/lib/actions/ios.js +9 -162
- package/lib/actions/locations.js +7 -122
- package/lib/actions/messages.js +21 -196
- package/lib/actions/notifications.js +2 -59
- package/lib/actions/payments.js +11 -464
- package/lib/actions/posts.js +75 -527
- package/lib/actions/profiles.js +8 -0
- package/lib/actions/reactions.js +25 -312
- package/lib/actions/s3.js +2 -133
- package/lib/actions/search.js +5 -90
- package/lib/actions/sms.js +2 -108
- package/lib/actions/statistics.js +6 -60
- package/lib/actions/subscriptions.js +12 -0
- package/lib/actions/tags.js +19 -287
- package/lib/actions/users.js +64 -764
- package/lib/actions/websockets.js +14 -158
- package/lib/adapters/arangoAdapter.js +2 -46
- package/lib/adapters/contentAdapter.js +2 -0
- package/lib/adapters/fileAdapter.js +2 -76
- package/lib/adapters/imageAdapter.js +2 -40
- package/lib/adapters/messageAdapter.js +2 -49
- package/lib/adapters/postAdapter.js +2 -70
- package/lib/adapters/reaktorAdapter.js +2 -44
- package/lib/adapters/tagAdapter.js +2 -50
- package/lib/adapters/userAdapter.js +2 -115
- package/lib/config.js +2 -125
- package/lib/handlers/graphqlHandler.js +2 -0
- package/lib/index.js +2 -66
- package/lib/lambdas/actions/websockets.js +14 -116
- package/lib/lambdas/authorizer.js +2 -67
- package/lib/lambdas/connection.js +2 -91
- package/lib/lambdas/utils/message.js +2 -42
- package/lib/lambdas/utils/websocket.js +2 -105
- package/lib/mocks/conversation.js +2 -35
- package/lib/mocks/file.js +2 -38
- package/lib/mocks/group.js +2 -47
- package/lib/mocks/image.js +2 -44
- package/lib/mocks/post.js +2 -55
- package/lib/mocks/tag.js +2 -37
- package/lib/mocks/user.js +2 -88
- package/lib/mutations/index.js +2 -26
- package/lib/mutations/locations.integration.js +2 -0
- package/lib/mutations/locations.js +2 -44
- package/lib/mutations/messages.integration.js +2 -0
- package/lib/mutations/messages.js +2 -86
- package/lib/mutations/posts.integration.js +2 -0
- package/lib/mutations/posts.js +2 -53
- package/lib/mutations/profiles.integration.js +2 -0
- package/lib/mutations/profiles.js +2 -0
- package/lib/mutations/reactions.integration.js +2 -0
- package/lib/mutations/reactions.js +2 -51
- package/lib/mutations/statistics.integration.js +2 -0
- package/lib/mutations/statistics.js +2 -39
- package/lib/mutations/subscriptions.integration.js +2 -0
- package/lib/mutations/subscriptions.js +2 -56
- package/lib/mutations/tags.integration.js +2 -0
- package/lib/mutations/tags.js +2 -120
- package/lib/mutations/users.integration.js +2 -0
- package/lib/mutations/users.js +2 -116
- package/lib/objectTypes/app.js +2 -173
- package/lib/objectTypes/bankAccount.js +2 -76
- package/lib/objectTypes/connection.js +2 -48
- package/lib/objectTypes/conversation.js +2 -77
- package/lib/objectTypes/creditCard.js +2 -86
- package/lib/objectTypes/document.js +2 -46
- package/lib/objectTypes/error.js +2 -46
- package/lib/objectTypes/external.js +2 -74
- package/lib/objectTypes/file.js +2 -100
- package/lib/objectTypes/filter.js +2 -43
- package/lib/objectTypes/group.js +2 -123
- package/lib/objectTypes/iapSubscription.js +2 -40
- package/lib/objectTypes/image.js +2 -129
- package/lib/objectTypes/index.js +2 -68
- package/lib/objectTypes/location.js +2 -109
- package/lib/objectTypes/message.js +2 -96
- package/lib/objectTypes/passcode.js +2 -42
- package/lib/objectTypes/plan.js +2 -95
- package/lib/objectTypes/post.js +2 -125
- package/lib/objectTypes/profile.js +2 -0
- package/lib/objectTypes/reaction.js +2 -61
- package/lib/objectTypes/relation.js +2 -49
- package/lib/objectTypes/search.js +2 -72
- package/lib/objectTypes/statistics.js +2 -39
- package/lib/objectTypes/subscription.js +2 -117
- package/lib/objectTypes/tag.js +2 -65
- package/lib/objectTypes/user.js +2 -144
- package/lib/queries/index.js +2 -33
- package/lib/queries/locations.integration.js +2 -0
- package/lib/queries/locations.js +2 -45
- package/lib/queries/messages.integration.js +2 -0
- package/lib/queries/messages.js +2 -52
- package/lib/queries/posts.integration.js +2 -0
- package/lib/queries/posts.js +2 -154
- package/lib/queries/reactions.integration.js +2 -0
- package/lib/queries/reactions.js +2 -56
- package/lib/queries/statistics.js +2 -39
- package/lib/queries/subscriptions.js +2 -44
- package/lib/queries/tags.integration.js +2 -0
- package/lib/queries/tags.js +2 -75
- package/lib/queries/users.integration.js +2 -0
- package/lib/queries/users.js +2 -64
- package/lib/templates/email/layout.js +3 -25
- package/lib/templates/email/passwordForgot.js +3 -25
- package/lib/templates/email/passwordRecovery.js +3 -25
- package/lib/templates/email/verifyEmail.js +3 -25
- package/lib/templates/email/welcome.js +3 -25
- package/lib/templates/sms/passwordForgot.js +2 -24
- package/lib/templates/sms/passwordRecovery.js +2 -24
- package/lib/templates/sms/verifyEmail.js +2 -24
- package/lib/templates/sms/verifyPhone.js +2 -24
- package/lib/templates/sms/welcome.js +2 -24
- package/lib/types/apps.types.js +2 -32
- package/lib/types/arangodb.types.js +1 -16
- package/lib/types/auth.types.js +1 -16
- package/lib/types/connections.types.js +1 -16
- package/lib/types/content.types.js +1 -0
- package/lib/types/conversations.types.js +1 -16
- package/lib/types/email.types.js +1 -16
- package/lib/types/error.types.js +2 -44
- package/lib/types/files.types.js +1 -16
- package/lib/types/google.types.js +1 -16
- package/lib/types/groups.types.js +1 -16
- package/lib/types/images.types.js +1 -16
- package/lib/types/index.js +2 -60
- package/lib/types/locations.types.js +1 -16
- package/lib/types/messages.types.js +1 -16
- package/lib/types/notifications.types.js +1 -16
- package/lib/types/payments.types.js +1 -16
- package/lib/types/posts.types.js +1 -16
- package/lib/types/profiles.types.js +1 -0
- package/lib/types/statistics.types.js +1 -16
- package/lib/types/tags.types.js +1 -16
- package/lib/types/users.types.js +1 -16
- package/lib/types/websockets.types.js +1 -16
- package/lib/utils/adapterUtils.js +2 -45
- package/lib/utils/analyticsUtils.js +2 -72
- package/lib/utils/arangodbUtils.js +5 -163
- package/lib/utils/authUtils.js +2 -0
- package/lib/utils/contextUtils.js +2 -0
- package/lib/utils/dbI18n.example.js +6 -0
- package/lib/utils/dbI18n.js +2 -0
- package/lib/utils/googleTranslate.js +2 -0
- package/lib/utils/graphqlUtils.js +2 -0
- package/lib/utils/index.js +2 -30
- package/lib/utils/languageDetection.js +2 -0
- package/lib/utils/localeUtils.example.js +2 -0
- package/lib/utils/localeUtils.js +2 -0
- package/lib/utils/middlewareUtils.js +2 -0
- package/lib/utils/sessionUtils.js +2 -0
- package/lib/utils/stripeUtils.js +2 -43
- package/lib/utils/templateUtils.js +2 -0
- package/lib/utils/testUtils.js +2 -0
- package/lib/utils/translationQueue.example.js +2 -0
- package/lib/utils/translationQueue.js +2 -0
- package/package.json +27 -24
- package/.prettierrc.js +0 -4
- package/lib/actions/apps.d.ts +0 -25
- package/lib/actions/connections.d.ts +0 -4
- package/lib/actions/conversations.d.ts +0 -14
- package/lib/actions/dynamodb.d.ts +0 -8
- package/lib/actions/email.d.ts +0 -5
- package/lib/actions/files.d.ts +0 -19
- package/lib/actions/groups.d.ts +0 -14
- package/lib/actions/images.d.ts +0 -26
- package/lib/actions/index.d.ts +0 -23
- package/lib/actions/ios.d.ts +0 -7
- package/lib/actions/locations.d.ts +0 -6
- package/lib/actions/messages.d.ts +0 -14
- package/lib/actions/notifications.d.ts +0 -5
- package/lib/actions/payments.d.ts +0 -10
- package/lib/actions/personas.d.ts +0 -3
- package/lib/actions/personas.js +0 -110
- package/lib/actions/posts.d.ts +0 -22
- package/lib/actions/reactions.d.ts +0 -30
- package/lib/actions/s3.d.ts +0 -7
- package/lib/actions/search.d.ts +0 -3
- package/lib/actions/sms.d.ts +0 -9
- package/lib/actions/statistics.d.ts +0 -3
- package/lib/actions/subscription.d.ts +0 -7
- package/lib/actions/subscription.js +0 -208
- package/lib/actions/tags.d.ts +0 -34
- package/lib/actions/users.d.ts +0 -72
- package/lib/actions/websockets.d.ts +0 -20
- package/lib/adapters/arangoAdapter.d.ts +0 -2
- package/lib/adapters/fileAdapter.d.ts +0 -3
- package/lib/adapters/imageAdapter.d.ts +0 -2
- package/lib/adapters/messageAdapter.d.ts +0 -2
- package/lib/adapters/postAdapter.d.ts +0 -2
- package/lib/adapters/reaktorAdapter.d.ts +0 -6
- package/lib/adapters/tagAdapter.d.ts +0 -2
- package/lib/adapters/userAdapter.d.ts +0 -2
- package/lib/config.d.ts +0 -20
- package/lib/index.d.ts +0 -12
- package/lib/lambdas/actions/websockets.d.ts +0 -7
- package/lib/lambdas/authorizer.d.ts +0 -20
- package/lib/lambdas/connection.d.ts +0 -12
- package/lib/lambdas/utils/message.d.ts +0 -1
- package/lib/lambdas/utils/websocket.d.ts +0 -7
- package/lib/mocks/conversation.d.ts +0 -8
- package/lib/mocks/file.d.ts +0 -11
- package/lib/mocks/group.d.ts +0 -17
- package/lib/mocks/image.d.ts +0 -3
- package/lib/mocks/post.d.ts +0 -38
- package/lib/mocks/tag.d.ts +0 -2
- package/lib/mocks/user.d.ts +0 -4
- package/lib/mutations/index.d.ts +0 -3
- package/lib/mutations/locations.d.ts +0 -2
- package/lib/mutations/messages.d.ts +0 -2
- package/lib/mutations/personas.d.ts +0 -2
- package/lib/mutations/personas.js +0 -100
- package/lib/mutations/posts.d.ts +0 -2
- package/lib/mutations/reactions.d.ts +0 -2
- package/lib/mutations/statistics.d.ts +0 -2
- package/lib/mutations/subscriptions.d.ts +0 -2
- package/lib/mutations/tags.d.ts +0 -2
- package/lib/mutations/users.d.ts +0 -1
- package/lib/objectTypes/app.d.ts +0 -3
- package/lib/objectTypes/bankAccount.d.ts +0 -1
- package/lib/objectTypes/connection.d.ts +0 -1
- package/lib/objectTypes/conversation.d.ts +0 -2
- package/lib/objectTypes/creditCard.d.ts +0 -1
- package/lib/objectTypes/document.d.ts +0 -1
- package/lib/objectTypes/error.d.ts +0 -1
- package/lib/objectTypes/external.d.ts +0 -1
- package/lib/objectTypes/file.d.ts +0 -2
- package/lib/objectTypes/filter.d.ts +0 -1
- package/lib/objectTypes/group.d.ts +0 -3
- package/lib/objectTypes/iapSubscription.d.ts +0 -1
- package/lib/objectTypes/image.d.ts +0 -2
- package/lib/objectTypes/index.d.ts +0 -24
- package/lib/objectTypes/location.d.ts +0 -2
- package/lib/objectTypes/message.d.ts +0 -2
- package/lib/objectTypes/passcode.d.ts +0 -1
- package/lib/objectTypes/persona.d.ts +0 -3
- package/lib/objectTypes/persona.js +0 -87
- package/lib/objectTypes/plan.d.ts +0 -2
- package/lib/objectTypes/post.d.ts +0 -2
- package/lib/objectTypes/reaction.d.ts +0 -2
- package/lib/objectTypes/relation.d.ts +0 -1
- package/lib/objectTypes/search.d.ts +0 -1
- package/lib/objectTypes/statistics.d.ts +0 -1
- package/lib/objectTypes/subscription.d.ts +0 -2
- package/lib/objectTypes/tag.d.ts +0 -2
- package/lib/objectTypes/user.d.ts +0 -4
- package/lib/queries/index.d.ts +0 -3
- package/lib/queries/locations.d.ts +0 -2
- package/lib/queries/messages.d.ts +0 -2
- package/lib/queries/posts.d.ts +0 -2
- package/lib/queries/reactions.d.ts +0 -2
- package/lib/queries/statistics.d.ts +0 -2
- package/lib/queries/subscriptions.d.ts +0 -2
- package/lib/queries/tags.d.ts +0 -2
- package/lib/queries/users.d.ts +0 -1
- package/lib/templates/email/layout.d.ts +0 -2
- package/lib/templates/email/passwordForgot.d.ts +0 -2
- package/lib/templates/email/passwordRecovery.d.ts +0 -2
- package/lib/templates/email/verifyEmail.d.ts +0 -2
- package/lib/templates/email/welcome.d.ts +0 -2
- package/lib/templates/sms/passwordForgot.d.ts +0 -2
- package/lib/templates/sms/passwordRecovery.d.ts +0 -2
- package/lib/templates/sms/verifyEmail.d.ts +0 -2
- package/lib/templates/sms/verifyPhone.d.ts +0 -2
- package/lib/templates/sms/welcome.d.ts +0 -2
- package/lib/types/apps.types.d.ts +0 -46
- package/lib/types/arangodb.types.d.ts +0 -34
- package/lib/types/auth.types.d.ts +0 -9
- package/lib/types/connections.types.d.ts +0 -5
- package/lib/types/conversations.types.d.ts +0 -27
- package/lib/types/email.types.d.ts +0 -13
- package/lib/types/error.types.d.ts +0 -20
- package/lib/types/files.types.d.ts +0 -23
- package/lib/types/google.types.d.ts +0 -29
- package/lib/types/groups.types.d.ts +0 -18
- package/lib/types/images.types.d.ts +0 -52
- package/lib/types/index.d.ts +0 -20
- package/lib/types/locations.types.d.ts +0 -18
- package/lib/types/messages.types.d.ts +0 -16
- package/lib/types/notifications.types.d.ts +0 -19
- package/lib/types/payments.types.d.ts +0 -109
- package/lib/types/personas.types.d.ts +0 -32
- package/lib/types/personas.types.js +0 -16
- package/lib/types/posts.types.d.ts +0 -28
- package/lib/types/statistics.types.d.ts +0 -3
- package/lib/types/tags.types.d.ts +0 -15
- package/lib/types/users.types.d.ts +0 -79
- package/lib/types/websockets.types.d.ts +0 -18
- package/lib/utils/adapterUtils.d.ts +0 -1
- package/lib/utils/analyticsUtils.d.ts +0 -21
- package/lib/utils/arangodbUtils.d.ts +0 -66
- package/lib/utils/auth.d.ts +0 -21
- package/lib/utils/auth.js +0 -57
- package/lib/utils/index.d.ts +0 -5
- package/lib/utils/session.d.ts +0 -18
- package/lib/utils/session.js +0 -60
- package/lib/utils/stripeUtils.d.ts +0 -3
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# Test Utilities Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to use the test utilities in `src/utils/testUtils.ts` to optimize and consolidate your GraphQL query and mutation tests.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The test utilities provide a standardized way to create tests for GraphQL resolvers, reducing code duplication and improving maintainability. They abstract common testing patterns into reusable functions.
|
|
8
|
+
|
|
9
|
+
## Available Utilities
|
|
10
|
+
|
|
11
|
+
### 1. Mock Context and Resolve Info
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createMockContext, createMockResolveInfo } from '../utils/testUtils';
|
|
15
|
+
|
|
16
|
+
// Create a standard mock context
|
|
17
|
+
const context = createMockContext();
|
|
18
|
+
|
|
19
|
+
// Create a custom context with overrides
|
|
20
|
+
const customContext = createMockContext({
|
|
21
|
+
databaseName: 'custom-db',
|
|
22
|
+
session: { userId: 'custom-user' }
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Create mock resolve info for GraphQL resolvers
|
|
26
|
+
const resolveInfo = createMockResolveInfo('fieldName');
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Mock Data Generators
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import {
|
|
33
|
+
createMockUser,
|
|
34
|
+
createMockPost,
|
|
35
|
+
createMockMessage,
|
|
36
|
+
createMockReaction,
|
|
37
|
+
createMockTag
|
|
38
|
+
} from '../utils/testUtils';
|
|
39
|
+
|
|
40
|
+
// Create mock data with defaults
|
|
41
|
+
const user = createMockUser();
|
|
42
|
+
const post = createMockPost();
|
|
43
|
+
|
|
44
|
+
// Create mock data with custom values
|
|
45
|
+
const customUser = createMockUser({
|
|
46
|
+
userId: 'custom-id',
|
|
47
|
+
email: 'custom@example.com'
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Mock Setup Utilities
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { mockActionsModule, mockObjectType, setupCommonMocks } from '../utils/testUtils';
|
|
55
|
+
|
|
56
|
+
// Mock actions module
|
|
57
|
+
mockActionsModule('../actions/users', {
|
|
58
|
+
getUser: jest.fn(),
|
|
59
|
+
getSessionUser: jest.fn()
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Mock object types
|
|
63
|
+
mockObjectType('../objectTypes/user', 'user');
|
|
64
|
+
|
|
65
|
+
// Setup common mocks (auth utils, etc.)
|
|
66
|
+
setupCommonMocks();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Test Suite Creators
|
|
70
|
+
|
|
71
|
+
### 1. Query Test Suite
|
|
72
|
+
|
|
73
|
+
Use `createQueryTestSuite` for testing GraphQL query resolvers:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { createQueryTestSuite, createMockUser } from '../utils/testUtils';
|
|
77
|
+
|
|
78
|
+
// Mock dependencies
|
|
79
|
+
mockActionsModule('../actions/users', {
|
|
80
|
+
getUser: jest.fn(),
|
|
81
|
+
getSessionUser: jest.fn()
|
|
82
|
+
});
|
|
83
|
+
mockObjectType('../objectTypes/user', 'user');
|
|
84
|
+
|
|
85
|
+
// Define test cases
|
|
86
|
+
const testCases = [
|
|
87
|
+
{
|
|
88
|
+
name: 'getUserByEmail',
|
|
89
|
+
actionName: 'getUser',
|
|
90
|
+
args: { email: 'test@example.com' },
|
|
91
|
+
expectedCall: (context: any, args: any) => ({ email: args.email }),
|
|
92
|
+
mockReturnValue: createMockUser(),
|
|
93
|
+
errorCase: true
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'getUserById',
|
|
97
|
+
actionName: 'getUser',
|
|
98
|
+
args: { userId: 'user1' },
|
|
99
|
+
expectedCall: (context: any, args: any) => ({ userId: args.userId }),
|
|
100
|
+
mockReturnValue: createMockUser(),
|
|
101
|
+
errorCase: true
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
// Create the test suite
|
|
106
|
+
createQueryTestSuite(
|
|
107
|
+
'User Queries',
|
|
108
|
+
'../actions/users',
|
|
109
|
+
'../objectTypes/user',
|
|
110
|
+
'user',
|
|
111
|
+
testCases
|
|
112
|
+
);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 2. Mutation Test Suite
|
|
116
|
+
|
|
117
|
+
Use `createMutationTestSuite` for testing GraphQL mutation resolvers:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { createMutationTestSuite, createMockUser, setupCommonMocks } from '../utils/testUtils';
|
|
121
|
+
|
|
122
|
+
// Setup common mocks
|
|
123
|
+
setupCommonMocks();
|
|
124
|
+
|
|
125
|
+
// Mock mutations module (complex setup)
|
|
126
|
+
jest.mock('./users', () => ({
|
|
127
|
+
userMutations: {
|
|
128
|
+
getField: jest.fn((fieldName) => ({
|
|
129
|
+
resolve: jest.fn(async (context, args) => {
|
|
130
|
+
const actions = require('../actions/users');
|
|
131
|
+
return await actions[fieldName](context, args);
|
|
132
|
+
})
|
|
133
|
+
}))
|
|
134
|
+
}
|
|
135
|
+
}));
|
|
136
|
+
|
|
137
|
+
// Define test cases
|
|
138
|
+
const testCases = [
|
|
139
|
+
{
|
|
140
|
+
name: 'addUser',
|
|
141
|
+
actionName: 'addUser',
|
|
142
|
+
args: { username: 'testuser', email: 'test@example.com' },
|
|
143
|
+
expectedCall: (context: any, args: any) => args,
|
|
144
|
+
mockReturnValue: createMockUser()
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: 'deactivateUser',
|
|
148
|
+
actionName: 'deactivateUser',
|
|
149
|
+
args: { userId: 'user1' },
|
|
150
|
+
expectedCall: (context: any, args: any) => args,
|
|
151
|
+
mockReturnValue: createMockUser(),
|
|
152
|
+
requiresAuth: true,
|
|
153
|
+
authUserId: 'user1'
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
// Create the test suite
|
|
158
|
+
createMutationTestSuite(
|
|
159
|
+
'User',
|
|
160
|
+
'../actions/users',
|
|
161
|
+
'./users',
|
|
162
|
+
testCases
|
|
163
|
+
);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 3. Integration Test Suite
|
|
167
|
+
|
|
168
|
+
Use `createIntegrationTestSuite` for testing integration scenarios:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { createIntegrationTestSuite, createMockUser } from '../utils/testUtils';
|
|
172
|
+
|
|
173
|
+
// Define test cases
|
|
174
|
+
const testCases = [
|
|
175
|
+
{
|
|
176
|
+
name: 'getUserByEmail',
|
|
177
|
+
actionName: 'getUser',
|
|
178
|
+
args: { email: 'test@example.com' },
|
|
179
|
+
expectedCall: (context: any, args: any) => ({ email: args.email }),
|
|
180
|
+
successReturnValue: createMockUser(),
|
|
181
|
+
errorReturnValue: null,
|
|
182
|
+
testErrorCase: true
|
|
183
|
+
}
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
// Create the integration test suite
|
|
187
|
+
createIntegrationTestSuite(
|
|
188
|
+
'User',
|
|
189
|
+
'../actions/users',
|
|
190
|
+
'../objectTypes/user',
|
|
191
|
+
'user',
|
|
192
|
+
testCases
|
|
193
|
+
);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Test Case Configuration
|
|
197
|
+
|
|
198
|
+
### Query Test Cases
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
{
|
|
202
|
+
name: string; // Test name
|
|
203
|
+
actionName: string; // Action function name
|
|
204
|
+
args: any; // Arguments to pass
|
|
205
|
+
expectedCall: (context: any, args: any) => any; // Expected call parameters
|
|
206
|
+
mockReturnValue?: any; // Mock return value
|
|
207
|
+
errorCase?: boolean; // Whether to test error handling
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Mutation Test Cases
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
{
|
|
215
|
+
name: string; // Test name
|
|
216
|
+
actionName: string; // Action function name
|
|
217
|
+
args: any; // Arguments to pass
|
|
218
|
+
expectedCall: (context: any, args: any) => any; // Expected call parameters
|
|
219
|
+
mockReturnValue?: any; // Mock return value
|
|
220
|
+
requiresAuth?: boolean; // Whether authentication is required
|
|
221
|
+
authUserId?: string; // User ID for auth check
|
|
222
|
+
errorCase?: boolean; // Whether to test error handling
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Integration Test Cases
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
{
|
|
230
|
+
name: string; // Test name
|
|
231
|
+
actionName: string; // Action function name
|
|
232
|
+
args: any; // Arguments to pass
|
|
233
|
+
expectedCall: (context: any, args: any) => any; // Expected call parameters
|
|
234
|
+
successReturnValue?: any; // Success case return value
|
|
235
|
+
errorReturnValue?: any; // Error case return value
|
|
236
|
+
testErrorCase?: boolean; // Whether to test error scenarios
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Migration Guide
|
|
241
|
+
|
|
242
|
+
### From Manual Tests to Utilities
|
|
243
|
+
|
|
244
|
+
**Before (Manual):**
|
|
245
|
+
```typescript
|
|
246
|
+
describe('User Queries', () => {
|
|
247
|
+
const mockContext = {
|
|
248
|
+
databaseName: 'test',
|
|
249
|
+
session: { userId: 'user1', username: 'testuser', userAccess: 1 }
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
beforeEach(() => {
|
|
253
|
+
jest.clearAllMocks();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe('getUserByEmail', () => {
|
|
257
|
+
it('should call getUser action with email parameter', async () => {
|
|
258
|
+
const mockUser = { userId: 'user1', email: 'test@example.com' };
|
|
259
|
+
const { getUser } = require('../actions/users');
|
|
260
|
+
getUser.mockResolvedValue(mockUser);
|
|
261
|
+
|
|
262
|
+
const result = await getUser(mockContext, { email: 'test@example.com' });
|
|
263
|
+
|
|
264
|
+
expect(getUser).toHaveBeenCalledWith(mockContext, { email: 'test@example.com' });
|
|
265
|
+
expect(result).toEqual(mockUser);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**After (Using Utilities):**
|
|
272
|
+
```typescript
|
|
273
|
+
import { createQueryTestSuite, createMockUser } from '../utils/testUtils';
|
|
274
|
+
|
|
275
|
+
const testCases = [
|
|
276
|
+
{
|
|
277
|
+
name: 'getUserByEmail',
|
|
278
|
+
actionName: 'getUser',
|
|
279
|
+
args: { email: 'test@example.com' },
|
|
280
|
+
expectedCall: (context: any, args: any) => ({ email: args.email }),
|
|
281
|
+
mockReturnValue: createMockUser()
|
|
282
|
+
}
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
createQueryTestSuite('User Queries', '../actions/users', '../objectTypes/user', 'user', testCases);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Benefits
|
|
289
|
+
|
|
290
|
+
1. **Reduced Code Duplication**: Common test patterns are abstracted into reusable functions
|
|
291
|
+
2. **Consistent Testing**: All tests follow the same structure and patterns
|
|
292
|
+
3. **Easier Maintenance**: Changes to test patterns only need to be made in one place
|
|
293
|
+
4. **Better Readability**: Test intentions are clearer with declarative test case definitions
|
|
294
|
+
5. **Faster Development**: New tests can be created quickly by defining test cases
|
|
295
|
+
|
|
296
|
+
## Best Practices
|
|
297
|
+
|
|
298
|
+
1. **Use Descriptive Names**: Make test case names clear and descriptive
|
|
299
|
+
2. **Group Related Tests**: Use the suite name to group related functionality
|
|
300
|
+
3. **Test Both Success and Error Cases**: Include error handling tests where appropriate
|
|
301
|
+
4. **Use Mock Data Generators**: Use the provided mock data generators for consistent test data
|
|
302
|
+
5. **Keep Test Cases Focused**: Each test case should test one specific scenario
|
|
303
|
+
|
|
304
|
+
## Example: Complete Optimized Test File
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
import {
|
|
308
|
+
createQueryTestSuite,
|
|
309
|
+
createMockUser,
|
|
310
|
+
mockActionsModule,
|
|
311
|
+
mockObjectType
|
|
312
|
+
} from '../utils/testUtils';
|
|
313
|
+
|
|
314
|
+
// Mock dependencies
|
|
315
|
+
mockActionsModule('../actions/users', {
|
|
316
|
+
getUser: jest.fn(),
|
|
317
|
+
getSessionUser: jest.fn()
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
mockObjectType('../objectTypes/user', 'user');
|
|
321
|
+
|
|
322
|
+
// Define test cases
|
|
323
|
+
const userQueryTestCases = [
|
|
324
|
+
{
|
|
325
|
+
name: 'getUserByEmail',
|
|
326
|
+
actionName: 'getUser',
|
|
327
|
+
args: { email: 'test@example.com' },
|
|
328
|
+
expectedCall: (context: any, args: any) => ({ email: args.email }),
|
|
329
|
+
mockReturnValue: createMockUser(),
|
|
330
|
+
errorCase: true
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
name: 'getUserById',
|
|
334
|
+
actionName: 'getUser',
|
|
335
|
+
args: { userId: 'user1' },
|
|
336
|
+
expectedCall: (context: any, args: any) => ({ userId: args.userId }),
|
|
337
|
+
mockReturnValue: createMockUser(),
|
|
338
|
+
errorCase: true
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
name: 'getUserBySession',
|
|
342
|
+
actionName: 'getSessionUser',
|
|
343
|
+
args: {},
|
|
344
|
+
expectedCall: (context: any, args: any) => ({}),
|
|
345
|
+
mockReturnValue: createMockUser(),
|
|
346
|
+
errorCase: true
|
|
347
|
+
}
|
|
348
|
+
];
|
|
349
|
+
|
|
350
|
+
// Create the test suite
|
|
351
|
+
createQueryTestSuite(
|
|
352
|
+
'User Queries',
|
|
353
|
+
'../actions/users',
|
|
354
|
+
'../objectTypes/user',
|
|
355
|
+
'user',
|
|
356
|
+
userQueryTestCases
|
|
357
|
+
);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
This approach reduces the original 130-line test file to just 40 lines while maintaining the same test coverage and functionality.
|
package/coverage/index.html
CHANGED
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">78.94% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>2414/3058</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">64.96% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>777/1196</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">
|
|
40
|
+
<span class="strong">75.51% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>512/678</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">77.19% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>2126/2754</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
</div>
|
|
62
62
|
</template>
|
|
63
63
|
</div>
|
|
64
|
-
<div class='status-line
|
|
64
|
+
<div class='status-line medium'></div>
|
|
65
65
|
<div class="pad1">
|
|
66
66
|
<table class="coverage-summary">
|
|
67
67
|
<thead>
|
|
@@ -84,43 +84,43 @@
|
|
|
84
84
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
85
85
|
</td>
|
|
86
86
|
<td data-value="100" class="pct high">100%</td>
|
|
87
|
-
<td data-value="
|
|
87
|
+
<td data-value="17" class="abs high">17/17</td>
|
|
88
|
+
<td data-value="86.66" class="pct high">86.66%</td>
|
|
89
|
+
<td data-value="15" class="abs high">13/15</td>
|
|
88
90
|
<td data-value="100" class="pct high">100%</td>
|
|
89
|
-
<td data-value="
|
|
90
|
-
<td data-value="100" class="pct high">100%</td>
|
|
91
|
-
<td data-value="2" class="abs high">2/2</td>
|
|
91
|
+
<td data-value="4" class="abs high">4/4</td>
|
|
92
92
|
<td data-value="100" class="pct high">100%</td>
|
|
93
|
-
<td data-value="
|
|
93
|
+
<td data-value="17" class="abs high">17/17</td>
|
|
94
94
|
</tr>
|
|
95
95
|
|
|
96
96
|
<tr>
|
|
97
97
|
<td class="file high" data-value="src/actions"><a href="src/actions/index.html">src/actions</a></td>
|
|
98
|
-
<td data-value="
|
|
99
|
-
<div class="chart"><div class="cover-fill" style="width:
|
|
98
|
+
<td data-value="80.23" class="pic high">
|
|
99
|
+
<div class="chart"><div class="cover-fill" style="width: 80%"></div><div class="cover-empty" style="width: 20%"></div></div>
|
|
100
100
|
</td>
|
|
101
|
-
<td data-value="
|
|
102
|
-
<td data-value="
|
|
103
|
-
<td data-value="
|
|
104
|
-
<td data-value="
|
|
105
|
-
<td data-value="
|
|
106
|
-
<td data-value="
|
|
107
|
-
<td data-value="
|
|
108
|
-
<td data-value="
|
|
101
|
+
<td data-value="80.23" class="pct high">80.23%</td>
|
|
102
|
+
<td data-value="2181" class="abs high">1750/2181</td>
|
|
103
|
+
<td data-value="64.36" class="pct medium">64.36%</td>
|
|
104
|
+
<td data-value="623" class="abs medium">401/623</td>
|
|
105
|
+
<td data-value="78.57" class="pct medium">78.57%</td>
|
|
106
|
+
<td data-value="490" class="abs medium">385/490</td>
|
|
107
|
+
<td data-value="78.57" class="pct medium">78.57%</td>
|
|
108
|
+
<td data-value="2002" class="abs medium">1573/2002</td>
|
|
109
109
|
</tr>
|
|
110
110
|
|
|
111
111
|
<tr>
|
|
112
|
-
<td class="file
|
|
113
|
-
<td data-value="
|
|
114
|
-
<div class="chart"><div class="cover-fill
|
|
112
|
+
<td class="file medium" data-value="src/adapters"><a href="src/adapters/index.html">src/adapters</a></td>
|
|
113
|
+
<td data-value="61.71" class="pic medium">
|
|
114
|
+
<div class="chart"><div class="cover-fill" style="width: 61%"></div><div class="cover-empty" style="width: 39%"></div></div>
|
|
115
115
|
</td>
|
|
116
|
-
<td data-value="
|
|
117
|
-
<td data-value="
|
|
118
|
-
<td data-value="
|
|
119
|
-
<td data-value="
|
|
120
|
-
<td data-value="
|
|
121
|
-
<td data-value="
|
|
122
|
-
<td data-value="
|
|
123
|
-
<td data-value="
|
|
116
|
+
<td data-value="61.71" class="pct medium">61.71%</td>
|
|
117
|
+
<td data-value="431" class="abs medium">266/431</td>
|
|
118
|
+
<td data-value="62.26" class="pct medium">62.26%</td>
|
|
119
|
+
<td data-value="424" class="abs medium">264/424</td>
|
|
120
|
+
<td data-value="40" class="pct low">40%</td>
|
|
121
|
+
<td data-value="75" class="abs low">30/75</td>
|
|
122
|
+
<td data-value="58.99" class="pct medium">58.99%</td>
|
|
123
|
+
<td data-value="378" class="abs medium">223/378</td>
|
|
124
124
|
</tr>
|
|
125
125
|
|
|
126
126
|
<tr>
|
|
@@ -138,36 +138,6 @@
|
|
|
138
138
|
<td data-value="20" class="abs high">20/20</td>
|
|
139
139
|
</tr>
|
|
140
140
|
|
|
141
|
-
<tr>
|
|
142
|
-
<td class="file high" data-value="src/templates/email"><a href="src/templates/email/index.html">src/templates/email</a></td>
|
|
143
|
-
<td data-value="100" class="pic high">
|
|
144
|
-
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
145
|
-
</td>
|
|
146
|
-
<td data-value="100" class="pct high">100%</td>
|
|
147
|
-
<td data-value="5" class="abs high">5/5</td>
|
|
148
|
-
<td data-value="100" class="pct high">100%</td>
|
|
149
|
-
<td data-value="0" class="abs high">0/0</td>
|
|
150
|
-
<td data-value="100" class="pct high">100%</td>
|
|
151
|
-
<td data-value="0" class="abs high">0/0</td>
|
|
152
|
-
<td data-value="100" class="pct high">100%</td>
|
|
153
|
-
<td data-value="5" class="abs high">5/5</td>
|
|
154
|
-
</tr>
|
|
155
|
-
|
|
156
|
-
<tr>
|
|
157
|
-
<td class="file high" data-value="src/templates/sms"><a href="src/templates/sms/index.html">src/templates/sms</a></td>
|
|
158
|
-
<td data-value="100" class="pic high">
|
|
159
|
-
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
160
|
-
</td>
|
|
161
|
-
<td data-value="100" class="pct high">100%</td>
|
|
162
|
-
<td data-value="4" class="abs high">4/4</td>
|
|
163
|
-
<td data-value="100" class="pct high">100%</td>
|
|
164
|
-
<td data-value="0" class="abs high">0/0</td>
|
|
165
|
-
<td data-value="100" class="pct high">100%</td>
|
|
166
|
-
<td data-value="0" class="abs high">0/0</td>
|
|
167
|
-
<td data-value="100" class="pct high">100%</td>
|
|
168
|
-
<td data-value="4" class="abs high">4/4</td>
|
|
169
|
-
</tr>
|
|
170
|
-
|
|
171
141
|
<tr>
|
|
172
142
|
<td class="file high" data-value="src/types"><a href="src/types/index.html">src/types</a></td>
|
|
173
143
|
<td data-value="100" class="pic high">
|
|
@@ -185,17 +155,17 @@
|
|
|
185
155
|
|
|
186
156
|
<tr>
|
|
187
157
|
<td class="file high" data-value="src/utils"><a href="src/utils/index.html">src/utils</a></td>
|
|
188
|
-
<td data-value="
|
|
189
|
-
<div class="chart"><div class="cover-fill" style="width:
|
|
158
|
+
<td data-value="88.23" class="pic high">
|
|
159
|
+
<div class="chart"><div class="cover-fill" style="width: 88%"></div><div class="cover-empty" style="width: 12%"></div></div>
|
|
190
160
|
</td>
|
|
191
|
-
<td data-value="
|
|
192
|
-
<td data-value="
|
|
193
|
-
<td data-value="
|
|
194
|
-
<td data-value="
|
|
195
|
-
<td data-value="
|
|
196
|
-
<td data-value="
|
|
197
|
-
<td data-value="
|
|
198
|
-
<td data-value="
|
|
161
|
+
<td data-value="88.23" class="pct high">88.23%</td>
|
|
162
|
+
<td data-value="408" class="abs high">360/408</td>
|
|
163
|
+
<td data-value="73.88" class="pct medium">73.88%</td>
|
|
164
|
+
<td data-value="134" class="abs medium">99/134</td>
|
|
165
|
+
<td data-value="85.32" class="pct high">85.32%</td>
|
|
166
|
+
<td data-value="109" class="abs high">93/109</td>
|
|
167
|
+
<td data-value="86.9" class="pct high">86.9%</td>
|
|
168
|
+
<td data-value="336" class="abs high">292/336</td>
|
|
199
169
|
</tr>
|
|
200
170
|
|
|
201
171
|
</tbody>
|
|
@@ -206,7 +176,7 @@
|
|
|
206
176
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
207
177
|
Code coverage generated by
|
|
208
178
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
209
|
-
at 2025-
|
|
179
|
+
at 2025-07-02T05:49:37.404Z
|
|
210
180
|
</div>
|
|
211
181
|
<script src="prettify.js"></script>
|
|
212
182
|
<script>
|
package/index.js
CHANGED
package/jest.config.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
3
|
+
testEnvironment: 'node',
|
|
4
|
+
transform: {
|
|
5
|
+
'^.+\\.ts$': 'ts-jest'
|
|
6
|
+
},
|
|
7
|
+
moduleFileExtensions: ['ts', 'js', 'json'],
|
|
8
|
+
transformIgnorePatterns: [
|
|
9
|
+
'node_modules/(?!(zod)/)'
|
|
10
|
+
],
|
|
11
|
+
extensionsToTreatAsEsm: ['.ts'],
|
|
12
|
+
globals: {
|
|
13
|
+
'ts-jest': {
|
|
14
|
+
useESM: true
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
package/jest.setup.js
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Centralized ArangoDB mock for all tests
|
|
2
|
+
jest.mock('arangojs', () => ({
|
|
3
|
+
...jest.requireActual('arangojs'),
|
|
4
|
+
aql: jest.fn((templateStrings, ...args) => {
|
|
5
|
+
// Concatenate template strings and interpolate arguments
|
|
6
|
+
let result = '';
|
|
7
|
+
for (let i = 0; i < templateStrings.length; i++) {
|
|
8
|
+
result += templateStrings[i];
|
|
9
|
+
if (i < args.length) {
|
|
10
|
+
// Add the actual value to the template
|
|
11
|
+
result += args[i];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
// Normalize to single line: remove newlines and normalize whitespace
|
|
15
|
+
const singleLine = result.replace(/\s+/g, ' ').trim();
|
|
16
|
+
return [singleLine, ...args];
|
|
17
|
+
})
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
// Mock the useDb function from arangodbUtils with a basic default
|
|
21
|
+
const mockUseDb = jest.fn(() => ({
|
|
22
|
+
collection: jest.fn(() => ({
|
|
23
|
+
save: jest.fn(() => Promise.resolve()),
|
|
24
|
+
remove: jest.fn(() => Promise.resolve()),
|
|
25
|
+
update: jest.fn(() => Promise.resolve())
|
|
26
|
+
})),
|
|
27
|
+
query: jest.fn(() => Promise.resolve({
|
|
28
|
+
all: jest.fn(() => Promise.resolve([])),
|
|
29
|
+
next: jest.fn(() => Promise.resolve({}))
|
|
30
|
+
}))
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
jest.mock('./src/utils/arangodbUtils', () => ({
|
|
34
|
+
...jest.requireActual('./src/utils/arangodbUtils'),
|
|
35
|
+
useDb: mockUseDb
|
|
36
|
+
}));
|