Skip to content

Commit 9cd8178

Browse files
feat(condo): DOMA-13327 added tests
1 parent 5bbebee commit 9cd8178

2 files changed

Lines changed: 178 additions & 133 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
const index = require('@app/condo/index')
2+
const { faker } = require('@faker-js/faker')
3+
const dayjs = require('dayjs')
4+
5+
const { EncryptionManager } = require('@open-condo/keystone/crypto/EncryptionManager')
6+
const { setFakeClientMode, makeLoggedInAdminClient, waitFor } = require('@open-condo/keystone/test.utils')
7+
const { WebhookPayload } = require('@open-condo/webhooks/schema/utils/testSchema')
8+
9+
const {
10+
PAYMENT_DONE_STATUS,
11+
} = require('@condo/domains/acquiring/constants/payment')
12+
const {
13+
updateTestMultiPayment,
14+
updateTestPayment,
15+
Payment,
16+
} = require('@condo/domains/acquiring/utils/testSchema')
17+
const { WEBHOOK_EVENT_SUBSCRIPTION_ACTIVATED } = require('@condo/domains/common/constants/webhooks')
18+
const { MANAGING_COMPANY_TYPE } = require('@condo/domains/organization/constants/common')
19+
const { registerNewOrganization } = require('@condo/domains/organization/utils/testSchema')
20+
const { SUBSCRIPTION_CONTEXT_STATUS, SUBSCRIPTION_PERIOD } = require('@condo/domains/subscription/constants')
21+
const { processRecurrentSubscriptionPayments } = require('@condo/domains/subscription/tasks/processRecurrentSubscriptionPayments')
22+
const {
23+
SubscriptionContext,
24+
registerSubscriptionContextByTestClient,
25+
createTestSubscriptionPlan,
26+
createTestSubscriptionPlanPricingRule,
27+
createTestSubscriptionContext,
28+
} = require('@condo/domains/subscription/utils/testSchema')
29+
30+
describe('ActivateSubscriptionContextService webhook', () => {
31+
setFakeClientMode(index)
32+
33+
const encryptionManager = new EncryptionManager()
34+
const WEBHOOK_URL = 'http://localhost/test-subscription-webhook'
35+
const WEBHOOK_SECRET = 'test-webhook-secret-32-bytes-long!!'
36+
37+
const PAYMENT_METHOD = {
38+
bindingId: faker.datatype.uuid(),
39+
paymentSystem: 'MasterCard',
40+
cardNumber: '******4242',
41+
expiration: '12/2025',
42+
bankName: 'Test Bank',
43+
bankCountryCode: 'RU',
44+
}
45+
46+
let admin, organization, subscriptionPlan, pricingRule
47+
48+
beforeAll(async () => {
49+
process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_URL = WEBHOOK_URL
50+
process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_SECRET = WEBHOOK_SECRET
51+
52+
admin = await makeLoggedInAdminClient()
53+
54+
const [plan] = await createTestSubscriptionPlan(admin, {
55+
organizationType: MANAGING_COMPANY_TYPE,
56+
isHidden: false,
57+
})
58+
subscriptionPlan = plan
59+
60+
const [rule] = await createTestSubscriptionPlanPricingRule(admin, subscriptionPlan, {
61+
period: SUBSCRIPTION_PERIOD.MONTH,
62+
price: '1000.00',
63+
currencyCode: 'RUB',
64+
})
65+
pricingRule = rule
66+
67+
const [org] = await registerNewOrganization(admin, { type: MANAGING_COMPANY_TYPE })
68+
organization = org
69+
})
70+
71+
afterAll(() => {
72+
delete process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_URL
73+
delete process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_SECRET
74+
})
75+
76+
async function payInvoice (invoiceId) {
77+
const [payment] = await Payment.getAll(admin, { invoice: { id: invoiceId }, deletedAt: null })
78+
await updateTestMultiPayment(admin, payment.multiPayment.id, { meta: { paymentMethod: PAYMENT_METHOD } })
79+
await updateTestPayment(admin, payment.id, { status: PAYMENT_DONE_STATUS, advancedAt: dayjs().toISOString() })
80+
}
81+
82+
test('manual payment: creates WebhookPayload with all required fields including user', async () => {
83+
const [result] = await registerSubscriptionContextByTestClient(admin, {
84+
organization: { id: organization.id },
85+
subscriptionPlanPricingRule: { id: pricingRule.id },
86+
isTrial: false,
87+
})
88+
const subscriptionContext = result.subscriptionContext
89+
const invoice = result.subscriptionContext.invoice
90+
91+
await payInvoice(invoice.id)
92+
93+
await waitFor(async () => {
94+
const [ctx] = await SubscriptionContext.getAll(admin, { id: subscriptionContext.id })
95+
expect(ctx.status).toBe(SUBSCRIPTION_CONTEXT_STATUS.DONE)
96+
})
97+
98+
let webhookPayload
99+
await waitFor(async () => {
100+
const payloads = await WebhookPayload.getAll(admin, {
101+
eventType: WEBHOOK_EVENT_SUBSCRIPTION_ACTIVATED,
102+
itemId: subscriptionContext.id,
103+
deletedAt: null,
104+
})
105+
expect(payloads).toHaveLength(1)
106+
webhookPayload = payloads[0]
107+
})
108+
109+
const payload = JSON.parse(encryptionManager.decrypt(webhookPayload.payload))
110+
111+
expect(webhookPayload.url).toBe(WEBHOOK_URL)
112+
expect(payload.invoiceId).toBe(invoice.id)
113+
expect(payload.paidAt).toBeDefined()
114+
expect(payload.toPay).toBe(pricingRule.price)
115+
expect(payload.planName).toBe(subscriptionPlan.name)
116+
expect(payload.organization.id).toBe(organization.id)
117+
expect(payload.organization.name).toBeDefined()
118+
expect(payload.organization.tin).toBeDefined()
119+
expect(payload.user.id).toBe(admin.user.id)
120+
expect(payload.user.name).toBeDefined()
121+
})
122+
123+
test('auto-payment: creates WebhookPayload without user field', async () => {
124+
const [payerOrganization] = await registerNewOrganization(admin, { type: MANAGING_COMPANY_TYPE })
125+
126+
await createTestSubscriptionContext(admin, payerOrganization, subscriptionPlan, {
127+
subscriptionPlanPricingRule: { connect: { id: pricingRule.id } },
128+
status: SUBSCRIPTION_CONTEXT_STATUS.DONE,
129+
bindingId: faker.datatype.uuid(),
130+
startAt: dayjs().subtract(1, 'month').format('YYYY-MM-DD'),
131+
endAt: dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
132+
isTrial: false,
133+
frozenPaymentInfo: { pricingRuleId: pricingRule.id, paymentMethod: PAYMENT_METHOD },
134+
})
135+
136+
await processRecurrentSubscriptionPayments()
137+
138+
let newContext
139+
await waitFor(async () => {
140+
const contexts = await SubscriptionContext.getAll(admin, {
141+
organization: { id: payerOrganization.id },
142+
status_in: [SUBSCRIPTION_CONTEXT_STATUS.CREATED, SUBSCRIPTION_CONTEXT_STATUS.PENDING, SUBSCRIPTION_CONTEXT_STATUS.ERROR],
143+
deletedAt: null,
144+
})
145+
expect(contexts).toHaveLength(1)
146+
newContext = contexts[0]
147+
})
148+
149+
await payInvoice(newContext.invoice.id)
150+
151+
await waitFor(async () => {
152+
const [ctx] = await SubscriptionContext.getAll(admin, { id: newContext.id })
153+
expect(ctx.status).toBe(SUBSCRIPTION_CONTEXT_STATUS.DONE)
154+
})
155+
156+
let webhookPayload
157+
await waitFor(async () => {
158+
const payloads = await WebhookPayload.getAll(admin, {
159+
eventType: WEBHOOK_EVENT_SUBSCRIPTION_ACTIVATED,
160+
itemId: newContext.id,
161+
deletedAt: null,
162+
})
163+
expect(payloads).toHaveLength(1)
164+
webhookPayload = payloads[0]
165+
})
166+
167+
const payload = JSON.parse(encryptionManager.decrypt(webhookPayload.payload))
168+
169+
expect(payload.invoiceId).toBe(newContext.invoice.id)
170+
expect(payload.paidAt).toBeDefined()
171+
expect(payload.toPay).toBe(pricingRule.price)
172+
expect(payload.planName).toBe(subscriptionPlan.name)
173+
expect(payload.organization.id).toBe(payerOrganization.id)
174+
expect(payload.organization.name).toBeDefined()
175+
expect(payload.organization.tin).toBeDefined()
176+
expect(payload.user).toBeUndefined()
177+
})
178+
})

