@@ -3,4 +3,186 @@ const assert = require('assert');
33const { Application, MailSystem } = require ( './main' ) ;
44
55// TODO: write your tests here
6- // Remember to use Stub, Mock, and Spy when necessary
6+ // Remember to use Stub, Mock, and Spy when necessary
7+ const fs = require ( 'node:fs' ) ;
8+ const util = require ( 'util' ) ;
9+ const writeFile = util . promisify ( fs . writeFile ) ;
10+ const unlinkFile = util . promisify ( fs . unlink ) ;
11+
12+ async function createTestFile ( content = "Alice\nBob\nCharlie" ) {
13+ await writeFile ( "name_list.txt" , content , 'utf-8' ) ;
14+ }
15+
16+ async function removeTestFile ( ) {
17+ try {
18+ await unlinkFile ( "name_list.txt" ) ;
19+ } catch ( error ) {
20+ // Ignore errors
21+ }
22+ }
23+
24+ test . before ( async ( ) => {
25+ await createTestFile ( ) ;
26+ } ) ;
27+
28+ test . after ( async ( ) => {
29+ await removeTestFile ( ) ;
30+ } ) ;
31+
32+ // Tests for MailSystem class
33+ test ( 'MailSystem.write should return congratulatory message' , ( t ) => {
34+ const mailSystem = new MailSystem ( ) ;
35+ const result = mailSystem . write ( 'John' ) ;
36+ assert . strictEqual ( result , 'Congrats, John!' ) ;
37+ } ) ;
38+
39+ test ( 'MailSystem.send should return boolean indicating success' , ( t ) => {
40+ const mailSystem = new MailSystem ( ) ;
41+
42+ const originalRandom = Math . random ;
43+
44+ // Test success case
45+ Math . random = ( ) => 0.6 ; // return true
46+ const successResult = mailSystem . send ( 'John' , 'Congrats, John!' ) ;
47+ assert . strictEqual ( successResult , true ) ;
48+
49+ // Test failure case
50+ Math . random = ( ) => 0.4 ; // return false
51+ const failureResult = mailSystem . send ( 'John' , 'Congrats, John!' ) ;
52+ assert . strictEqual ( failureResult , false ) ;
53+
54+ Math . random = originalRandom ;
55+ } ) ;
56+
57+ test ( 'Application constructor should initialize properties' , async ( t ) => {
58+ await createTestFile ( "Alice\nBob\nCharlie" ) ;
59+ const app = new Application ( ) ;
60+
61+ await new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
62+
63+ assert . deepStrictEqual ( app . people , [ 'Alice' , 'Bob' , 'Charlie' ] ) ;
64+ assert . deepStrictEqual ( app . selected , [ ] ) ;
65+ assert . ok ( app . mailSystem instanceof MailSystem ) ;
66+ } ) ;
67+
68+ test ( 'getNames should read and parse names from file' , async ( t ) => {
69+ await createTestFile ( "Dave\nEve\nFrank" ) ;
70+
71+ const app = new Application ( ) ;
72+ const [ people , selected ] = await app . getNames ( ) ;
73+
74+ assert . deepStrictEqual ( people , [ 'Dave' , 'Eve' , 'Frank' ] ) ;
75+ assert . deepStrictEqual ( selected , [ ] ) ;
76+ } ) ;
77+
78+ test ( 'getRandomPerson should return a person from the people array' , async ( t ) => {
79+ const app = new Application ( ) ;
80+
81+ await new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
82+
83+ app . people = [ 'Alice' , 'Bob' , 'Charlie' ] ;
84+
85+ const originalRandom = Math . random ;
86+ const originalFloor = Math . floor ;
87+
88+ // Create a spy
89+ let floorCallCount = 0 ;
90+ Math . floor = ( num ) => {
91+ floorCallCount ++ ;
92+ return originalFloor ( num ) ;
93+ } ;
94+
95+ Math . random = ( ) => 0 ; //select idx 0
96+ assert . strictEqual ( app . getRandomPerson ( ) , 'Alice' ) ;
97+
98+ Math . random = ( ) => 0.34 ; // select idx 1
99+ assert . strictEqual ( app . getRandomPerson ( ) , 'Bob' ) ;
100+
101+ Math . random = ( ) => 0.67 ; // select idx 2
102+ assert . strictEqual ( app . getRandomPerson ( ) , 'Charlie' ) ;
103+
104+ assert . strictEqual ( floorCallCount , 3 ) ;
105+
106+ Math . random = originalRandom ;
107+ Math . floor = originalFloor ;
108+ } ) ;
109+
110+ test ( 'selectNextPerson should select a random unselected person' , async ( t ) => {
111+ const app = new Application ( ) ;
112+ await new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
113+
114+ app . people = [ 'Alice' , 'Bob' , 'Charlie' ] ;
115+ app . selected = [ ] ;
116+
117+ const originalGetRandomPerson = app . getRandomPerson ;
118+ let randomPersonCalls = 0 ;
119+
120+ app . getRandomPerson = ( ) => {
121+ randomPersonCalls ++ ;
122+ if ( randomPersonCalls === 1 ) return 'Bob' ;
123+ if ( randomPersonCalls === 2 ) return 'Bob' ;
124+ if ( randomPersonCalls === 3 ) return 'Alice' ;
125+ return 'Charlie' ;
126+ } ;
127+
128+ const result = app . selectNextPerson ( ) ;
129+ assert . strictEqual ( result , 'Bob' ) ;
130+ assert . deepStrictEqual ( app . selected , [ 'Bob' ] ) ;
131+
132+ const secondResult = app . selectNextPerson ( ) ;
133+ assert . strictEqual ( secondResult , 'Alice' ) ;
134+ assert . deepStrictEqual ( app . selected , [ 'Bob' , 'Alice' ] ) ;
135+
136+ app . getRandomPerson = originalGetRandomPerson ;
137+ } ) ;
138+
139+ test ( 'selectNextPerson should return null when all people are selected' , async ( t ) => {
140+ const app = new Application ( ) ;
141+ await new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
142+
143+ app . people = [ 'Alice' , 'Bob' ] ;
144+ app . selected = [ 'Alice' , 'Bob' ] ;
145+
146+ const result = app . selectNextPerson ( ) ;
147+
148+ assert . strictEqual ( result , null ) ;
149+ } ) ;
150+
151+ test ( 'notifySelected should send mail to all selected people' , async ( t ) => {
152+ const app = new Application ( ) ;
153+ await new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
154+
155+ app . selected = [ 'Alice' , 'Bob' ] ;
156+
157+ const originalWrite = app . mailSystem . write ;
158+ const originalSend = app . mailSystem . send ;
159+
160+ const writeCalls = [ ] ;
161+ const sendCalls = [ ] ;
162+
163+ app . mailSystem . write = ( name ) => {
164+ writeCalls . push ( name ) ;
165+ return `Congrats, ${ name } !` ;
166+ } ;
167+
168+ app . mailSystem . send = ( name , context ) => {
169+ sendCalls . push ( { name, context } ) ;
170+ return true ;
171+ } ;
172+
173+ app . notifySelected ( ) ;
174+
175+ assert . strictEqual ( writeCalls . length , 2 ) ;
176+ assert . strictEqual ( sendCalls . length , 2 ) ;
177+
178+ assert . strictEqual ( writeCalls [ 0 ] , 'Alice' ) ;
179+ assert . strictEqual ( writeCalls [ 1 ] , 'Bob' ) ;
180+
181+ assert . strictEqual ( sendCalls [ 0 ] . name , 'Alice' ) ;
182+ assert . strictEqual ( sendCalls [ 0 ] . context , 'Congrats, Alice!' ) ;
183+ assert . strictEqual ( sendCalls [ 1 ] . name , 'Bob' ) ;
184+ assert . strictEqual ( sendCalls [ 1 ] . context , 'Congrats, Bob!' ) ;
185+
186+ app . mailSystem . write = originalWrite ;
187+ app . mailSystem . send = originalSend ;
188+ } ) ;
0 commit comments