@@ -2,8 +2,12 @@ import { beforeEach, describe, expect, it, vi } from "vite-plus/test";
22
33import { createAbortError } from "@/utils/network/abort" ;
44
5- const { axiosGetMock } = vi . hoisted ( ( ) => ( {
5+ const { axiosGetMock, getCurrentProxyServiceMock , applyProxyToUrlMock } = vi . hoisted ( ( ) => ( {
66 axiosGetMock : vi . fn ( ) ,
7+ getCurrentProxyServiceMock : vi . fn ( ( ) => "https://proxy.example.com" ) ,
8+ applyProxyToUrlMock : vi . fn (
9+ ( url : string , proxyUrl : string ) => `${ proxyUrl } /${ url . replace ( / ^ h t t p s ? : \/ \/ / u, "" ) } ` ,
10+ ) ,
711} ) ) ;
812
913vi . mock ( "axios" , ( ) => ( {
@@ -43,6 +47,13 @@ vi.mock("../../schemas", () => ({
4347 validateGitHubContentsArray : vi . fn ( ( ) => ( { isValid : true , invalidItems : [ ] } ) ) ,
4448} ) ) ;
4549
50+ vi . mock ( "../../proxy" , ( ) => ( {
51+ getCurrentProxyService : getCurrentProxyServiceMock ,
52+ ProxyUrlTransformer : {
53+ applyProxyToUrl : applyProxyToUrlMock ,
54+ } ,
55+ } ) ) ;
56+
4657vi . mock ( "./cacheState" , ( ) => ( {
4758 ensureCacheInitialized : vi . fn ( async ( ) => { } ) ,
4859 getCachedDirectoryContents : vi . fn ( async ( ) => null ) ,
@@ -67,7 +78,7 @@ if (typeof window === "undefined") {
6778 vi . stubGlobal ( "window" , globalThis ) ;
6879}
6980
70- import { shouldUseServerAPI } from "../../config" ;
81+ import { getForceServerProxy , shouldUseServerAPI } from "../../config" ;
7182const { clearBatcherCache, getContents, getFileContent } = await import ( "./service" ) ;
7283
7384describe ( "content service abort handling" , ( ) => {
@@ -77,6 +88,11 @@ describe("content service abort handling", () => {
7788 vi . stubGlobal ( "window" , globalThis ) ;
7889 clearBatcherCache ( ) ;
7990 vi . mocked ( shouldUseServerAPI ) . mockReturnValue ( false ) ;
91+ vi . mocked ( getForceServerProxy ) . mockReturnValue ( false ) ;
92+ getCurrentProxyServiceMock . mockReturnValue ( "https://proxy.example.com" ) ;
93+ applyProxyToUrlMock . mockImplementation (
94+ ( url : string , proxyUrl : string ) => `${ proxyUrl } /${ url . replace ( / ^ h t t p s ? : \/ \/ / u, "" ) } ` ,
95+ ) ;
8096 } ) ;
8197
8298 it ( "propagates abort to direct fetch requests" , async ( ) => {
@@ -176,4 +192,56 @@ describe("content service abort handling", () => {
176192 await expect ( promise ) . rejects . toMatchObject ( { name : "AbortError" } ) ;
177193 expect ( fetchSignal ?. aborted ) . toBe ( true ) ;
178194 } ) ;
195+
196+ it ( "prefers direct proxy URL for file content requests" , async ( ) => {
197+ const fetchMock = vi . fn ( async ( ) => ( {
198+ ok : true ,
199+ status : 200 ,
200+ statusText : "OK" ,
201+ text : async ( ) => "proxy content" ,
202+ } ) ) ;
203+ vi . stubGlobal ( "fetch" , fetchMock ) ;
204+
205+ const content = await getFileContent (
206+ "https://raw.githubusercontent.com/test-owner/test-repo/main/docs/readme.md" ,
207+ ) ;
208+
209+ expect ( content ) . toBe ( "proxy content" ) ;
210+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
211+ expect ( fetchMock . mock . calls [ 0 ] ?. [ 0 ] ) . toBe (
212+ "https://proxy.example.com/raw.githubusercontent.com/test-owner/test-repo/main/docs/readme.md" ,
213+ ) ;
214+ } ) ;
215+
216+ it ( "falls back to server API when direct proxy request fails in force mode" , async ( ) => {
217+ vi . mocked ( getForceServerProxy ) . mockReturnValue ( true ) ;
218+ const fetchMock = vi
219+ . fn ( )
220+ . mockResolvedValueOnce ( {
221+ ok : false ,
222+ status : 502 ,
223+ statusText : "Bad Gateway" ,
224+ text : async ( ) => "" ,
225+ } )
226+ . mockResolvedValueOnce ( {
227+ ok : true ,
228+ status : 200 ,
229+ statusText : "OK" ,
230+ text : async ( ) => "fallback content" ,
231+ } ) ;
232+ vi . stubGlobal ( "fetch" , fetchMock ) ;
233+
234+ const content = await getFileContent (
235+ "https://raw.githubusercontent.com/test-owner/test-repo/main/docs/readme.md" ,
236+ ) ;
237+
238+ expect ( content ) . toBe ( "fallback content" ) ;
239+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 2 ) ;
240+ expect ( fetchMock . mock . calls [ 0 ] ?. [ 0 ] ) . toBe (
241+ "https://proxy.example.com/raw.githubusercontent.com/test-owner/test-repo/main/docs/readme.md" ,
242+ ) ;
243+ expect ( String ( fetchMock . mock . calls [ 1 ] ?. [ 0 ] ?? "" ) ) . toContain (
244+ "/api/github?action=getGitHubAsset&url=" ,
245+ ) ;
246+ } ) ;
179247} ) ;
0 commit comments