-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathbilling.requirePlan.unit.tests.js
More file actions
132 lines (102 loc) · 3.87 KB
/
Copy pathbilling.requirePlan.unit.tests.js
File metadata and controls
132 lines (102 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
* Module dependencies.
*/
import mongoose from 'mongoose';
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
const mockFindByOrganization = jest.fn();
jest.unstable_mockModule('../repositories/billing.subscription.repository.js', () => ({
default: { findByOrganization: mockFindByOrganization },
}));
const { default: requirePlan } = await import('../middlewares/billing.requirePlan.js');
/**
* Unit tests for the requirePlan middleware.
*/
describe('requirePlan middleware unit tests:', () => {
const fakeOrgId = new mongoose.Types.ObjectId();
/**
* @desc Build a minimal Express-like req object
* @param {Object} overrides - Properties to merge onto the request
* @returns {Object} mock request
*/
function mockReq(overrides = {}) {
return {
organization: { _id: fakeOrgId, name: 'Test Org' },
...overrides,
};
}
/**
* @desc Build a minimal Express-like res object with spies
* @returns {Object} mock response
*/
function mockRes() {
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
return res;
}
beforeEach(() => {
jest.clearAllMocks();
});
test('should call next when subscription plan matches the required plan', async () => {
mockFindByOrganization.mockResolvedValue({ plan: 'pro' });
const middleware = requirePlan('pro');
const req = mockReq();
const res = mockRes();
const next = jest.fn();
await middleware(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(res.status).not.toHaveBeenCalled();
});
test('should call next when subscription plan is in multiple allowed plans', async () => {
mockFindByOrganization.mockResolvedValue({ plan: 'starter' });
const middleware = requirePlan('starter', 'pro', 'enterprise');
const req = mockReq();
const res = mockRes();
const next = jest.fn();
await middleware(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(res.status).not.toHaveBeenCalled();
});
test('should return 403 when subscription plan does not match', async () => {
mockFindByOrganization.mockResolvedValue({ plan: 'free' });
const middleware = requirePlan('pro', 'enterprise');
const req = mockReq();
const res = mockRes();
const next = jest.fn();
await middleware(req, res, next);
expect(next).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(403);
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ type: 'error', message: 'Forbidden' }));
});
test('should default to free plan when no subscription exists', async () => {
mockFindByOrganization.mockResolvedValue(null);
const middleware = requirePlan('free');
const req = mockReq();
const res = mockRes();
const next = jest.fn();
await middleware(req, res, next);
expect(next).toHaveBeenCalledTimes(1);
expect(res.status).not.toHaveBeenCalled();
});
test('should return 403 when no subscription exists and free is not allowed', async () => {
mockFindByOrganization.mockResolvedValue(null);
const middleware = requirePlan('pro');
const req = mockReq();
const res = mockRes();
const next = jest.fn();
await middleware(req, res, next);
expect(next).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(403);
});
test('should return 403 when organization is missing from request', async () => {
const middleware = requirePlan('pro');
const req = mockReq({ organization: undefined });
const res = mockRes();
const next = jest.fn();
await middleware(req, res, next);
expect(next).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(403);
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ type: 'error', message: 'Forbidden' }));
expect(mockFindByOrganization).not.toHaveBeenCalled();
});
});