apps/condo/domains/subscription/schema/ActivateSubscriptionContextService.test.js

Lines changed: 0 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
const { faker } = require('@faker-js/faker')
66
const dayjs = require('dayjs')
77

8-
const { EncryptionManager } = require('@open-condo/keystone/crypto/EncryptionManager')
98
const { makeLoggedInAdminClient, makeClient, expectToThrowGQLError, waitFor } = require('@open-condo/keystone/test.utils')
109
const { expectToThrowAccessDeniedErrorToResult, expectToThrowAuthenticationErrorToResult } = require('@open-condo/keystone/test.utils')
11-
const { WebhookPayload } = require('@open-condo/webhooks/schema/utils/testSchema')
1210

1311
const {
1412
PAYMENT_DONE_STATUS,
@@ -18,11 +16,9 @@ const {
1816
updateTestPayment,
1917
Payment,
2018
} = require('@condo/domains/acquiring/utils/testSchema')
21-
const { WEBHOOK_EVENT_SUBSCRIPTION_ACTIVATED } = require('@condo/domains/common/constants/webhooks')
2219
const { MANAGING_COMPANY_TYPE } = require('@condo/domains/organization/constants/common')
2320
const { registerNewOrganization } = require('@condo/domains/organization/utils/testSchema')
2421
const { SUBSCRIPTION_PERIOD, SUBSCRIPTION_CONTEXT_STATUS } = require('@condo/domains/subscription/constants')
25-
const { processRecurrentSubscriptionPayments } = require('@condo/domains/subscription/tasks/processRecurrentSubscriptionPayments')
2622
const {
2723
SubscriptionContext,
2824
activateSubscriptionContextByTestClient,
@@ -152,135 +148,6 @@ describe('ActivateSubscriptionContextService', () => {
152148
})
153149
})
154150

