1- import { describe , it , expect , beforeEach } from 'vitest' ;
1+ import { describe , it , expect , beforeEach , vi } from 'vitest' ;
22import { createGitHubAuthHeaders , isGitHubUrl } from './git-auth-helpers' ;
33import { oAuthState } from './state' ;
44
5+ vi . mock ( 'virtual:cors-proxy-url' , ( ) => ( {
6+ corsProxyUrl : 'https://corsproxyurl/' ,
7+ } ) ) ;
8+
59describe ( 'isGitHubUrl' , ( ) => {
610 describe ( 'direct GitHub URLs' , ( ) => {
711 it ( 'returns true for github.com URLs' , ( ) => {
@@ -40,34 +44,27 @@ describe('isGitHubUrl', () => {
4044 it ( 'returns true for GitHub URLs through CORS proxy' , ( ) => {
4145 expect (
4246 isGitHubUrl (
43- 'https://playground.wordpress.net/cors-proxy.php?https://github.com/user/repo'
44- )
45- ) . toBe ( true ) ;
46- expect (
47- isGitHubUrl (
48- 'http://127.0.0.1:5263/cors-proxy.php?https://github.com/user/repo'
47+ 'https://corsproxyurl/?https://github.com/user/repo'
4948 )
5049 ) . toBe ( true ) ;
5150 } ) ;
5251
5352 it ( 'returns false for non-GitHub URLs through CORS proxy' , ( ) => {
5453 expect (
5554 isGitHubUrl (
56- 'https://playground.wordpress.net/cors-proxy.php ?https://gitlab.com/user/repo'
55+ 'https://corsproxyurl/ ?https://gitlab.com/user/repo'
5756 )
5857 ) . toBe ( false ) ;
5958 } ) ;
6059
6160 it ( 'returns false for malicious URLs through CORS proxy' , ( ) => {
6261 expect (
6362 isGitHubUrl (
64- 'https://playground.wordpress.net/cors-proxy.php ?https://evil.com/github.com/fake'
63+ 'https://corsproxyurl/ ?https://evil.com/github.com/fake'
6564 )
6665 ) . toBe ( false ) ;
6766 expect (
68- isGitHubUrl (
69- 'http://127.0.0.1:5263/cors-proxy.php?https://github.com.evil.com'
70- )
67+ isGitHubUrl ( 'https://corsproxyurl/?https://github.com.evil.com' )
7168 ) . toBe ( false ) ;
7269 } ) ;
7370 } ) ;
@@ -116,7 +113,7 @@ describe('createGitHubAuthHeaders integration', () => {
116113 it ( 'includes Authorization header for GitHub URLs through CORS proxy' , ( ) => {
117114 const getHeaders = createGitHubAuthHeaders ( ) ;
118115 const headers = getHeaders (
119- 'https://playground.wordpress.net/cors-proxy.php ?https://github.com/user/repo'
116+ 'https://corsproxyurl/ ?https://github.com/user/repo'
120117 ) ;
121118
122119 expect ( headers ) . toHaveProperty ( 'Authorization' ) ;
@@ -136,7 +133,7 @@ describe('createGitHubAuthHeaders integration', () => {
136133 it ( 'does NOT include Authorization header for non-GitHub URLs through CORS proxy' , ( ) => {
137134 const getHeaders = createGitHubAuthHeaders ( ) ;
138135 const headers = getHeaders (
139- 'https://playground.wordpress.net/cors-proxy.php ?https://gitlab.com/user/repo'
136+ 'https://corsproxyurl/ ?https://gitlab.com/user/repo'
140137 ) ;
141138
142139 expect ( headers ) . toEqual ( { } ) ;
@@ -164,5 +161,22 @@ describe('createGitHubAuthHeaders integration', () => {
164161 const decoded = atob ( headers . Authorization . replace ( 'Basic ' , '' ) ) ;
165162 expect ( decoded ) . toBe ( 'test-token:' ) ;
166163 } ) ;
164+
165+ it ( 'handles tokens with non-ASCII characters (UTF-8)' , ( ) => {
166+ // This would fail with plain btoa(): "characters outside of the Latin1 range"
167+ oAuthState . value = {
168+ token : 'test-token-ąñ-emoji-🔑' ,
169+ isAuthorizing : false ,
170+ } ;
171+ const getHeaders = createGitHubAuthHeaders ( ) ;
172+ const headers = getHeaders ( 'https://github.com/user/repo' ) ;
173+
174+ expect ( headers ) . toHaveProperty ( 'Authorization' ) ;
175+ expect ( headers . Authorization ) . toMatch ( / ^ B a s i c / ) ;
176+
177+ // Verify the encoding is valid base64
178+ const base64Part = headers . Authorization . replace ( 'Basic ' , '' ) ;
179+ expect ( ( ) => atob ( base64Part ) ) . not . toThrow ( ) ;
180+ } ) ;
167181 } ) ;
168182} ) ;
0 commit comments