66import json
77import os
88from collections import defaultdict
9- from distutils .util import strtobool
109from pathlib import Path
1110from typing import TYPE_CHECKING , Any , Callable , Generic , cast
1211
1312import pytest
13+ from str_to_bool import str_to_bool
1414
1515from redux .basic_types import FinishEvent , State
1616
2323class StoreSnapshot (Generic [State ]):
2424 """Context object for tests taking snapshots of the store."""
2525
26- def __init__ (
26+ def __init__ ( # noqa: PLR0913
2727 self : StoreSnapshot ,
2828 * ,
2929 test_id : str ,
3030 path : Path ,
3131 override : bool ,
3232 store : Store ,
33+ prefix : str | None ,
3334 ) -> None :
3435 """Create a new store snapshot context."""
36+ self .prefix = prefix
3537 self ._is_failed = False
3638 self ._is_closed = False
3739 self .override = override
@@ -41,8 +43,13 @@ def __init__(
4143 path .parent / 'results' / file / test_id .split ('::' )[- 1 ][5 :],
4244 )
4345 if self .results_dir .exists ():
46+ prefix_element = ''
47+ if self .prefix :
48+ prefix_element = self .prefix + '-'
4449 for file in self .results_dir .glob (
45- 'store-*.jsonc' if override else 'store-*.mismatch.jsonc' ,
50+ f'store-{ prefix_element } *.jsonc'
51+ if override
52+ else f'store-{ prefix_element } *.mismatch.jsonc' ,
4653 ):
4754 file .unlink () # pragma: no cover
4855 self .results_dir .mkdir (parents = True , exist_ok = True )
@@ -69,9 +76,15 @@ def json_snapshot(
6976
7077 def get_filename (self : StoreSnapshot [State ], title : str | None ) -> str :
7178 """Get the filename for the snapshot."""
79+ title_element = ''
7280 if title :
73- return f"""store-{ title } -{ self .test_counter [title ]:03d} """
74- return f"""store-{ self .test_counter [title ]:03d} """
81+ title_element = title + '-'
82+ prefix_element = ''
83+ if self .prefix :
84+ prefix_element = self .prefix + '-'
85+ return (
86+ f"""store-{ prefix_element } { title_element } { self .test_counter [title ]:03d} """
87+ )
7588
7689 def take (
7790 self : StoreSnapshot [State ],
@@ -101,10 +114,10 @@ def take(
101114 if json_path .exists ():
102115 old_snapshot = json_path .read_text ().split ('\n ' , 1 )[1 ][:- 1 ]
103116 else :
104- old_snapshot = None
105- if old_snapshot != new_snapshot :
117+ old_snapshot = None # pragma: no cover
118+ if old_snapshot != new_snapshot : # pragma: no cover
106119 self ._is_failed = True
107- mismatch_path .write_text ( # pragma: no cover
120+ mismatch_path .write_text (
108121 f'// MISMATCH: { filename } \n { new_snapshot } \n ' ,
109122 )
110123 assert new_snapshot == old_snapshot , f'Store snapshot mismatch - { filename } '
@@ -123,7 +136,7 @@ def _(state: object | None) -> None:
123136 def close (self : StoreSnapshot [State ]) -> None :
124137 """Close the snapshot context."""
125138 self ._is_closed = True
126- if self ._is_failed :
139+ if self ._is_failed : # pragma: no cover
127140 return
128141 for title in self .test_counter :
129142 filename = self .get_filename (title )
@@ -133,14 +146,24 @@ def close(self: StoreSnapshot[State]) -> None:
133146
134147
135148@pytest .fixture ()
136- def store_snapshot (request : SubRequest , store : Store ) -> StoreSnapshot :
149+ def snapshot_prefix () -> str | None :
150+ """Return the prefix for the snapshots."""
151+ return None
152+
153+
154+ @pytest .fixture ()
155+ def store_snapshot (
156+ request : SubRequest ,
157+ store : Store ,
158+ snapshot_prefix : str | None ,
159+ ) -> StoreSnapshot :
137160 """Take a snapshot of the current state of the store."""
138161 override = (
139162 request .config .getoption (
140163 '--override-store-snapshots' ,
141164 default = cast (
142165 Any ,
143- strtobool (os .environ .get ('REDUX_TEST_OVERRIDE_SNAPSHOTS' , 'false' ))
166+ str_to_bool (os .environ .get ('REDUX_TEST_OVERRIDE_SNAPSHOTS' , 'false' ))
144167 == 1 ,
145168 ),
146169 )
@@ -151,4 +174,5 @@ def store_snapshot(request: SubRequest, store: Store) -> StoreSnapshot:
151174 path = request .node .path ,
152175 override = override ,
153176 store = store ,
177+ prefix = snapshot_prefix ,
154178 )
0 commit comments