@@ -597,7 +597,7 @@ describe("SettingsPage", () => {
597597 } ) ;
598598
599599 // The .catch sets setStatus("Failed to save settings") — assert it
600- // surfaced via ConnectionSection.status (mirrors the handleTest throw test) .
600+ // surfaced via ConnectionSection.status.
601601 const last = capturedConnection [ capturedConnection . length - 1 ] ;
602602 expect ( last ?. status ) . toBe ( "Failed to save settings" ) ;
603603 } ) ;
@@ -940,37 +940,6 @@ describe("SettingsPage", () => {
940940 } ) ;
941941 } ) ;
942942
943- describe ( "handleTest" , ( ) => {
944- it ( "forwards the result message into ConnectionSection.status on success" , async ( ) => {
945- vi . mocked ( backend . testConnection ) . mockResolvedValue ( {
946- success : true ,
947- message : "Connected!" ,
948- } ) ;
949- render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
950- await flushAsync ( ) ;
951-
952- await act ( async ( ) => {
953- capturedConnection [ capturedConnection . length - 1 ] ?. onTestConnection ( ) ;
954- await Promise . resolve ( ) ;
955- } ) ;
956-
957- expect ( capturedConnection [ capturedConnection . length - 1 ] ?. status ) . toBe ( "Connected!" ) ;
958- } ) ;
959-
960- it ( "sets status='Connection test failed' on throw" , async ( ) => {
961- vi . mocked ( backend . testConnection ) . mockRejectedValue ( new Error ( "boom" ) ) ;
962- render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
963- await flushAsync ( ) ;
964-
965- await act ( async ( ) => {
966- capturedConnection [ capturedConnection . length - 1 ] ?. onTestConnection ( ) ;
967- await Promise . resolve ( ) ;
968- } ) ;
969-
970- expect ( capturedConnection [ capturedConnection . length - 1 ] ?. status ) . toBe ( "Connection test failed" ) ;
971- } ) ;
972- } ) ;
973-
974943 describe ( "handleSaveSyncSettingChange" , ( ) => {
975944 it ( "does nothing when saveSyncSettings is still null" , async ( ) => {
976945 // Cause getSaveSyncSettings to never resolve — saveSyncSettings stays null.
@@ -1306,81 +1275,41 @@ describe("SettingsPage", () => {
13061275 } ) ;
13071276
13081277 describe ( "SteamGridDB handlers" , ( ) => {
1309- it ( "handleSgdbKeySubmit success with a non-empty value sets sgdbApiKey='set' and surfaces result.message" , async ( ) => {
1310- vi . mocked ( backend . saveSgdbApiKey ) . mockResolvedValue ( {
1311- success : true ,
1312- message : "Saved!" ,
1313- } ) ;
1278+ it ( "wires onVerifyKey directly to the verifySgdbApiKey callable (tests the key without persisting)" , async ( ) => {
1279+ vi . mocked ( backend . verifySgdbApiKey ) . mockResolvedValue ( { success : true , message : "API key is valid" } ) ;
13141280 render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
13151281 await flushAsync ( ) ;
1316- await act ( async ( ) => {
1317- capturedSgdb [ capturedSgdb . length - 1 ] ?. onSubmitKey ( "apikey123" ) ;
1318- } ) ;
13191282 const sgdb = capturedSgdb [ capturedSgdb . length - 1 ] ;
1320- expect ( sgdb ?. sgdbApiKey ) . toBe ( "set" ) ;
1321- expect ( sgdb ?. sgdbStatus ) . toBe ( "Saved!" ) ;
1322- } ) ;
1323-
1324- it ( "handleSgdbKeySubmit success with an empty value clears the masked sgdbApiKey" , async ( ) => {
1325- vi . mocked ( backend . saveSgdbApiKey ) . mockResolvedValue ( {
1326- success : true ,
1327- message : "Cleared" ,
1328- } ) ;
1329- render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
1330- await flushAsync ( ) ;
13311283 await act ( async ( ) => {
1332- capturedSgdb [ capturedSgdb . length - 1 ] ?. onSubmitKey ( " ") ;
1284+ await sgdb ?. onVerifyKey ( "apikey123 ") ;
13331285 } ) ;
1334- expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbApiKey ) . toBe ( "" ) ;
1286+ expect ( vi . mocked ( backend . verifySgdbApiKey ) ) . toHaveBeenCalledWith ( "apikey123" ) ;
1287+ // Verifying never persists — that is the modal's second step (onSaveKey).
1288+ expect ( vi . mocked ( backend . saveSgdbApiKey ) ) . not . toHaveBeenCalled ( ) ;
13351289 } ) ;
13361290
1337- it ( "handleSgdbKeySubmit sets sgdbStatus='Failed to save API key' on throw " , async ( ) => {
1338- vi . mocked ( backend . saveSgdbApiKey ) . mockRejectedValue ( new Error ( "boom" ) ) ;
1291+ it ( "handleSaveSgdbKey persists via saveSgdbApiKey and flips the masked display to a configured key " , async ( ) => {
1292+ vi . mocked ( backend . saveSgdbApiKey ) . mockResolvedValue ( { success : true , message : "Saved!" } ) ;
13391293 render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
13401294 await flushAsync ( ) ;
13411295 await act ( async ( ) => {
1342- capturedSgdb [ capturedSgdb . length - 1 ] ?. onSubmitKey ( "k ") ;
1296+ await capturedSgdb [ capturedSgdb . length - 1 ] ?. onSaveKey ( "apikey123 ") ;
13431297 } ) ;
1344- expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbStatus ) . toBe ( "Failed to save API key" ) ;
1298+ expect ( vi . mocked ( backend . saveSgdbApiKey ) ) . toHaveBeenCalledWith ( "apikey123" ) ;
1299+ // A configured key renders as the masked "••••" (sgdbApiKey truthy).
1300+ expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbApiKey ) . toBe ( "set" ) ;
13451301 } ) ;
13461302
1347- it ( "handleSgdbVerify success=true sets sgdbStatus='Valid'" , async ( ) => {
1348- vi . mocked ( backend . verifySgdbApiKey ) . mockResolvedValue ( {
1349- success : true ,
1350- message : "any" ,
1351- } ) ;
1352- render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
1353- await flushAsync ( ) ;
1354- await act ( async ( ) => {
1355- capturedSgdb [ capturedSgdb . length - 1 ] ?. onVerifyKey ( ) ;
1356- await Promise . resolve ( ) ;
1357- } ) ;
1358- expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbStatus ) . toBe ( "Valid" ) ;
1359- } ) ;
1360-
1361- it ( "handleSgdbVerify success=false surfaces result.message" , async ( ) => {
1362- vi . mocked ( backend . verifySgdbApiKey ) . mockResolvedValue ( {
1363- success : false ,
1364- message : "Invalid key" ,
1365- } ) ;
1366- render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
1367- await flushAsync ( ) ;
1368- await act ( async ( ) => {
1369- capturedSgdb [ capturedSgdb . length - 1 ] ?. onVerifyKey ( ) ;
1370- await Promise . resolve ( ) ;
1371- } ) ;
1372- expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbStatus ) . toBe ( "Invalid key" ) ;
1373- } ) ;
1374-
1375- it ( "handleSgdbVerify throws → sgdbStatus='Verification failed'" , async ( ) => {
1376- vi . mocked ( backend . verifySgdbApiKey ) . mockRejectedValue ( new Error ( "net" ) ) ;
1303+ it ( "handleSaveSgdbKey lets a save rejection propagate so the modal can surface it" , async ( ) => {
1304+ vi . mocked ( backend . saveSgdbApiKey ) . mockRejectedValue ( new Error ( "boom" ) ) ;
13771305 render ( < SettingsPage onBack = { vi . fn ( ) } /> ) ;
13781306 await flushAsync ( ) ;
1379- await act ( async ( ) => {
1380- capturedSgdb [ capturedSgdb . length - 1 ] ?. onVerifyKey ( ) ;
1381- await Promise . resolve ( ) ;
1382- } ) ;
1383- expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbStatus ) . toBe ( "Verification failed" ) ;
1307+ const sgdb = capturedSgdb [ capturedSgdb . length - 1 ] ;
1308+ // The handler does not swallow — the modal's own try/catch owns the error
1309+ // UI, so onSaveKey must reject rather than resolve.
1310+ await expect ( sgdb ?. onSaveKey ( "k" ) ) . rejects . toThrow ( "boom" ) ;
1311+ // A failed save must not flip the masked display to configured.
1312+ expect ( capturedSgdb [ capturedSgdb . length - 1 ] ?. sgdbApiKey ) . toBe ( "" ) ;
13841313 } ) ;
13851314 } ) ;
13861315
0 commit comments