nodebb-plugin-phone-verification 1.2.2

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.
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const fc = require('fast-check');
5
+ const plugin = require('../library');
6
+
7
+ describe('Verification Code Logic', function () {
8
+
9
+ // ניקוי לפני כל בדיקה
10
+ beforeEach(function () {
11
+ plugin.clearAllCodes();
12
+ });
13
+
14
+ // **Feature: nodebb-phone-verification, Property 3: תוקף קוד אימות**
15
+ // **Validates: Requirements 2.4**
16
+ describe('Code Expiry (Property 3)', function () {
17
+
18
+ it('Property 3: saved code should have expiry exactly 5 minutes from creation', function () {
19
+ const validPhoneArb = fc.tuple(
20
+ fc.constantFrom('050', '052', '054'),
21
+ fc.stringOf(fc.constantFrom('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), { minLength: 7, maxLength: 7 })
22
+ ).map(([prefix, suffix]) => prefix + suffix);
23
+
24
+ fc.assert(
25
+ fc.property(validPhoneArb, (phone) => {
26
+ plugin.clearVerificationCode(phone);
27
+ const code = plugin.generateVerificationCode();
28
+ const before = Date.now();
29
+ const result = plugin.saveVerificationCode(phone, code);
30
+ const after = Date.now();
31
+
32
+ if (!result.success) return true; // Skip blocked phones
33
+
34
+ const expectedMinExpiry = before + (5 * 60 * 1000);
35
+ const expectedMaxExpiry = after + (5 * 60 * 1000);
36
+
37
+ return result.expiresAt >= expectedMinExpiry && result.expiresAt <= expectedMaxExpiry;
38
+ }),
39
+ { numRuns: 100 }
40
+ );
41
+ });
42
+
43
+ it('Property 3: getCodeExpiry should return correct expiry time', function () {
44
+ const phone = '0501234567';
45
+ const code = plugin.generateVerificationCode();
46
+ const result = plugin.saveVerificationCode(phone, code);
47
+
48
+ const expiry = plugin.getCodeExpiry(phone);
49
+ assert.strictEqual(expiry, result.expiresAt);
50
+ });
51
+ });
52
+
53
+
54
+ // **Feature: nodebb-phone-verification, Property 4: אימות קוד נכון**
55
+ // **Validates: Requirements 3.1**
56
+ describe('Correct Code Verification (Property 4)', function () {
57
+
58
+ it('Property 4: correct code should always verify successfully', function () {
59
+ const validPhoneArb = fc.tuple(
60
+ fc.constantFrom('050', '052', '054'),
61
+ fc.stringOf(fc.constantFrom('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), { minLength: 7, maxLength: 7 })
62
+ ).map(([prefix, suffix]) => prefix + suffix);
63
+
64
+ fc.assert(
65
+ fc.property(validPhoneArb, (phone) => {
66
+ plugin.clearVerificationCode(phone);
67
+ const code = plugin.generateVerificationCode();
68
+ plugin.saveVerificationCode(phone, code);
69
+
70
+ const result = plugin.verifyCode(phone, code);
71
+ return result.success === true;
72
+ }),
73
+ { numRuns: 100 }
74
+ );
75
+ });
76
+
77
+ it('Property 4: code should be deleted after successful verification', function () {
78
+ const phone = '0501234567';
79
+ const code = plugin.generateVerificationCode();
80
+ plugin.saveVerificationCode(phone, code);
81
+
82
+ // First verification should succeed
83
+ const result1 = plugin.verifyCode(phone, code);
84
+ assert.strictEqual(result1.success, true);
85
+
86
+ // Second verification should fail (code deleted)
87
+ const result2 = plugin.verifyCode(phone, code);
88
+ assert.strictEqual(result2.success, false);
89
+ assert.strictEqual(result2.error, 'CODE_NOT_FOUND');
90
+ });
91
+ });
92
+
93
+ // **Feature: nodebb-phone-verification, Property 5: דחיית קוד שגוי**
94
+ // **Validates: Requirements 3.2**
95
+ describe('Wrong Code Rejection (Property 5)', function () {
96
+
97
+ it('Property 5: wrong code should always fail verification', function () {
98
+ const validPhoneArb = fc.tuple(
99
+ fc.constantFrom('050', '052', '054'),
100
+ fc.stringOf(fc.constantFrom('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), { minLength: 7, maxLength: 7 })
101
+ ).map(([prefix, suffix]) => prefix + suffix);
102
+
103
+ fc.assert(
104
+ fc.property(validPhoneArb, (phone) => {
105
+ plugin.clearVerificationCode(phone);
106
+ const correctCode = plugin.generateVerificationCode();
107
+ plugin.saveVerificationCode(phone, correctCode);
108
+
109
+ // Generate a different code
110
+ let wrongCode;
111
+ do {
112
+ wrongCode = plugin.generateVerificationCode();
113
+ } while (wrongCode === correctCode);
114
+
115
+ const result = plugin.verifyCode(phone, wrongCode);
116
+ return result.success === false;
117
+ }),
118
+ { numRuns: 100 }
119
+ );
120
+ });
121
+
122
+ it('Property 5: 3 wrong attempts should block the phone', function () {
123
+ const phone = '0501234567';
124
+ const correctCode = '123456';
125
+ const wrongCode = '654321';
126
+
127
+ plugin.saveVerificationCode(phone, correctCode);
128
+
129
+ // First 2 wrong attempts
130
+ plugin.verifyCode(phone, wrongCode);
131
+ plugin.verifyCode(phone, wrongCode);
132
+
133
+ // Third wrong attempt should block
134
+ const result = plugin.verifyCode(phone, wrongCode);
135
+ assert.strictEqual(result.success, false);
136
+ assert.strictEqual(result.error, 'PHONE_BLOCKED');
137
+ });
138
+
139
+ it('Property 5: blocked phone cannot verify even with correct code', function () {
140
+ const phone = '0501234567';
141
+ const correctCode = '123456';
142
+ const wrongCode = '654321';
143
+
144
+ plugin.saveVerificationCode(phone, correctCode);
145
+
146
+ // Block the phone with 3 wrong attempts
147
+ plugin.verifyCode(phone, wrongCode);
148
+ plugin.verifyCode(phone, wrongCode);
149
+ plugin.verifyCode(phone, wrongCode);
150
+
151
+ // Try to save new code - should fail
152
+ const saveResult = plugin.saveVerificationCode(phone, '111111');
153
+ assert.strictEqual(saveResult.success, false);
154
+ assert.strictEqual(saveResult.error, 'PHONE_BLOCKED');
155
+ });
156
+ });
157
+
158
+ describe('Hash Code', function () {
159
+
160
+ it('should produce consistent hash for same input', function () {
161
+ const code = '123456';
162
+ const hash1 = plugin.hashCode(code);
163
+ const hash2 = plugin.hashCode(code);
164
+ assert.strictEqual(hash1, hash2);
165
+ });
166
+
167
+ it('should produce different hash for different inputs', function () {
168
+ const hash1 = plugin.hashCode('123456');
169
+ const hash2 = plugin.hashCode('654321');
170
+ assert.notStrictEqual(hash1, hash2);
171
+ });
172
+ });
173
+ });