Skip to content

Commit 6762347

Browse files
committed
Merge branch 'fix/card-linking' into stage
2 parents 7f02035 + cd50987 commit 6762347

File tree

2 files changed

+113
-170
lines changed

2 files changed

+113
-170
lines changed

src/resolvers/billingNew.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,18 @@ export default {
111111

112112
let isCardLinkOperation = false;
113113

114-
if (workspace.tariffPlanId.toString() === tariffPlanId && !workspace.isTariffPlanExpired() && !workspace.isBlocked) {
114+
115+
/**
116+
* We need to only link card and not pay for the whole plan in case
117+
* 1. We are paying for the same plan and
118+
* 2. Plan is not expired and
119+
* 3. Workspace is not blocked
120+
*/
121+
if (
122+
workspace.tariffPlanId.toString() === tariffPlanId && // 1
123+
!workspace.isTariffPlanExpired() && // 2
124+
!workspace.isBlocked // 3
125+
) {
115126
isCardLinkOperation = true;
116127
}
117128

test/resolvers/billingNew.test.ts

Lines changed: 101 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,113 @@
11
import '../../src/env-test';
22
import { ObjectId } from 'mongodb';
3-
import { PlanDBScheme, WorkspaceDBScheme, UserDBScheme } from '@hawk.so/types';
3+
import { PlanDBScheme, WorkspaceDBScheme } from '@hawk.so/types';
44
import billingNewResolver from '../../src/resolvers/billingNew';
55
import { ResolverContextWithUser } from '../../src/types/graphql';
66

7-
// Мокаем telegram модуль
8-
// jest.mock('../../src/utils/telegram', () => ({
9-
// sendMessage: jest.fn().mockResolvedValue(undefined),
10-
// TelegramBotURLs: {
11-
// Base: 'base',
12-
// Money: 'money',
13-
// },
14-
// }));
15-
16-
// Устанавливаем переменные окружения для теста
7+
// Set environment variables for test
178
process.env.JWT_SECRET_BILLING_CHECKSUM = 'checksum_secret';
189
process.env.JWT_SECRET_ACCESS_TOKEN = 'belarus';
1910
process.env.JWT_SECRET_REFRESH_TOKEN = 'abacaba';
2011
process.env.JWT_SECRET_PROJECT_TOKEN = 'qwerty';
2112

13+
/**
14+
* Creates test data and mocks for composePayment tests
15+
*/
16+
function createComposePaymentTestSetup(options: {
17+
isTariffPlanExpired?: boolean;
18+
isBlocked?: boolean;
19+
lastChargeDate?: Date;
20+
planMonthlyCharge?: number;
21+
planCurrency?: string;
22+
}) {
23+
const {
24+
isTariffPlanExpired = false,
25+
isBlocked = false,
26+
lastChargeDate = new Date(),
27+
planMonthlyCharge = 1000,
28+
planCurrency = 'RUB'
29+
} = options;
30+
31+
const userId = new ObjectId().toString();
32+
const workspaceId = new ObjectId().toString();
33+
const planId = new ObjectId().toString();
34+
35+
const plan: PlanDBScheme = {
36+
_id: new ObjectId(planId),
37+
name: 'Test Plan',
38+
monthlyCharge: planMonthlyCharge,
39+
monthlyChargeCurrency: planCurrency,
40+
eventsLimit: 1000,
41+
isDefault: false,
42+
isHidden: false,
43+
};
44+
45+
const workspace: WorkspaceDBScheme = {
46+
_id: new ObjectId(workspaceId),
47+
name: 'Test Workspace',
48+
accountId: 'test-account-id',
49+
balance: 0,
50+
billingPeriodEventsCount: 0,
51+
isBlocked,
52+
lastChargeDate,
53+
tariffPlanId: new ObjectId(planId),
54+
inviteHash: 'test-invite-hash',
55+
subscriptionId: undefined,
56+
};
57+
58+
// Mock workspaces factory
59+
const mockWorkspacesFactory = {
60+
findById: jest.fn().mockResolvedValue({
61+
...workspace,
62+
getMemberInfo: jest.fn().mockResolvedValue({ isAdmin: true }),
63+
isTariffPlanExpired: jest.fn().mockReturnValue(isTariffPlanExpired),
64+
isBlocked,
65+
}),
66+
};
67+
68+
// Mock plans factory
69+
const mockPlansFactory = {
70+
findById: jest.fn().mockResolvedValue(plan),
71+
};
72+
73+
const mockContext: ResolverContextWithUser = {
74+
user: {
75+
id: userId,
76+
accessTokenExpired: false,
77+
},
78+
factories: {
79+
workspacesFactory: mockWorkspacesFactory as any,
80+
plansFactory: mockPlansFactory as any,
81+
usersFactory: {} as any,
82+
projectsFactory: {} as any,
83+
businessOperationsFactory: {} as any,
84+
},
85+
};
86+
87+
return {
88+
userId,
89+
workspaceId,
90+
planId,
91+
plan,
92+
workspace,
93+
mockContext,
94+
mockWorkspacesFactory,
95+
mockPlansFactory,
96+
};
97+
}
98+
2299
describe('GraphQLBillingNew', () => {
23100
describe('composePayment', () => {
24101
it('should return isCardLinkOperation = false in case of expired tariff plan', async () => {
25-
const userId = new ObjectId().toString();
26-
const workspaceId = new ObjectId().toString();
27-
const planId = new ObjectId().toString();
28-
29-
const plan: PlanDBScheme = {
30-
_id: new ObjectId(planId),
31-
name: 'Test Plan',
32-
monthlyCharge: 1000,
33-
monthlyChargeCurrency: 'RUB',
34-
eventsLimit: 1000,
35-
isDefault: false,
36-
isHidden: false,
37-
};
38-
39-
// Workspace with expired tariff plan
102+
// Create 2 months ago date
40103
const expiredDate = new Date();
41104
expiredDate.setMonth(expiredDate.getMonth() - 2);
42105

43-
const workspace: WorkspaceDBScheme = {
44-
_id: new ObjectId(workspaceId),
45-
name: 'Test Workspace',
46-
accountId: 'test-account-id',
47-
balance: 0,
48-
billingPeriodEventsCount: 0,
106+
const { mockContext, planId, workspaceId } = createComposePaymentTestSetup({
107+
isTariffPlanExpired: true,
49108
isBlocked: false,
50109
lastChargeDate: expiredDate,
51-
tariffPlanId: new ObjectId(planId),
52-
inviteHash: 'test-invite-hash',
53-
subscriptionId: undefined,
54-
};
55-
56-
// Mock workspaces factory
57-
const mockWorkspacesFactory = {
58-
findById: jest.fn().mockResolvedValue({
59-
...workspace,
60-
getMemberInfo: jest.fn().mockResolvedValue({ isAdmin: true }),
61-
isTariffPlanExpired: jest.fn().mockReturnValue(true), // План истек
62-
isBlocked: false,
63-
}),
64-
};
65-
66-
// Mock plans factory
67-
const mockPlansFactory = {
68-
findById: jest.fn().mockResolvedValue(plan),
69-
};
70-
71-
const mockContext: ResolverContextWithUser = {
72-
user: {
73-
id: userId,
74-
accessTokenExpired: false,
75-
},
76-
factories: {
77-
workspacesFactory: mockWorkspacesFactory as any,
78-
plansFactory: mockPlansFactory as any,
79-
usersFactory: {} as any,
80-
projectsFactory: {} as any,
81-
businessOperationsFactory: {} as any,
82-
},
83-
};
110+
});
84111

85112
// Call composePayment resolver
86113
const result = await billingNewResolver.Query.composePayment(
@@ -111,61 +138,14 @@ describe('GraphQLBillingNew', () => {
111138
});
112139

113140
it('should return isCardLinkOperation = true in case of active tariff plan', async () => {
114-
const userId = new ObjectId().toString();
115-
const workspaceId = new ObjectId().toString();
116-
const planId = new ObjectId().toString();
117-
141+
// Create 2 days ago date
142+
const lastChargeDate = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000);
118143

119-
const plan: PlanDBScheme = {
120-
_id: new ObjectId(planId),
121-
name: 'Test Plan',
122-
monthlyCharge: 1000,
123-
monthlyChargeCurrency: 'RUB',
124-
eventsLimit: 1000,
125-
isDefault: false,
126-
isHidden: false,
127-
};
128-
129-
const lastChargeDate = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000); // Last charge date is 2 days ago
130-
131-
const workspace: WorkspaceDBScheme = {
132-
_id: new ObjectId(workspaceId),
133-
name: 'Test Workspace',
134-
accountId: 'test-account-id',
135-
balance: 0,
136-
billingPeriodEventsCount: 0,
144+
const { mockContext, planId, workspaceId, workspace } = createComposePaymentTestSetup({
145+
isTariffPlanExpired: false,
137146
isBlocked: false,
138147
lastChargeDate,
139-
tariffPlanId: new ObjectId(planId),
140-
inviteHash: 'test-invite-hash',
141-
subscriptionId: undefined,
142-
};
143-
144-
const mockWorkspacesFactory = {
145-
findById: jest.fn().mockResolvedValue({
146-
...workspace,
147-
getMemberInfo: jest.fn().mockResolvedValue({ isAdmin: true }),
148-
isTariffPlanExpired: jest.fn().mockReturnValue(false),
149-
}),
150-
};
151-
152-
const mockPlansFactory = {
153-
findById: jest.fn().mockResolvedValue(plan),
154-
};
155-
156-
const mockContext: ResolverContextWithUser = {
157-
user: {
158-
id: userId,
159-
accessTokenExpired: false,
160-
},
161-
factories: {
162-
workspacesFactory: mockWorkspacesFactory as any,
163-
plansFactory: mockPlansFactory as any,
164-
usersFactory: {} as any,
165-
projectsFactory: {} as any,
166-
businessOperationsFactory: {} as any,
167-
},
168-
};
148+
});
169149

170150
const result = await billingNewResolver.Query.composePayment(
171151
undefined,
@@ -183,7 +163,7 @@ describe('GraphQLBillingNew', () => {
183163
expect(result.plan.monthlyCharge).toBe(1000);
184164
expect(result.currency).toBe('RUB');
185165

186-
const oneMonthFromLastChargeDate = new Date(lastChargeDate);
166+
const oneMonthFromLastChargeDate = new Date(workspace.lastChargeDate);
187167
oneMonthFromLastChargeDate.setMonth(oneMonthFromLastChargeDate.getMonth() + 1);
188168

189169
const oneMonthFromLastChargeDateStr = oneMonthFromLastChargeDate.toISOString().split('T')[0];
@@ -192,59 +172,11 @@ describe('GraphQLBillingNew', () => {
192172
});
193173

194174
it('should return isCardLinkOperation = false in case of blocked workspace', async () => {
195-
const userId = new ObjectId().toString();
196-
const workspaceId = new ObjectId().toString();
197-
const planId = new ObjectId().toString();
198-
199-
const plan: PlanDBScheme = {
200-
_id: new ObjectId(planId),
201-
name: 'Test Plan',
202-
monthlyCharge: 1000,
203-
monthlyChargeCurrency: 'RUB',
204-
eventsLimit: 1000,
205-
isDefault: false,
206-
isHidden: false,
207-
};
208-
209-
const workspace: WorkspaceDBScheme = {
210-
_id: new ObjectId(workspaceId),
211-
name: 'Test Workspace',
212-
accountId: 'test-account-id',
213-
balance: 0,
214-
billingPeriodEventsCount: 0,
175+
const { mockContext, planId, workspaceId } = createComposePaymentTestSetup({
176+
isTariffPlanExpired: false,
215177
isBlocked: true,
216178
lastChargeDate: new Date(),
217-
tariffPlanId: new ObjectId(planId),
218-
inviteHash: 'test-invite-hash',
219-
subscriptionId: undefined,
220-
};
221-
222-
const mockWorkspacesFactory = {
223-
findById: jest.fn().mockResolvedValue({
224-
...workspace,
225-
getMemberInfo: jest.fn().mockResolvedValue({ isAdmin: true }),
226-
isTariffPlanExpired: jest.fn().mockReturnValue(false),
227-
}),
228-
};
229-
230-
231-
const mockPlansFactory = {
232-
findById: jest.fn().mockResolvedValue(plan),
233-
};
234-
235-
const mockContext: ResolverContextWithUser = {
236-
user: {
237-
id: userId,
238-
accessTokenExpired: false,
239-
},
240-
factories: {
241-
workspacesFactory: mockWorkspacesFactory as any,
242-
plansFactory: mockPlansFactory as any,
243-
usersFactory: {} as any,
244-
projectsFactory: {} as any,
245-
businessOperationsFactory: {} as any,
246-
},
247-
};
179+
});
248180

249181
const result = await billingNewResolver.Query.composePayment(
250182
undefined,

0 commit comments

Comments
 (0)