@@ -41,9 +41,8 @@ jest.mock('crypto', () => ({
4141
4242import {
4343 getAllOrganizations ,
44+ registerOrganization ,
4445 getOrganizationById ,
45- getCurrentOrganizationProfile ,
46- updateOrganizationProfile ,
4746 updateOrganization ,
4847 deleteOrganization ,
4948} from '../../controllers/organizationController' ;
@@ -79,11 +78,7 @@ const mockOrganization = {
7978 contactTitle : 'Executive Director' ,
8079 role : 'MEMBER' as OrganizationRole ,
8180 status : 'ACTIVE' as OrganizationStatus ,
82- isActive : true ,
8381 tags : [ 'Nashville' , 'Senior Services' , 'Healthcare' ] ,
84- emailVerified : true ,
85- inviteToken : null ,
86- inviteTokenExp : null ,
8782} ;
8883
8984const mockAdminOrg = {
@@ -120,24 +115,8 @@ describe('OrganizationController', () => {
120115 await getAllOrganizations ( req , res ) ;
121116
122117 expect ( prismaMock . organization . findMany ) . toHaveBeenCalledWith ( {
118+ where : { } ,
123119 orderBy : { name : 'asc' } ,
124- select : {
125- id : true ,
126- name : true ,
127- email : true ,
128- description : true ,
129- website : true ,
130- address : true ,
131- city : true ,
132- state : true ,
133- zipCode : true ,
134- phoneNumber : true ,
135- contactPerson : true ,
136- contactTitle : true ,
137- role : true ,
138- status : true ,
139- tags : true ,
140- } ,
141120 } ) ;
142121
143122 expect ( res . json ) . toHaveBeenCalledWith ( mockOrgs ) ;
@@ -156,6 +135,116 @@ describe('OrganizationController', () => {
156135 } ) ;
157136 } ) ;
158137
138+ describe ( 'registerOrganization' , ( ) => {
139+ it ( 'should register new organization - POST /api/organizations/register' , async ( ) => {
140+ const req = createMockRequest ( {
141+ body : {
142+ email : 'neworg@nonprofit.org' ,
143+ password : 'securePassword123' ,
144+ name : 'New Community Services' ,
145+ contactPerson : 'John Smith' ,
146+ contactTitle : 'Executive Director' ,
147+ city : 'Memphis' ,
148+ state : 'TN' ,
149+ tags : [ 'Community' , 'Services' ] ,
150+ } ,
151+ } ) ;
152+ const res = createMockResponse ( ) ;
153+
154+ prismaMock . organization . findFirst . mockResolvedValue ( null ) ;
155+ prismaMock . organization . create . mockResolvedValue ( {
156+ ...mockOrganization ,
157+ email : 'neworg@nonprofit.org' ,
158+ name : 'New Community Services' ,
159+ contactPerson : 'John Smith' ,
160+ status : 'PENDING' ,
161+ } ) ;
162+
163+ await registerOrganization ( req , res ) ;
164+
165+ expect ( prismaMock . organization . findFirst ) . toHaveBeenCalledWith ( {
166+ where : {
167+ OR : [
168+ { email : 'neworg@nonprofit.org' } ,
169+ { name : 'New Community Services' }
170+ ] ,
171+ } ,
172+ } ) ;
173+
174+ expect ( admin . auth ( ) . createUser ) . toHaveBeenCalledWith ( {
175+ email : 'neworg@nonprofit.org' ,
176+ password : 'securePassword123' ,
177+ emailVerified : false ,
178+ displayName : 'New Community Services' ,
179+ } ) ;
180+
181+ expect ( prismaMock . organization . create ) . toHaveBeenCalledWith ( {
182+ data : {
183+ email : 'neworg@nonprofit.org' ,
184+ name : 'New Community Services' ,
185+ contactPerson : 'John Smith' ,
186+ contactTitle : 'Executive Director' ,
187+ description : undefined ,
188+ website : undefined ,
189+ address : undefined ,
190+ city : 'Memphis' ,
191+ state : 'TN' ,
192+ zipCode : undefined ,
193+ phoneNumber : undefined ,
194+ tags : [ 'Community' , 'Services' ] ,
195+ firebaseUid : 'firebase-uid-123' ,
196+ role : 'MEMBER' ,
197+ status : 'PENDING' ,
198+ } ,
199+ } ) ;
200+
201+ expect ( res . status ) . toHaveBeenCalledWith ( 201 ) ;
202+ expect ( res . json ) . toHaveBeenCalledWith ( expect . objectContaining ( {
203+ email : 'neworg@nonprofit.org' ,
204+ name : 'New Community Services' ,
205+ status : 'PENDING' ,
206+ } ) ) ;
207+ } ) ;
208+
209+ it ( 'should reject registration with missing required fields - POST /api/organizations/register' , async ( ) => {
210+ const req = createMockRequest ( {
211+ body : {
212+ email : 'incomplete@nonprofit.org' ,
213+ // Missing password, name, contactPerson
214+ } ,
215+ } ) ;
216+ const res = createMockResponse ( ) ;
217+
218+ await registerOrganization ( req , res ) ;
219+
220+ expect ( res . status ) . toHaveBeenCalledWith ( 400 ) ;
221+ expect ( res . json ) . toHaveBeenCalledWith ( {
222+ error : 'Email, password, name, and contact person are required'
223+ } ) ;
224+ } ) ;
225+
226+ it ( 'should prevent duplicate registration - POST /api/organizations/register' , async ( ) => {
227+ const req = createMockRequest ( {
228+ body : {
229+ email : 'existing@nonprofit.org' ,
230+ password : 'password123' ,
231+ name : 'Existing Organization' ,
232+ contactPerson : 'Jane Doe' ,
233+ } ,
234+ } ) ;
235+ const res = createMockResponse ( ) ;
236+
237+ prismaMock . organization . findFirst . mockResolvedValue ( mockOrganization ) ;
238+
239+ await registerOrganization ( req , res ) ;
240+
241+ expect ( res . status ) . toHaveBeenCalledWith ( 400 ) ;
242+ expect ( res . json ) . toHaveBeenCalledWith ( {
243+ error : 'Organization with this email or name already exists'
244+ } ) ;
245+ } ) ;
246+ } ) ;
247+
159248 describe ( 'getOrganizationById' , ( ) => {
160249 it ( 'should return organization by ID - GET /api/organizations/:id' , async ( ) => {
161250 const req = createMockRequest ( {
@@ -170,11 +259,6 @@ describe('OrganizationController', () => {
170259
171260 expect ( prismaMock . organization . findUnique ) . toHaveBeenCalledWith ( {
172261 where : { id : 'org123' } ,
173- select : expect . objectContaining ( {
174- id : true ,
175- name : true ,
176- email : true ,
177- } ) ,
178262 } ) ;
179263
180264 expect ( res . json ) . toHaveBeenCalledWith ( mockOrganization ) ;
@@ -223,44 +307,41 @@ describe('OrganizationController', () => {
223307 } ) ;
224308 } ) ;
225309
226- describe ( 'getCurrentOrganizationProfile ' , ( ) => {
310+ describe ( 'getOrganizationById (/profile route) ' , ( ) => {
227311 it ( 'should return current org profile - GET /api/organizations/profile' , async ( ) => {
228312 const req = createMockRequest ( {
229313 user : { id : 'org123' } ,
314+ params : { id : 'profile' } ,
230315 } ) ;
231316 const res = createMockResponse ( ) ;
232317
233318 prismaMock . organization . findUnique . mockResolvedValue ( mockOrganization ) ;
234319
235- await getCurrentOrganizationProfile ( req , res ) ;
320+ await getOrganizationById ( req , res ) ;
236321
237322 expect ( prismaMock . organization . findUnique ) . toHaveBeenCalledWith ( {
238323 where : { id : 'org123' } ,
239- select : expect . objectContaining ( {
240- id : true ,
241- name : true ,
242- email : true ,
243- } ) ,
244324 } ) ;
245325
246326 expect ( res . json ) . toHaveBeenCalledWith ( mockOrganization ) ;
247327 } ) ;
248328
249329 it ( 'should return 401 for unauthenticated - GET /api/organizations/profile' , async ( ) => {
250- const req = createMockRequest ( ) ;
330+ const req = createMockRequest ( { params : { id : 'profile' } } ) ;
251331 const res = createMockResponse ( ) ;
252332
253- await getCurrentOrganizationProfile ( req , res ) ;
333+ await getOrganizationById ( req , res ) ;
254334
255335 expect ( res . status ) . toHaveBeenCalledWith ( 401 ) ;
256336 expect ( res . json ) . toHaveBeenCalledWith ( { error : 'Organization not authenticated' } ) ;
257337 } ) ;
258338 } ) ;
259339
260- describe ( 'updateOrganizationProfile ' , ( ) => {
340+ describe ( 'updateOrganization (/profile route) ' , ( ) => {
261341 it ( 'should update org profile - PUT /api/organizations/profile' , async ( ) => {
262342 const req = createMockRequest ( {
263343 user : { id : 'org123' } ,
344+ params : { id : 'profile' } ,
264345 body : {
265346 name : 'Updated Senior Services' ,
266347 description : 'Updated description' ,
@@ -277,7 +358,7 @@ describe('OrganizationController', () => {
277358 } ;
278359 prismaMock . organization . update . mockResolvedValue ( updatedOrg ) ;
279360
280- await updateOrganizationProfile ( req , res ) ;
361+ await updateOrganization ( req , res ) ;
281362
282363 expect ( prismaMock . organization . update ) . toHaveBeenCalledWith ( {
283364 where : { id : 'org123' } ,
@@ -287,11 +368,6 @@ describe('OrganizationController', () => {
287368 contactPerson : 'John Doe' ,
288369 contactTitle : 'New Director' ,
289370 } ) ,
290- select : expect . objectContaining ( {
291- id : true ,
292- name : true ,
293- email : true ,
294- } ) ,
295371 } ) ;
296372
297373 expect ( res . json ) . toHaveBeenCalledWith ( updatedOrg ) ;
@@ -300,6 +376,7 @@ describe('OrganizationController', () => {
300376 it ( 'should update org email and reset verification - PUT /api/organizations/profile' , async ( ) => {
301377 const req = createMockRequest ( {
302378 user : { id : 'org123' } ,
379+ params : { id : 'profile' } ,
303380 body : {
304381 email : 'newemail@nonprofit.org' ,
305382 name : 'Updated Senior Services' ,
@@ -316,11 +393,10 @@ describe('OrganizationController', () => {
316393 const updatedOrg = {
317394 ...mockOrganization ,
318395 email : 'newemail@nonprofit.org' ,
319- emailVerified : false ,
320396 } ;
321397 prismaMock . organization . update . mockResolvedValue ( updatedOrg ) ;
322398
323- await updateOrganizationProfile ( req , res ) ;
399+ await updateOrganization ( req , res ) ;
324400
325401 expect ( prismaMock . organization . findFirst ) . toHaveBeenCalledWith ( {
326402 where : {
@@ -337,9 +413,7 @@ describe('OrganizationController', () => {
337413 where : { id : 'org123' } ,
338414 data : expect . objectContaining ( {
339415 email : 'newemail@nonprofit.org' ,
340- emailVerified : false ,
341- } ) ,
342- select : expect . any ( Object ) ,
416+ } ) ,
343417 } ) ;
344418
345419 expect ( res . json ) . toHaveBeenCalled ( ) ;
@@ -348,6 +422,7 @@ describe('OrganizationController', () => {
348422 it ( 'should reject duplicate email - PUT /api/organizations/profile' , async ( ) => {
349423 const req = createMockRequest ( {
350424 user : { id : 'org123' } ,
425+ params : { id : 'profile' } ,
351426 body : {
352427 email : 'existing@nonprofit.org' ,
353428 } ,
@@ -359,7 +434,7 @@ describe('OrganizationController', () => {
359434 email : 'existing@nonprofit.org' ,
360435 } as any ) ;
361436
362- await updateOrganizationProfile ( req , res ) ;
437+ await updateOrganization ( req , res ) ;
363438
364439 expect ( res . status ) . toHaveBeenCalledWith ( 400 ) ;
365440 expect ( res . json ) . toHaveBeenCalledWith ( {
@@ -373,6 +448,7 @@ describe('OrganizationController', () => {
373448 it ( 'should handle Firebase email update failure - PUT /api/organizations/profile' , async ( ) => {
374449 const req = createMockRequest ( {
375450 user : { id : 'org123' } ,
451+ params : { id : 'profile' } ,
376452 body : {
377453 email : 'newemail@nonprofit.org' ,
378454 } ,
@@ -387,7 +463,7 @@ describe('OrganizationController', () => {
387463 const mockUpdateUser = admin . auth ( ) . updateUser as jest . Mock ;
388464 mockUpdateUser . mockRejectedValue ( new Error ( 'Firebase error' ) ) ;
389465
390- await updateOrganizationProfile ( req , res ) ;
466+ await updateOrganization ( req , res ) ;
391467
392468 expect ( res . status ) . toHaveBeenCalledWith ( 400 ) ;
393469 expect ( res . json ) . toHaveBeenCalledWith ( {
0 commit comments