155-
describe('Webhook on activation', () => {
156-
const encryptionManager = new EncryptionManager()
157-
const WEBHOOK_URL = 'http://localhost/test-subscription-webhook'
158-
const WEBHOOK_SECRET = 'test-webhook-secret-32-bytes-long!!'
159-
160-
beforeAll(() => {
161-
process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_URL = WEBHOOK_URL
162-
process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_SECRET = WEBHOOK_SECRET
163-
})
164-
165-
afterAll(() => {
166-
delete process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_URL
167-
delete process.env.SUBSCRIPTION_ACTIVATED_WEBHOOK_SECRET
168-
})
169-
170-
const PAYMENT_METHOD = {
171-
bindingId: faker.datatype.uuid(),
172-
paymentSystem: 'MasterCard',
173-
cardNumber: '******4242',
174-
expiration: '12/2025',
175-
bankName: 'Test Bank',
176-
bankCountryCode: 'RU',
177-
}
178-
179-
async function payInvoice (invoiceId) {
180-
const [payment] = await Payment.getAll(admin, { invoice: { id: invoiceId }, deletedAt: null })
181-
await updateTestMultiPayment(admin, payment.multiPayment.id, { meta: { paymentMethod: PAYMENT_METHOD } })
182-
await updateTestPayment(admin, payment.id, { status: PAYMENT_DONE_STATUS, advancedAt: dayjs().toISOString() })
183-
return payment
184-
}
185-
186-
test('manual payment: creates WebhookPayload with all required fields including user', async () => {
187-
const [result] = await registerSubscriptionContextByTestClient(admin, {
188-
organization: { id: organization.id },
189-
subscriptionPlanPricingRule: { id: pricingRule.id },
190-
isTrial: false,
191-
})
192-
const subscriptionContext = result.subscriptionContext
193-
const invoice = result.subscriptionContext.invoice
194-
195-
await payInvoice(invoice.id)
196-
197-
await waitFor(async () => {
198-
const [ctx] = await SubscriptionContext.getAll(admin, { id: subscriptionContext.id })
199-
expect(ctx.status).toBe(SUBSCRIPTION_CONTEXT_STATUS.DONE)
200-
})
201-
202-
let webhookPayload
203-
await waitFor(async () => {
204-
const payloads = await WebhookPayload.getAll(admin, {
205-
eventType: WEBHOOK_EVENT_SUBSCRIPTION_ACTIVATED,
206-
itemId: subscriptionContext.id,
207-
deletedAt: null,
208-
})
209-
expect(payloads).toHaveLength(1)
210-
webhookPayload = payloads[0]
211-
})
212-
213-
const payload = JSON.parse(encryptionManager.decrypt(webhookPayload.payload))
214-
215-
expect(webhookPayload.url).toBe(WEBHOOK_URL)
216-
expect(payload.invoiceId).toBe(invoice.id)
217-
expect(payload.paidAt).toBeDefined()
218-
expect(payload.toPay).toBe(pricingRule.price)
219-
expect(payload.planName).toBe(subscriptionPlan.name)
220-
expect(payload.organization.id).toBe(organization.id)
221-
expect(payload.organization.name).toBeDefined()
222-
expect(payload.organization.tin).toBeDefined()
223-
expect(payload.user.id).toBe(admin.user.id)
224-
expect(payload.user.name).toBeDefined()
225-
})
226-
227-
test('auto-payment: creates WebhookPayload without user field', async () => {
228-
const [payerOrganization] = await registerNewOrganization(admin, { type: MANAGING_COMPANY_TYPE })
229-
230-
await createTestSubscriptionContext(admin, payerOrganization, subscriptionPlan, {
231-
subscriptionPlanPricingRule: { connect: { id: pricingRule.id } },
232-
status: SUBSCRIPTION_CONTEXT_STATUS.DONE,
233-
bindingId: faker.datatype.uuid(),
234-
startAt: dayjs().subtract(1, 'month').format('YYYY-MM-DD'),
235-
endAt: dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
236-
isTrial: false,
237-
frozenPaymentInfo: { pricingRuleId: pricingRule.id, paymentMethod: PAYMENT_METHOD },
238-
})
239-
240-
await processRecurrentSubscriptionPayments()
241-
242-
let newContext
243-
await waitFor(async () => {
244-
const contexts = await SubscriptionContext.getAll(admin, {
245-
organization: { id: payerOrganization.id },
246-
status_in: [SUBSCRIPTION_CONTEXT_STATUS.CREATED, SUBSCRIPTION_CONTEXT_STATUS.PENDING, SUBSCRIPTION_CONTEXT_STATUS.ERROR],
247-
deletedAt: null,
248-
})
249-
expect(contexts).toHaveLength(1)
250-
newContext = contexts[0]
251-
})
252-
253-
await payInvoice(newContext.invoice.id)
254-
255-
await waitFor(async () => {
256-
const [ctx] = await SubscriptionContext.getAll(admin, { id: newContext.id })
257-
expect(ctx.status).toBe(SUBSCRIPTION_CONTEXT_STATUS.DONE)
258-
})
259-
260-
let webhookPayload
261-
await waitFor(async () => {
262-
const payloads = await WebhookPayload.getAll(admin, {
263-
eventType: WEBHOOK_EVENT_SUBSCRIPTION_ACTIVATED,
264-
itemId: newContext.id,
265-
deletedAt: null,
266-
})
267-
expect(payloads).toHaveLength(1)
268-
webhookPayload = payloads[0]
269-
})
270-
271-
const payload = JSON.parse(encryptionManager.decrypt(webhookPayload.payload))
272-
273-
expect(payload.invoiceId).toBe(newContext.invoice.id)
274-
expect(payload.paidAt).toBeDefined()
275-
expect(payload.toPay).toBe(pricingRule.price)
276-
expect(payload.planName).toBe(subscriptionPlan.name)
277-
expect(payload.organization.id).toBe(payerOrganization.id)
278-
expect(payload.organization.name).toBeDefined()
279-
expect(payload.organization.tin).toBeDefined()
280-
expect(payload.user).toBeUndefined()
281-
})
282-
})
283-
284151
describe('Payment Method Extraction and Freezing', () => {
285152
test('extracts payment method from multiPayment and freezes payment info when transitioning to DONE', async () => {
286153
const [result] = await registerSubscriptionContextByTestClient(admin, {

0 commit comments

Comments
 (0)