@@ -1533,14 +1533,10 @@ impl TestContext {
15331533 let mut settings = insta:: Settings :: clone_current ( ) ;
15341534 let project_dir_uri = Uri :: from_file_path ( project_dir. as_std_path ( ) )
15351535 . map_err ( |( ) | anyhow ! ( "Failed to convert root directory to uri" ) ) ?;
1536- settings. add_filter ( & tempdir_filter ( project_dir. as_str ( ) ) , "<temp_dir>/" ) ;
1537- settings. add_filter ( & tempdir_filter ( project_dir_uri. path ( ) ) , "<temp_dir>/" ) ;
1538- settings. add_filter ( r#"\\\\"# , "/" ) ;
1539- settings. add_filter (
1540- r#"The system cannot find the file specified."# ,
1541- "No such file or directory" ,
1542- ) ;
1543- settings. add_filter ( r"file://.*/stdlib/" , "file://<typeshed>/stdlib/" ) ;
1536+ for ( pattern, replacement) in snapshot_filters ( project_dir. as_str ( ) , project_dir_uri. path ( ) )
1537+ {
1538+ settings. add_filter ( & pattern, replacement) ;
1539+ }
15441540
15451541 let settings_scope = settings. bind_to_scope ( ) ;
15461542
@@ -1559,3 +1555,74 @@ impl TestContext {
15591555fn tempdir_filter ( path : impl AsRef < str > ) -> String {
15601556 format ! ( r"{}\\?/?" , regex:: escape( path. as_ref( ) ) )
15611557}
1558+
1559+ /// What a snapshot has to have taken out of it to be the same everywhere, in the
1560+ /// order it is taken out.
1561+ ///
1562+ /// The order carries meaning: a path inside a JSON snapshot has its separators
1563+ /// escaped, so on Windows nothing that matches `\` matches the `\\` the snapshot
1564+ /// holds. The escaping is undone part way through, and what the directory looks
1565+ /// like on either side of that is matched separately.
1566+ fn snapshot_filters ( project_dir : & str , uri_path : & str ) -> Vec < ( String , & ' static str ) > {
1567+ vec ! [
1568+ // the directory as the system spells it, which on Windows is with `\`
1569+ ( tempdir_filter( project_dir) , "<temp_dir>/" ) ,
1570+ // and as a `file:` URI spells it, which is with `/` and a leading one
1571+ ( tempdir_filter( uri_path) , "<temp_dir>/" ) ,
1572+ // an escaped separator, which is what a JSON snapshot holds
1573+ ( r#"\\\\"# . to_string( ) , "/" ) ,
1574+ // the directory again, now that the line above has left it spelled with
1575+ // `/`. On a system that spells it that way already this is the first
1576+ // filter over again, which matches nothing new
1577+ (
1578+ tempdir_filter( project_dir. replace( '\\' , "/" ) ) ,
1579+ "<temp_dir>/" ,
1580+ ) ,
1581+ (
1582+ r#"The system cannot find the file specified."# . to_string( ) ,
1583+ "No such file or directory" ,
1584+ ) ,
1585+ (
1586+ r"file://.*/stdlib/" . to_string( ) ,
1587+ "file://<typeshed>/stdlib/" ,
1588+ ) ,
1589+ ]
1590+ }
1591+
1592+ /// A path a JSON snapshot holds is filtered whichever way the system spells it.
1593+ ///
1594+ /// Windows spells it with `\`, which a JSON snapshot escapes, and a filter
1595+ /// written for the unescaped spelling silently misses — leaving a real path in
1596+ /// the snapshot, and a test that only fails there.
1597+ #[ test]
1598+ fn a_path_in_a_json_snapshot_is_the_temp_directory_on_either_system ( ) {
1599+ let filtered = |directory : & str , uri_path : & str , snapshot : & str | {
1600+ snapshot_filters ( directory, uri_path) . into_iter ( ) . fold (
1601+ snapshot. to_string ( ) ,
1602+ |snapshot, ( pattern, replacement) | {
1603+ regex:: Regex :: new ( & pattern)
1604+ . expect ( "a filter to be a valid pattern" )
1605+ . replace_all ( & snapshot, replacement)
1606+ . into_owned ( )
1607+ } ,
1608+ )
1609+ } ;
1610+
1611+ assert_eq ! (
1612+ filtered(
1613+ r"C:\Users\runner\AppData\Local\Temp\.tmp42" ,
1614+ "/C:/Users/runner/AppData/Local/Temp/.tmp42" ,
1615+ r#"{"root": "C:\\Users\\runner\\AppData\\Local\\Temp\\.tmp42\\src"}"# ,
1616+ ) ,
1617+ r#"{"root": "<temp_dir>/src"}"#
1618+ ) ;
1619+
1620+ assert_eq ! (
1621+ filtered(
1622+ "/tmp/.tmp42" ,
1623+ "/tmp/.tmp42" ,
1624+ r#"{"root": "/tmp/.tmp42/src"}"# ,
1625+ ) ,
1626+ r#"{"root": "<temp_dir>/src"}"#
1627+ ) ;
1628+ }
0 commit comments