@@ -8,6 +8,9 @@ use keyring_cli::cli::commands::config::{execute, ConfigCommands};
88use keyring_cli:: db:: Vault ;
99use tempfile:: TempDir ;
1010
11+ // Tests must run serially because they use global environment variables
12+ use serial_test:: serial;
13+
1114/// Helper to set up test environment and clean up afterwards
1215struct TestEnv {
1316 _temp_dir : TempDir ,
@@ -16,14 +19,19 @@ struct TestEnv {
1619
1720impl TestEnv {
1821 fn setup ( test_name : & str ) -> Self {
22+ // Brief delay to ensure previous test cleanup completes
23+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 50 ) ) ;
24+
1925 // Clean up any existing environment variables first
2026 std:: env:: remove_var ( "OK_CONFIG_DIR" ) ;
2127 std:: env:: remove_var ( "OK_DATA_DIR" ) ;
2228 std:: env:: remove_var ( "OK_MASTER_PASSWORD" ) ;
2329
2430 let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
25- let config_dir = temp_dir. path ( ) . join ( format ! ( "config_{}" , test_name) ) ;
26- let data_dir = temp_dir. path ( ) . join ( format ! ( "data_{}" , test_name) ) ;
31+ // Use UUID for unique database file name to avoid conflicts between tests
32+ let unique_id = uuid:: Uuid :: new_v4 ( ) . to_string ( ) [ ..8 ] . to_string ( ) ;
33+ let config_dir = temp_dir. path ( ) . join ( format ! ( "config_{}_{}" , test_name, unique_id) ) ;
34+ let data_dir = temp_dir. path ( ) . join ( format ! ( "data_{}_{}" , test_name, unique_id) ) ;
2735 std:: env:: set_var ( "OK_CONFIG_DIR" , config_dir. to_str ( ) . unwrap ( ) ) ;
2836 std:: env:: set_var ( "OK_DATA_DIR" , data_dir. to_str ( ) . unwrap ( ) ) ;
2937 std:: env:: set_var ( "OK_MASTER_PASSWORD" , "test-password" ) ;
@@ -49,9 +57,11 @@ impl Drop for TestEnv {
4957}
5058
5159#[ test]
60+ #[ serial]
5261fn test_config_set_persists_to_metadata ( ) {
5362 let _env = TestEnv :: setup ( "set_persists" ) ;
5463
64+
5565 // Set a config value
5666 let set_command = ConfigCommands :: Set {
5767 key : "clipboard.timeout" . to_string ( ) ,
@@ -64,7 +74,8 @@ fn test_config_set_persists_to_metadata() {
6474 . unwrap ( ) ;
6575
6676 // Give time for WAL to checkpoint and for all connections to close
67- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 500 ) ) ;
77+ // macOS CI needs more time for WAL checkpoint
78+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) ;
6879
6980 // Drop the vault from execute() before opening a new one
7081 // Verify it was saved to metadata
@@ -79,9 +90,11 @@ fn test_config_set_persists_to_metadata() {
7990}
8091
8192#[ test]
93+ #[ serial]
8294fn test_config_get_reads_from_metadata ( ) {
8395 let _env = TestEnv :: setup ( "get_reads" ) ;
8496
97+
8598 // Set a value in metadata
8699 {
87100 let mut vault = Vault :: open ( & _env. db_path , "" ) . unwrap ( ) ;
@@ -103,18 +116,22 @@ fn test_config_get_reads_from_metadata() {
103116}
104117
105118#[ test]
119+ #[ serial]
106120fn test_config_reset_clears_custom_metadata ( ) {
107121 let _env = TestEnv :: setup ( "reset_clears" ) ;
108122
123+
109124 // Set custom values directly in metadata
110125 {
111126 let mut vault = Vault :: open ( & _env. db_path , "" ) . unwrap ( ) ;
112127 vault. set_metadata ( "custom.key1" , "value1" ) . unwrap ( ) ;
113128 vault. set_metadata ( "custom.key2" , "value2" ) . unwrap ( ) ;
129+ // Force WAL checkpoint to ensure data is persisted
130+ let _ = vault. conn . pragma_update ( None , "wal_checkpoint" , "TRUNCATE" ) ;
114131 }
115132
116- // Give time for WAL to checkpoint
117- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 200 ) ) ;
133+ // Give time for WAL to checkpoint - macOS CI needs more time
134+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 500 ) ) ;
118135
119136 // Verify they were set
120137 let vault = Vault :: open ( & _env. db_path , "" ) . unwrap ( ) ;
@@ -129,7 +146,8 @@ fn test_config_reset_clears_custom_metadata() {
129146
130147 // Close vault to release lock
131148 drop ( vault) ;
132- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 100 ) ) ;
149+ // Give more time for WAL checkpoint and lock release on macOS CI
150+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) ;
133151
134152 // Reset config
135153 let reset_command = ConfigCommands :: Reset { force : true } ;
@@ -140,7 +158,8 @@ fn test_config_reset_clears_custom_metadata() {
140158 . unwrap ( ) ;
141159
142160 // Give time for WAL to checkpoint and for all connections to close
143- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 500 ) ) ;
161+ // macOS CI needs more time for WAL checkpoint
162+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) ;
144163
145164 // Verify custom metadata was cleared
146165 let vault = Vault :: open ( & _env. db_path , "" ) . unwrap ( ) ;
@@ -160,9 +179,11 @@ fn test_config_reset_clears_custom_metadata() {
160179}
161180
162181#[ test]
182+ #[ serial]
163183fn test_config_set_validates_key ( ) {
164184 let _env = TestEnv :: setup ( "validates_key" ) ;
165185
186+
166187 // Try to set an invalid key (should be rejected)
167188 let set_command = ConfigCommands :: Set {
168189 key : "invalid.unauthorized.key" . to_string ( ) ,
0 commit comments