1+ /**
2+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3+ *
4+ * WSO2 LLC. licenses this file to you under the Apache License,
5+ * Version 2.0 (the "License"); you may not use this file except
6+ * in compliance with the License.
7+ * You may obtain a copy of the License at
8+ *
9+ * http://www.apache.org/licenses/LICENSE-2.0
10+ *
11+ * Unless required by applicable law or agreed to in writing,
12+ * software distributed under the License is distributed on an
13+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+ * KIND, either express or implied. See the License for the
15+ * specific language governing permissions and limitations
16+ * under the License.
17+ */
18+
19+ import { describe , it , expect , vi , beforeEach , afterEach , Mock } from 'vitest' ;
20+
21+ // Adjust these paths if your project structure is different
22+ import createOrganization from '../createOrganization' ;
23+
24+ // Use the same class so we can assert instanceof and status code propagation
25+ import { AsgardeoAPIError , Organization , CreateOrganizationPayload } from '@asgardeo/node' ;
26+
27+ // ---- Mocks ----
28+ vi . mock ( '../../../AsgardeoNextClient' , ( ) => {
29+ // We return a default export with a static getInstance function we can stub
30+ return {
31+ default : {
32+ getInstance : vi . fn ( ) ,
33+ } ,
34+ } ;
35+ } ) ;
36+
37+ vi . mock ( '../getSessionId' , ( ) => ( {
38+ default : vi . fn ( ) ,
39+ } ) ) ;
40+
41+ // Pull the mocked modules so we can access their spies
42+ import AsgardeoNextClient from '../../../AsgardeoNextClient' ;
43+ import getSessionId from '../getSessionId' ;
44+
45+ describe ( 'createOrganization (Next.js server action)' , ( ) => {
46+ const mockClient = {
47+ createOrganization : vi . fn ( ) ,
48+ } ;
49+
50+ const basePayload : CreateOrganizationPayload = {
51+ name : 'Team Viewer' ,
52+ orgHandle : 'team-viewer' ,
53+ description : 'Screen sharing organization' ,
54+ parentId : 'parent-123' ,
55+ type : 'TENANT' ,
56+ } ;
57+
58+ const mockOrg : Organization = {
59+ id : 'org-001' ,
60+ name : 'Team Viewer' ,
61+ orgHandle : 'team-viewer' ,
62+ } ;
63+
64+ beforeEach ( ( ) => {
65+ vi . resetAllMocks ( ) ;
66+
67+ // Default: getInstance returns our mock client
68+ ( AsgardeoNextClient . getInstance as unknown as Mock ) . mockReturnValue ( mockClient ) ;
69+ // Default: getSessionId resolves to a session id
70+ ( getSessionId as unknown as Mock ) . mockResolvedValue ( 'sess-abc' ) ;
71+ } ) ;
72+
73+ afterEach ( ( ) => {
74+ vi . restoreAllMocks ( ) ;
75+ } ) ;
76+
77+ it ( 'should create an organization successfully when a sessionId is provided' , async ( ) => {
78+ mockClient . createOrganization . mockResolvedValueOnce ( mockOrg ) ;
79+
80+ const result = await createOrganization ( basePayload , 'sess-123' ) ;
81+
82+ expect ( AsgardeoNextClient . getInstance ) . toHaveBeenCalledTimes ( 1 ) ;
83+ expect ( getSessionId ) . not . toHaveBeenCalled ( ) ;
84+ expect ( mockClient . createOrganization ) . toHaveBeenCalledWith ( basePayload , 'sess-123' ) ;
85+ expect ( result ) . toEqual ( mockOrg ) ;
86+ } ) ;
87+
88+ it ( 'should fall back to getSessionId when sessionId is undefined' , async ( ) => {
89+ mockClient . createOrganization . mockResolvedValueOnce ( mockOrg ) ;
90+
91+ const result = await createOrganization ( basePayload , undefined as unknown as string ) ;
92+
93+ expect ( getSessionId ) . toHaveBeenCalledTimes ( 1 ) ;
94+ expect ( mockClient . createOrganization ) . toHaveBeenCalledWith ( basePayload , 'sess-abc' ) ;
95+ expect ( result ) . toEqual ( mockOrg ) ;
96+ } ) ;
97+
98+ it ( 'should fall back to getSessionId when sessionId is null' , async ( ) => {
99+ mockClient . createOrganization . mockResolvedValueOnce ( mockOrg ) ;
100+
101+ const result = await createOrganization ( basePayload , null as unknown as string ) ;
102+
103+ expect ( getSessionId ) . toHaveBeenCalledTimes ( 1 ) ;
104+ expect ( mockClient . createOrganization ) . toHaveBeenCalledWith ( basePayload , 'sess-abc' ) ;
105+ expect ( result ) . toEqual ( mockOrg ) ;
106+ } ) ;
107+
108+ it ( 'should not call getSessionId when an empty string is passed (empty string is not nullish)' , async ( ) => {
109+ mockClient . createOrganization . mockResolvedValueOnce ( mockOrg ) ;
110+
111+ const result = await createOrganization ( basePayload , '' ) ;
112+
113+ expect ( getSessionId ) . not . toHaveBeenCalled ( ) ;
114+ expect ( mockClient . createOrganization ) . toHaveBeenCalledWith ( basePayload , '' ) ;
115+ expect ( result ) . toEqual ( mockOrg ) ;
116+ } ) ;
117+
118+ it ( 'should wrap an AsgardeoAPIError thrown by client.createOrganization, preserving statusCode' , async ( ) => {
119+ const original = new AsgardeoAPIError (
120+ 'Upstream validation failed' ,
121+ 'ORG_CREATE_400' ,
122+ 'server' ,
123+ 400
124+ ) ;
125+ mockClient . createOrganization . mockRejectedValueOnce ( original ) ;
126+
127+ await expect ( createOrganization ( basePayload , 'sess-1' ) ) . rejects . toMatchObject ( {
128+ constructor : AsgardeoAPIError ,
129+ statusCode : 400 ,
130+ message : expect . stringContaining ( 'Failed to create the organization: Upstream validation failed' ) ,
131+ } ) ;
132+ } ) ;
133+ } ) ;
0 commit comments