@@ -15,8 +15,8 @@ const languages = {
1515
1616describe ( "fetchLanguageData" , ( ) => {
1717 beforeEach ( ( ) => {
18- vi . stubEnv ( 'GITHUB_USERNAME' , ' testuser' ) ;
19- vi . stubEnv ( ' IGNORED_REPOS' , ' ignored-repo' ) ;
18+ vi . stubEnv ( "GITHUB_USERNAMES" , " testuser" ) ;
19+ vi . stubEnv ( " IGNORED_REPOS" , " ignored-repo" ) ;
2020 global . fetch = vi . fn ( ) ;
2121 vi . resetModules ( ) ;
2222 resetCache ( ) ;
@@ -33,14 +33,14 @@ describe("fetchLanguageData", () => {
3333 expect ( global . fetch ) . not . toHaveBeenCalled ( ) ;
3434 } ) ;
3535
36- it ( "throws error when GITHUB_USERNAME env variable not set" , async ( ) => {
36+ it ( "throws error when GITHUB_USERNAMES env variable not set" , async ( ) => {
3737 vi . unstubAllEnvs ( ) ;
38- await expect ( fetchLanguageData ( ) ) . rejects . toThrow ( 'GITHUB_USERNAME environment variable is not set' ) ;
38+ await expect ( fetchLanguageData ( ) ) . rejects . toThrow ( "At least one of GITHUB_USERNAMES or GITHUB_ORGS must be set" ) ;
3939 } ) ;
4040
4141 it ( "handles missing IGNORED_REPOS env variable" , async ( ) => {
4242 vi . unstubAllEnvs ( ) ;
43- vi . stubEnv ( 'GITHUB_USERNAME' , ' testuser' ) ;
43+ vi . stubEnv ( "GITHUB_USERNAMES" , " testuser" ) ;
4444
4545 global . fetch
4646 . mockResolvedValueOnce ( { ok : true , json : async ( ) => repos } )
@@ -64,17 +64,17 @@ describe("fetchLanguageData", () => {
6464 await fetchLanguageData ( ) ;
6565
6666 expect ( global . fetch ) . toHaveBeenCalledWith (
67- ' https://api.github.com/users/testuser/repos?per_page=100'
67+ " https://api.github.com/users/testuser/repos?per_page=100"
6868 ) ;
6969 expect ( global . fetch ) . toHaveBeenCalledWith (
70- ' https://api.github.com/repos/user/repo1/languages'
70+ " https://api.github.com/repos/user/repo1/languages"
7171 ) ;
7272
7373 expect ( global . fetch ) . not . toHaveBeenCalledWith (
74- ' https://api.github.com/repos/user/repo2/languages'
74+ " https://api.github.com/repos/user/repo2/languages"
7575 ) ;
7676 expect ( global . fetch ) . not . toHaveBeenCalledWith (
77- ' https://api.github.com/repos/user/ignored-repo/languages'
77+ " https://api.github.com/repos/user/ignored-repo/languages"
7878 ) ;
7979 } ) ;
8080
@@ -97,10 +97,10 @@ describe("fetchLanguageData", () => {
9797 global . fetch . mockResolvedValueOnce ( {
9898 ok : false ,
9999 status : 404 ,
100- statusText : ' Not Found'
100+ statusText : " Not Found"
101101 } ) ;
102102
103- await expect ( fetchLanguageData ( ) ) . rejects . toThrow ( ' GitHub API error: 404 Not Found' ) ;
103+ await expect ( fetchLanguageData ( ) ) . rejects . toThrow ( " GitHub API error: 404 Not Found" ) ;
104104 } ) ;
105105
106106 it ( "caches results within refresh interval" , async ( ) => {
@@ -128,33 +128,53 @@ describe("fetchLanguageData", () => {
128128 const result = await fetchLanguageData ( ) ;
129129 expect ( result ) . toEqual ( { Python : 500 } ) ;
130130 } ) ;
131+
132+ it ( "fetches from organizations" , async ( ) => {
133+ vi . unstubAllEnvs ( ) ;
134+ vi . stubEnv ( "GITHUB_ORGS" , "test-org" ) ;
135+
136+ const orgRepos = [
137+ { name : "org-repo" , fork : false , full_name : "test-org/org-repo" }
138+ ] ;
139+
140+ global . fetch
141+ . mockResolvedValueOnce ( { ok : true , json : async ( ) => orgRepos } )
142+ . mockResolvedValueOnce ( { ok : true , json : async ( ) => ( { TypeScript : 4000 } ) } )
143+
144+ const result = await fetchLanguageData ( ) ;
145+
146+ expect ( global . fetch ) . toHaveBeenCalledWith (
147+ "https://api.github.com/orgs/test-org/repos?per_page=100"
148+ ) ;
149+ expect ( result ) . toEqual ( { TypeScript : 4000 } ) ;
150+ } ) ;
131151} ) ;
132152
133153describe ( "processLanguageData" , ( ) => {
134154 it ( "calculates percentages correctly" , ( ) => {
135155 const data = { JavaScript : 5000 , Python : 3000 , HTML : 2000 } ;
136156 const result = processLanguageData ( data , 3 ) ;
137157 expect ( result ) . toHaveLength ( 3 ) ;
138- expect ( result [ 0 ] ) . toEqual ( { lang : ' JavaScript' , pct : 50 } ) ;
139- expect ( result [ 1 ] ) . toEqual ( { lang : ' Python' , pct : 30 } ) ;
140- expect ( result [ 2 ] ) . toEqual ( { lang : ' HTML' , pct : 20 } ) ;
158+ expect ( result [ 0 ] ) . toEqual ( { lang : " JavaScript" , pct : 50 } ) ;
159+ expect ( result [ 1 ] ) . toEqual ( { lang : " Python" , pct : 30 } ) ;
160+ expect ( result [ 2 ] ) . toEqual ( { lang : " HTML" , pct : 20 } ) ;
141161 } ) ;
142162
143163 it ( "sorts by percentage descending" , ( ) => {
144164 const data = { HTML : 1000 , JavaScript : 5000 , Python : 3000 } ;
145165 const result = processLanguageData ( data , 3 ) ;
146166
147- expect ( result [ 0 ] . lang ) . toBe ( ' JavaScript' ) ;
148- expect ( result [ 1 ] . lang ) . toBe ( ' Python' ) ;
149- expect ( result [ 2 ] . lang ) . toBe ( ' HTML' ) ;
167+ expect ( result [ 0 ] . lang ) . toBe ( " JavaScript" ) ;
168+ expect ( result [ 1 ] . lang ) . toBe ( " Python" ) ;
169+ expect ( result [ 2 ] . lang ) . toBe ( " HTML" ) ;
150170 } ) ;
151171
152172 it ( "limits to count" , ( ) => {
153173 const data = { JavaScript : 5000 , Python : 3000 , HTML : 2000 , CSS : 1000 } ;
154174 const result = processLanguageData ( data , 2 ) ;
155175
156176 expect ( result ) . toHaveLength ( 2 ) ;
157- expect ( result . map ( l => l . lang ) ) . toEqual ( [ ' JavaScript' , ' Python' ] ) ;
177+ expect ( result . map ( l => l . lang ) ) . toEqual ( [ " JavaScript" , " Python" ] ) ;
158178 } ) ;
159179
160180 it ( "renormalizes percentages after slicing" , ( ) => {
@@ -166,6 +186,6 @@ describe("processLanguageData", () => {
166186 } ) ;
167187
168188 it ( "throws when no language data" , ( ) => {
169- expect ( ( ) => processLanguageData ( { } , 5 ) ) . toThrow ( ' No language data available' ) ;
189+ expect ( ( ) => processLanguageData ( { } , 5 ) ) . toThrow ( " No language data available" ) ;
170190 } ) ;
171191} ) ;
0 commit comments