Skip to content

Commit c699a56

Browse files
Add comprehensive validation overloads for all CaptureIt methods
Co-authored-by: AkhmedovEhson <129420305+AkhmedovEhson@users.noreply.github.com>
1 parent 844ce81 commit c699a56

File tree

3 files changed

+685
-5
lines changed

3 files changed

+685
-5
lines changed

src/SnapshotIt.FluentValidation/CaptureValidationExtensions.cs

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,272 @@ public static Task<ValidationResult> ValidateAsync<T>(
115115
{
116116
return validator.ValidateAsync(input);
117117
}
118+
119+
/// <summary>
120+
/// Creates new collection of captures with provided size, or recreates it with validation support
121+
/// </summary>
122+
/// <typeparam name="T">The type of objects that will be stored in the collection</typeparam>
123+
/// <param name="snapshot">The snapshot instance</param>
124+
/// <param name="size">The size of the collection</param>
125+
/// <param name="validator">The FluentValidation validator for future validations</param>
126+
public static void CreateWithValidation<T>(
127+
this ISnapshot snapshot,
128+
uint size,
129+
IValidator<T> validator)
130+
{
131+
snapshot.Create<T>(size);
132+
}
133+
134+
/// <summary>
135+
/// Gets captured object from captures by index with validation
136+
/// </summary>
137+
/// <typeparam name="T">The type of object to get and validate</typeparam>
138+
/// <param name="snapshot">The snapshot instance</param>
139+
/// <param name="ind">The index of the object to retrieve</param>
140+
/// <param name="validator">The FluentValidation validator to use</param>
141+
/// <returns>The validated captured object</returns>
142+
/// <exception cref="ValidationException">Thrown when the retrieved object fails validation</exception>
143+
/// <exception cref="IndexOutOfRangeException">Thrown when index is out of range</exception>
144+
public static T GetWithValidation<T>(
145+
this ISnapshot snapshot,
146+
IValidator<T> validator,
147+
uint ind = 0)
148+
{
149+
var result = snapshot.Get<T>(ind);
150+
var validationResult = validator.Validate(result);
151+
152+
if (!validationResult.IsValid)
153+
{
154+
throw new ValidationException(validationResult.Errors);
155+
}
156+
157+
return result;
158+
}
159+
160+
/// <summary>
161+
/// Gets captured object from captures using expressions with validation
162+
/// </summary>
163+
/// <typeparam name="T">The type of object to get and validate</typeparam>
164+
/// <param name="snapshot">The snapshot instance</param>
165+
/// <param name="predicate">The predicate to find the object</param>
166+
/// <param name="validator">The FluentValidation validator to use</param>
167+
/// <returns>The validated captured object</returns>
168+
/// <exception cref="ValidationException">Thrown when the retrieved object fails validation</exception>
169+
/// <exception cref="NullReferenceException">Thrown when object is not found</exception>
170+
public static T GetWithValidation<T>(
171+
this ISnapshot snapshot,
172+
Func<T, bool> predicate,
173+
IValidator<T> validator)
174+
{
175+
var result = snapshot.Get<T>(predicate);
176+
var validationResult = validator.Validate(result);
177+
178+
if (!validationResult.IsValid)
179+
{
180+
throw new ValidationException(validationResult.Errors);
181+
}
182+
183+
return result;
184+
}
185+
186+
/// <summary>
187+
/// Gets captured object by index asynchronously with validation
188+
/// </summary>
189+
/// <typeparam name="T">The type of object to get and validate</typeparam>
190+
/// <param name="snapshot">The snapshot instance</param>
191+
/// <param name="ind">The index of the object to retrieve</param>
192+
/// <param name="validator">The FluentValidation validator to use</param>
193+
/// <returns>The validated captured object</returns>
194+
/// <exception cref="ValidationException">Thrown when the retrieved object fails validation</exception>
195+
public static async Task<T> GetWithValidationAsync<T>(
196+
this ISnapshot snapshot,
197+
int ind,
198+
IValidator<T> validator)
199+
{
200+
var result = await snapshot.GetAsync<T>(ind);
201+
var validationResult = await validator.ValidateAsync(result);
202+
203+
if (!validationResult.IsValid)
204+
{
205+
throw new ValidationException(validationResult.Errors);
206+
}
207+
208+
return result;
209+
}
210+
211+
/// <summary>
212+
/// Gets all captures asynchronously with validation for each object
213+
/// </summary>
214+
/// <typeparam name="T">The type of objects to get and validate</typeparam>
215+
/// <param name="snapshot">The snapshot instance</param>
216+
/// <param name="validator">The FluentValidation validator to use</param>
217+
/// <returns>Array of validated captured objects</returns>
218+
/// <exception cref="ValidationException">Thrown when any retrieved object fails validation</exception>
219+
public static async Task<T[]> GetAllWithValidationAsync<T>(
220+
this ISnapshot snapshot,
221+
IValidator<T> validator)
222+
{
223+
var results = await snapshot.GetAllAsync<T>();
224+
var validationTasks = results.Where(r => r != null).Select(result => validator.ValidateAsync(result));
225+
var validationResults = await Task.WhenAll(validationTasks);
226+
227+
var allErrors = validationResults
228+
.Where(result => !result.IsValid)
229+
.SelectMany(result => result.Errors)
230+
.ToList();
231+
232+
if (allErrors.Count > 0)
233+
{
234+
throw new ValidationException(allErrors);
235+
}
236+
237+
return results;
238+
}
239+
240+
/// <summary>
241+
/// Gets collection of captures as Span with validation for each object
242+
/// </summary>
243+
/// <typeparam name="T">The type of objects to get and validate</typeparam>
244+
/// <param name="snapshot">The snapshot instance</param>
245+
/// <param name="validator">The FluentValidation validator to use</param>
246+
/// <returns>Span of validated captured objects</returns>
247+
/// <exception cref="ValidationException">Thrown when any object fails validation</exception>
248+
public static Span<T> GetAsSpanWithValidation<T>(
249+
this ISnapshot snapshot,
250+
IValidator<T> validator)
251+
{
252+
var results = snapshot.GetAsSpan<T>();
253+
254+
foreach (var item in results)
255+
{
256+
if (item != null)
257+
{
258+
var validationResult = validator.Validate(item);
259+
if (!validationResult.IsValid)
260+
{
261+
throw new ValidationException(validationResult.Errors);
262+
}
263+
}
264+
}
265+
266+
return results;
267+
}
268+
269+
/// <summary>
270+
/// Gets collection of captures as ReadOnlySpan with validation for each object
271+
/// </summary>
272+
/// <typeparam name="T">The type of objects to get and validate</typeparam>
273+
/// <param name="snapshot">The snapshot instance</param>
274+
/// <param name="validator">The FluentValidation validator to use</param>
275+
/// <returns>ReadOnlySpan of validated captured objects</returns>
276+
/// <exception cref="ValidationException">Thrown when any object fails validation</exception>
277+
public static ReadOnlySpan<T> GetAsReadonlySpanWithValidation<T>(
278+
this ISnapshot snapshot,
279+
IValidator<T> validator)
280+
{
281+
var results = snapshot.GetAsReadonlySpan<T>();
282+
283+
foreach (var item in results)
284+
{
285+
if (item != null)
286+
{
287+
var validationResult = validator.Validate(item);
288+
if (!validationResult.IsValid)
289+
{
290+
throw new ValidationException(validationResult.Errors);
291+
}
292+
}
293+
}
294+
295+
return results;
296+
}
297+
298+
/// <summary>
299+
/// Gets collection of captures as IEnumerable with validation for each object
300+
/// </summary>
301+
/// <typeparam name="T">The type of objects to get and validate</typeparam>
302+
/// <param name="snapshot">The snapshot instance</param>
303+
/// <param name="validator">The FluentValidation validator to use</param>
304+
/// <returns>IEnumerable of validated captured objects</returns>
305+
/// <exception cref="ValidationException">Thrown when any object fails validation</exception>
306+
public static IEnumerable<T> GetAsEnumerableWithValidation<T>(
307+
this ISnapshot snapshot,
308+
IValidator<T> validator)
309+
{
310+
var results = snapshot.GetAsEnumerable<T>();
311+
312+
foreach (var item in results)
313+
{
314+
if (item != null)
315+
{
316+
var validationResult = validator.Validate(item);
317+
if (!validationResult.IsValid)
318+
{
319+
throw new ValidationException(validationResult.Errors);
320+
}
321+
}
322+
yield return item;
323+
}
324+
}
325+
326+
/// <summary>
327+
/// Gets collection of captures as List with validation for each object
328+
/// </summary>
329+
/// <typeparam name="T">The type of objects to get and validate</typeparam>
330+
/// <param name="snapshot">The snapshot instance</param>
331+
/// <param name="validator">The FluentValidation validator to use</param>
332+
/// <returns>List of validated captured objects</returns>
333+
/// <exception cref="ValidationException">Thrown when any object fails validation</exception>
334+
public static List<T> GetAsListWithValidation<T>(
335+
this ISnapshot snapshot,
336+
IValidator<T> validator)
337+
{
338+
var results = snapshot.GetAsList<T>();
339+
340+
foreach (var item in results)
341+
{
342+
if (item != null)
343+
{
344+
var validationResult = validator.Validate(item);
345+
if (!validationResult.IsValid)
346+
{
347+
throw new ValidationException(validationResult.Errors);
348+
}
349+
}
350+
}
351+
352+
return results;
353+
}
354+
355+
/// <summary>
356+
/// Gets collection of captures as List with size settings and validation for each object
357+
/// </summary>
358+
/// <typeparam name="T">The type of objects to get and validate</typeparam>
359+
/// <param name="snapshot">The snapshot instance</param>
360+
/// <param name="size">The size of the list</param>
361+
/// <param name="validator">The FluentValidation validator to use</param>
362+
/// <returns>List of validated captured objects</returns>
363+
/// <exception cref="ValidationException">Thrown when any object fails validation</exception>
364+
public static List<T> GetAsListWithValidation<T>(
365+
this ISnapshot snapshot,
366+
uint size,
367+
IValidator<T> validator)
368+
{
369+
var results = snapshot.GetAsList<T>(size);
370+
371+
foreach (var item in results)
372+
{
373+
if (item != null)
374+
{
375+
var validationResult = validator.Validate(item);
376+
if (!validationResult.IsValid)
377+
{
378+
throw new ValidationException(validationResult.Errors);
379+
}
380+
}
381+
}
382+
383+
return results;
384+
}
118385
}
119386
}

