@@ -3,7 +3,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
33// Set env var before importing
44process . env . JIRA_TOKEN = 'test-token' ;
55
6- import { extractJQL , jiraAPI , searchIssues , getIssue , formatIssue , main } from '../jira-api.js' ;
6+ import { extractJQL , jiraAPI , searchIssues , getIssue , formatIssue , getJiraApiBaseUrl , getJiraCloudId , resetJiraCloudIdCache , main } from '../jira-api.js' ;
77import readline from 'readline' ;
88
99// Mock fetch
@@ -45,6 +45,7 @@ describe('jiraAPI', () => {
4545 vi . resetModules ( ) ;
4646 process . env = { ...originalEnv } ;
4747 global . fetch . mockClear ( ) ;
48+ resetJiraCloudIdCache ( ) ;
4849 } ) ;
4950
5051 afterEach ( ( ) => {
@@ -57,6 +58,7 @@ describe('jiraAPI', () => {
5758 } ) ;
5859
5960 it ( 'should handle 401 Unauthorized error' , async ( ) => {
61+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
6062 global . fetch . mockResolvedValue ( {
6163 ok : false ,
6264 status : 401 ,
@@ -67,6 +69,7 @@ describe('jiraAPI', () => {
6769 } ) ;
6870
6971 it ( 'should handle 404 Not Found error' , async ( ) => {
72+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
7073 global . fetch . mockResolvedValue ( {
7174 ok : false ,
7275 status : 404 ,
@@ -77,6 +80,7 @@ describe('jiraAPI', () => {
7780 } ) ;
7881
7982 it ( 'should return JSON on success' , async ( ) => {
83+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
8084 const mockData = { key : 'TT-123' } ;
8185 global . fetch . mockResolvedValue ( {
8286 ok : true ,
@@ -86,11 +90,57 @@ describe('jiraAPI', () => {
8690 const result = await jiraAPI ( '/test' ) ;
8791 expect ( result ) . toEqual ( mockData ) ;
8892 } ) ;
93+
94+ it ( 'should fetch JIRA_CLOUD_ID from tenant_info when it is not set' , async ( ) => {
95+ delete process . env . JIRA_CLOUD_ID ;
96+ global . fetch
97+ . mockResolvedValueOnce ( {
98+ ok : true ,
99+ json : vi . fn ( ) . mockResolvedValue ( { cloudId : 'cloud-123' } )
100+ } )
101+ . mockResolvedValueOnce ( {
102+ ok : true ,
103+ json : vi . fn ( ) . mockResolvedValue ( { } )
104+ } ) ;
105+
106+ await jiraAPI ( '/test' ) ;
107+
108+ expect ( global . fetch . mock . calls [ 0 ] [ 0 ] ) . toBe ( 'https://tyktech.atlassian.net/_edge/tenant_info' ) ;
109+ expect ( global . fetch . mock . calls [ 1 ] [ 0 ] ) . toBe ( 'https://api.atlassian.com/ex/jira/cloud-123/rest/api/3/test' ) ;
110+ } ) ;
111+
112+ it ( 'should use Atlassian scoped API token URL when JIRA_CLOUD_ID is set' , async ( ) => {
113+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
114+ global . fetch . mockResolvedValue ( {
115+ ok : true ,
116+ json : vi . fn ( ) . mockResolvedValue ( { } )
117+ } ) ;
118+
119+ await jiraAPI ( '/test' ) ;
120+
121+ expect ( global . fetch . mock . calls [ 0 ] [ 0 ] ) . toBe ( 'https://api.atlassian.com/ex/jira/cloud-123/rest/api/3/test' ) ;
122+ } ) ;
123+
124+ it ( 'should build Jira API base URL from JIRA_CLOUD_ID when present' , async ( ) => {
125+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
126+ await expect ( getJiraApiBaseUrl ( ) ) . resolves . toBe ( 'https://api.atlassian.com/ex/jira/cloud-123' ) ;
127+ } ) ;
128+
129+ it ( 'should throw if tenant_info does not return a cloud ID' , async ( ) => {
130+ delete process . env . JIRA_CLOUD_ID ;
131+ global . fetch . mockResolvedValue ( {
132+ ok : true ,
133+ json : vi . fn ( ) . mockResolvedValue ( { } )
134+ } ) ;
135+
136+ await expect ( getJiraCloudId ( ) ) . rejects . toThrow ( 'JIRA cloud ID was not found' ) ;
137+ } ) ;
89138} ) ;
90139
91140describe ( 'searchIssues' , ( ) => {
92141 beforeEach ( ( ) => {
93142 global . fetch . mockClear ( ) ;
143+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
94144 } ) ;
95145
96146 it ( 'should call jiraAPI with correct parameters' , async ( ) => {
@@ -110,6 +160,26 @@ describe('searchIssues', () => {
110160 } ) ;
111161} ) ;
112162
163+ describe ( 'getIssue' , ( ) => {
164+ beforeEach ( ( ) => {
165+ global . fetch . mockClear ( ) ;
166+ process . env . JIRA_CLOUD_ID = 'cloud-123' ;
167+ } ) ;
168+
169+ it ( 'should request only fields needed for branch suggestions' , async ( ) => {
170+ global . fetch . mockResolvedValue ( {
171+ ok : true ,
172+ json : vi . fn ( ) . mockResolvedValue ( { key : 'TT-123' } )
173+ } ) ;
174+
175+ await getIssue ( 'TT-123' ) ;
176+
177+ const url = global . fetch . mock . calls [ 0 ] [ 0 ] ;
178+ expect ( url ) . toContain ( '/issue/TT-123?' ) ;
179+ expect ( url ) . toContain ( 'fields=summary,priority,issuetype,fixVersions' ) ;
180+ } ) ;
181+ } ) ;
182+
113183describe ( 'formatIssue' , ( ) => {
114184 it ( 'should format issue correctly' , ( ) => {
115185 const issue = {
@@ -243,4 +313,4 @@ describe('main execution', () => {
243313 expect ( global . fetch ) . toHaveBeenCalledTimes ( 1 ) ;
244314 expect ( consoleLogMock ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Displayed 50 of 100 total issues' ) ) ;
245315 } ) ;
246- } ) ;
316+ } ) ;
0 commit comments