@@ -14,14 +14,66 @@ import {
1414 property ,
1515 uniqueArray ,
1616} from "fast-check" ;
17- import { describe , expect , test } from "vitest" ;
17+ import { afterEach , describe , expect , test , vi } from "vitest" ;
1818import { SENTRY_SCOPES } from "../../src/lib/api-scope.js" ;
1919import { ValidationError } from "../../src/lib/errors.js" ;
20- import { OAUTH_SCOPES , resolveOAuthScopeString } from "../../src/lib/oauth.js" ;
20+ import {
21+ OAUTH_SCOPES ,
22+ performDeviceFlow ,
23+ resolveOAuthScopeString ,
24+ } from "../../src/lib/oauth.js" ;
2125import { DEFAULT_NUM_RUNS } from "../model-based/helpers.js" ;
2226
2327const knownScopeArb = constantFrom ( ...SENTRY_SCOPES ) ;
2428
29+ afterEach ( ( ) => {
30+ vi . useRealTimers ( ) ;
31+ vi . unstubAllGlobals ( ) ;
32+ } ) ;
33+
34+ describe ( "performDeviceFlow polling" , ( ) => {
35+ test ( "keeps the interval for pending responses and adds five seconds after slow_down" , async ( ) => {
36+ vi . useFakeTimers ( ) ;
37+ vi . setSystemTime ( 0 ) ;
38+
39+ const token = {
40+ access_token : "test-token" ,
41+ token_type : "Bearer" ,
42+ expires_in : 3600 ,
43+ } ;
44+ const fetchMock = vi
45+ . fn ( )
46+ . mockResolvedValueOnce (
47+ Response . json ( {
48+ device_code : "test-code" ,
49+ user_code : "ABCD" ,
50+ verification_uri : "https://sentry.example/oauth/device/" ,
51+ interval : 1 ,
52+ expires_in : 30 ,
53+ } )
54+ )
55+ . mockResolvedValueOnce (
56+ Response . json ( { error : "authorization_pending" } , { status : 400 } )
57+ )
58+ . mockResolvedValueOnce (
59+ Response . json ( { error : "slow_down" } , { status : 400 } )
60+ )
61+ . mockResolvedValueOnce ( Response . json ( token ) ) ;
62+ vi . stubGlobal ( "fetch" , fetchMock ) ;
63+
64+ const result = performDeviceFlow ( { onUserCode : vi . fn ( ) } ) ;
65+ await vi . advanceTimersByTimeAsync ( 1000 ) ;
66+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 2 ) ;
67+ await vi . advanceTimersByTimeAsync ( 1000 ) ;
68+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 3 ) ;
69+ await vi . advanceTimersByTimeAsync ( 5999 ) ;
70+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 3 ) ;
71+ await vi . advanceTimersByTimeAsync ( 1 ) ;
72+ await expect ( result ) . resolves . toEqual ( token ) ;
73+ expect ( fetchMock ) . toHaveBeenCalledTimes ( 4 ) ;
74+ } ) ;
75+ } ) ;
76+
2577describe ( "resolveOAuthScopeString" , ( ) => {
2678 test ( "default scopes include Team Admin for project creation" , ( ) => {
2779 expect ( OAUTH_SCOPES ) . toContain ( "team:admin" ) ;
0 commit comments