src/SnapshotIt.FluentValidation/README.md

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,42 @@
11
# SnapshotIt.FluentValidation
22

3-
FluentValidation integration for SnapshotIt library, providing validation capabilities for capturing objects to snapshots.
3+
FluentValidation integration for SnapshotIt library, providing comprehensive validation capabilities for capturing and retrieving objects to/from snapshots.
44

55
## Features
66

7-
- Validate objects before posting to snapshots using FluentValidation
8-
- Support for both synchronous and asynchronous validation
9-
- Validation of single objects and arrays
10-
- Comprehensive error handling with ValidationException
7+
- **Post Validation**: Validate objects before posting to snapshots using FluentValidation
8+
- **Get Validation**: Validate objects when retrieving from snapshots
9+
- **Collection Validation**: Validate collections and arrays of objects
10+
- **Comprehensive Coverage**: Validation overloads for all CaptureIt methods
11+
- **Support for both synchronous and asynchronous validation**
12+
- **Comprehensive error handling with ValidationException**
13+
14+
## Available Methods
15+
16+
### Post Methods (with validation before storing)
17+
- `PostWithValidation<T>(T input, IValidator<T> validator)` - Synchronous validation before posting
18+
- `PostWithValidationAsync<T>(T input, IValidator<T> validator)` - Asynchronous validation before posting
19+
- `PostWithValidationAsync<T>(T[] values, IValidator<T> validator)` - Asynchronous validation before posting arrays
20+
21+
### Get Methods (with validation when retrieving)
22+
- `GetWithValidation<T>(IValidator<T> validator, uint ind = 0)` - Get by index with validation
23+
- `GetWithValidation<T>(Func<T, bool> predicate, IValidator<T> validator)` - Get by predicate with validation
24+
- `GetWithValidationAsync<T>(int ind, IValidator<T> validator)` - Async get by index with validation
25+
- `GetAllWithValidationAsync<T>(IValidator<T> validator)` - Get all items with validation
26+
27+
### Collection Methods (with validation when retrieving)
28+
- `GetAsListWithValidation<T>(IValidator<T> validator)` - Get as List with validation
29+
- `GetAsListWithValidation<T>(uint size, IValidator<T> validator)` - Get as List with size and validation
30+
- `GetAsEnumerableWithValidation<T>(IValidator<T> validator)` - Get as IEnumerable with validation
31+
- `GetAsSpanWithValidation<T>(IValidator<T> validator)` - Get as Span with validation
32+
- `GetAsReadonlySpanWithValidation<T>(IValidator<T> validator)` - Get as ReadOnlySpan with validation
33+
34+
### Pure Validation Methods (validation without posting/retrieving)
35+
- `Validate<T>(T input, IValidator<T> validator)` - Synchronous validation only
36+
- `ValidateAsync<T>(T input, IValidator<T> validator)` - Asynchronous validation only
37+
38+
### Utility Methods
39+
- `CreateWithValidation<T>(uint size, IValidator<T> validator)` - Create collection with validation support
1140

1241
## Usage
1342

@@ -39,6 +68,19 @@ Snapshot.Out.PostWithValidation(product, validator);
3968
await Snapshot.Out.PostWithValidationAsync(product, validator);
4069
```
4170

71+
### Validation on Retrieval
72+
73+
```csharp
74+
// Get object with validation
75+
var validatedProduct = Snapshot.Out.GetWithValidation(validator, 0);
76+
77+
// Get collection with validation
78+
var validatedList = Snapshot.Out.GetAsListWithValidation(validator);
79+
80+
// Get all items with validation
81+
var validatedItems = await Snapshot.Out.GetAllWithValidationAsync(validator);
82+
```
83+
4284
### Validation Without Posting
4385

4486
```csharp

0 commit comments

Comments
 (0)