@@ -1164,7 +1164,7 @@ describe("NylasConnect (custom code exchange)", () => {
11641164 expect ( result . accessToken ) . toBe ( "builtin_access_token" ) ;
11651165 expect ( result . grantId ) . toBe ( "builtin_grant_123" ) ;
11661166 expect ( fetch ) . toHaveBeenCalledWith (
1167- "https://api.us.nylas.com/connect/token" ,
1167+ "https://api.us.nylas.com/v3/ connect/token" ,
11681168 expect . objectContaining ( {
11691169 method : "POST" ,
11701170 headers : { "Content-Type" : "application/x-www-form-urlencoded" } ,
@@ -1187,3 +1187,129 @@ describe("NylasConnect (custom code exchange)", () => {
11871187 return [ base64url ( header ) , base64url ( payload ) , "signature" ] . join ( "." ) ;
11881188 }
11891189} ) ;
1190+
1191+ describe ( "NylasConnect (API URL normalization)" , ( ) => {
1192+ const clientId = "client_123" ;
1193+ const redirectUri = "https://app.example/callback" ;
1194+
1195+ beforeEach ( ( ) => {
1196+ localStorage . clear ( ) ;
1197+ vi . restoreAllMocks ( ) ;
1198+ } ) ;
1199+
1200+ it ( "should append /v3 to default API URL when no version is present" , async ( ) => {
1201+ const auth = new NylasConnect ( {
1202+ clientId,
1203+ redirectUri,
1204+ apiUrl : "https://api.us.nylas.com" ,
1205+ } ) ;
1206+
1207+ const { url } = await auth . getAuthUrl ( ) ;
1208+ expect ( url ) . toContain ( "https://api.us.nylas.com/v3/connect/auth" ) ;
1209+ } ) ;
1210+
1211+ it ( "should append /v3 to custom API URL when no version is present" , async ( ) => {
1212+ const auth = new NylasConnect ( {
1213+ clientId,
1214+ redirectUri,
1215+ apiUrl : "https://custom.api.com" ,
1216+ } ) ;
1217+
1218+ const { url } = await auth . getAuthUrl ( ) ;
1219+ expect ( url ) . toContain ( "https://custom.api.com/v3/connect/auth" ) ;
1220+ } ) ;
1221+
1222+ it ( "should preserve existing version suffix (v2)" , async ( ) => {
1223+ const auth = new NylasConnect ( {
1224+ clientId,
1225+ redirectUri,
1226+ apiUrl : "https://api.us.nylas.com/v2" ,
1227+ } ) ;
1228+
1229+ const { url } = await auth . getAuthUrl ( ) ;
1230+ expect ( url ) . toContain ( "https://api.us.nylas.com/v2/connect/auth" ) ;
1231+ expect ( url ) . not . toContain ( "/v3" ) ;
1232+ } ) ;
1233+
1234+ it ( "should preserve existing version suffix (v1)" , async ( ) => {
1235+ const auth = new NylasConnect ( {
1236+ clientId,
1237+ redirectUri,
1238+ apiUrl : "https://api.us.nylas.com/v1" ,
1239+ } ) ;
1240+
1241+ const { url } = await auth . getAuthUrl ( ) ;
1242+ expect ( url ) . toContain ( "https://api.us.nylas.com/v1/connect/auth" ) ;
1243+ expect ( url ) . not . toContain ( "/v3" ) ;
1244+ } ) ;
1245+
1246+ it ( "should handle trailing slashes correctly" , async ( ) => {
1247+ const auth = new NylasConnect ( {
1248+ clientId,
1249+ redirectUri,
1250+ apiUrl : "https://api.us.nylas.com/" ,
1251+ } ) ;
1252+
1253+ const { url } = await auth . getAuthUrl ( ) ;
1254+ expect ( url ) . toContain ( "https://api.us.nylas.com/v3/connect/auth" ) ;
1255+ expect ( url ) . not . toContain ( "//v3" ) ; // Should not have double slashes
1256+ } ) ;
1257+
1258+ it ( "should handle multiple trailing slashes correctly" , async ( ) => {
1259+ const auth = new NylasConnect ( {
1260+ clientId,
1261+ redirectUri,
1262+ apiUrl : "https://api.us.nylas.com///" ,
1263+ } ) ;
1264+
1265+ const { url } = await auth . getAuthUrl ( ) ;
1266+ expect ( url ) . toContain ( "https://api.us.nylas.com/v3/connect/auth" ) ;
1267+ expect ( url ) . not . toContain ( "//v3" ) ; // Should not have double slashes
1268+ } ) ;
1269+
1270+ it ( "should preserve version with trailing slashes" , async ( ) => {
1271+ const auth = new NylasConnect ( {
1272+ clientId,
1273+ redirectUri,
1274+ apiUrl : "https://api.us.nylas.com/v2/" ,
1275+ } ) ;
1276+
1277+ const { url } = await auth . getAuthUrl ( ) ;
1278+ expect ( url ) . toContain ( "https://api.us.nylas.com/v2/connect/auth" ) ;
1279+ expect ( url ) . not . toContain ( "/v3" ) ;
1280+ } ) ;
1281+
1282+ it ( "should append /v3 to default URL when no apiUrl is provided" , async ( ) => {
1283+ const auth = new NylasConnect ( {
1284+ clientId,
1285+ redirectUri,
1286+ // No apiUrl provided - should use default
1287+ } ) ;
1288+
1289+ const { url } = await auth . getAuthUrl ( ) ;
1290+ expect ( url ) . toContain ( "https://api.us.nylas.com/v3/connect/auth" ) ;
1291+ } ) ;
1292+
1293+ it ( "should handle EU API URL correctly" , async ( ) => {
1294+ const auth = new NylasConnect ( {
1295+ clientId,
1296+ redirectUri,
1297+ apiUrl : "https://api.eu.nylas.com" ,
1298+ } ) ;
1299+
1300+ const { url } = await auth . getAuthUrl ( ) ;
1301+ expect ( url ) . toContain ( "https://api.eu.nylas.com/v3/connect/auth" ) ;
1302+ } ) ;
1303+
1304+ it ( "should work with higher version numbers" , async ( ) => {
1305+ const auth = new NylasConnect ( {
1306+ clientId,
1307+ redirectUri,
1308+ apiUrl : "https://api.us.nylas.com/v10" ,
1309+ } ) ;
1310+
1311+ const { url } = await auth . getAuthUrl ( ) ;
1312+ expect ( url ) . toContain ( "https://api.us.nylas.com/v10/connect/auth" ) ;
1313+ expect ( url ) . not . toContain ( "/v3" ) ;
1314+ } ) ;
1315+ } ) ;
0 commit comments