Skip to content

Commit 07383aa

Browse files
committed
more coverage
1 parent 0bd9331 commit 07383aa

5 files changed

Lines changed: 876 additions & 25 deletions

File tree

lib/src/everies/modifiers/every_override_wrapper.dart

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,42 +43,59 @@ class EveryOverrideWrapper<T extends Every> extends EveryModifierInvalidator<T>
4343
limit: limit,
4444
);
4545

46-
/// - Iterate over the next possible dates after [previous] with the
47-
/// [every] generator using startDate on the first iteration and next on
48-
/// every following.
49-
/// If the date generated for the iteration is already bigger than the
50-
/// given [date], super.startDate will be used.
51-
/// If the date is valid for the [invalidator], the [overrider] startDate
52-
/// will be used.
53-
/// If that date is then the exact given [date], it will be returned.
54-
/// If that date is before the given [date], a new iteration will be
55-
/// started.
5646
previous = every.startDate(previous);
57-
if (previous.isAfter(date)) {
58-
return super.startDate(date, limit: limit);
59-
} else if (previous.isAtSameMomentAs(date)) {
60-
if (invalidator.invalid(previous)) return date;
61-
}
47+
48+
// Check the initial date after startDate
49+
final initialCheck = _checkDateConditions(previous, date, limit);
50+
if (initialCheck != null) return initialCheck;
51+
52+
// Iterate over the next possible dates after [previous] with the
53+
// [every] generator using startDate on the first iteration and next on
54+
// every following.
55+
//
56+
// - If the date generated for the iteration is already bigger than the
57+
// given [date], super.startDate will be used.
58+
// - If the date is valid for the [invalidator], the [overrider] startDate
59+
// will be used.
60+
// - If that date is then the exact given [date], it will be returned.
61+
// - If that date is before the given [date], a new iteration will be
62+
// started.
6263
while (previous.isBefore(date)) {
6364
if (invalidator.valid(previous)) {
6465
previous = overrider.startDate(previous);
6566
}
66-
if (previous.isAfter(date)) {
67-
return super.startDate(date, limit: limit);
68-
} else if (previous.isAtSameMomentAs(date)) {
69-
if (invalidator.invalid(previous)) return date;
70-
}
67+
// Check conditions after potential override
68+
final checkResult = _checkDateConditions(previous, date, limit);
69+
if (checkResult != null) return checkResult;
70+
7171
previous = every.next(previous);
7272
}
73-
if (previous.isAfter(date)) {
74-
return super.startDate(date, limit: limit);
75-
} else if (previous.isAtSameMomentAs(date)) {
76-
if (invalidator.invalid(previous)) return date;
77-
}
73+
74+
// Final check after the loop
75+
final finalCheck = _checkDateConditions(previous, date, limit);
76+
if (finalCheck != null) return finalCheck;
7877
}
7978
return super.startDate(date, limit: limit);
8079
}
8180

81+
/// Helper method to check common date conditions and return appropriate
82+
/// result.
83+
///
84+
/// Returns null if no condition is met and processing should continue.
85+
DateTime? _checkDateConditions(
86+
DateTime previous,
87+
DateTime date,
88+
DateTime? limit,
89+
) {
90+
if (previous.isAfter(date)) {
91+
return super.startDate(date, limit: limit);
92+
}
93+
if (previous.isAtSameMomentAs(date) && invalidator.invalid(previous)) {
94+
return date;
95+
}
96+
return null;
97+
}
98+
8299
/// Generates the next instance of the given [date] considering the [every]
83100
/// base process.
84101
/// If the [date] is valid for the [invalidator], the [overrider] next will
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// ignore_for_file: prefer_const_constructors
2+
3+
import 'package:due_date/due_date.dart';
4+
import 'package:test/test.dart';
5+
6+
import '../../src/every_match.dart';
7+
8+
/// Test implementation of [EveryModifier] with [EveryModifierMixin].
9+
class _TestEveryModifier<T extends Every> extends EveryModifier<T>
10+
with EveryModifierMixin<T> {
11+
const _TestEveryModifier({
12+
required super.every,
13+
this.direction = DateDirection.next,
14+
});
15+
16+
/// The direction to use when processing dates.
17+
final DateDirection direction;
18+
19+
@override
20+
DateTime processDate(DateTime date, DateDirection actualDirection) {
21+
// For testing, we can modify the date based on direction
22+
// This is a simple test implementation
23+
switch (direction) {
24+
case DateDirection.start:
25+
case DateDirection.next:
26+
return date;
27+
case DateDirection.previous:
28+
// Subtract one day for testing purposes
29+
return date.subtract(Duration(days: 1));
30+
}
31+
}
32+
}
33+
34+
void main() {
35+
group('EveryModifierMixin:', () {
36+
final baseEvery = EveryWeekday(Weekday.monday);
37+
final modifier = _TestEveryModifier<EveryWeekday>(every: baseEvery);
38+
39+
group('Constructor', () {
40+
group('Unnamed', () {
41+
test('Valid basic case', () {
42+
expect(modifier, isNotNull);
43+
});
44+
test('Creates with correct every', () {
45+
expect(modifier.every, equals(baseEvery));
46+
});
47+
test('Default property values', () {
48+
expect(modifier.direction, equals(DateDirection.next));
49+
});
50+
});
51+
});
52+
53+
group('Base every integration', () {
54+
test('Works with EveryWeekday', () {
55+
final base = EveryWeekday(Weekday.monday);
56+
final modified = _TestEveryModifier<EveryWeekday>(every: base);
57+
expect(modified.every, equals(base));
58+
});
59+
60+
test('Works with EveryDueDayMonth', () {
61+
final base = EveryDueDayMonth(15);
62+
final modified = _TestEveryModifier<EveryDueDayMonth>(every: base);
63+
expect(modified.every, equals(base));
64+
});
65+
66+
test('Works with other Every implementations', () {
67+
final base = EveryDueWorkdayMonth(3);
68+
final modified = _TestEveryModifier<EveryDueWorkdayMonth>(every: base);
69+
expect(modified.every, equals(base));
70+
});
71+
});
72+
73+
group('Modifier behavior', () {
74+
test('Delegates to LimitedOrEveryHandler.startDate', () {
75+
// December 4, 2023 is Monday
76+
final inputDate = DateTime(2023, DateTime.december, 4);
77+
expect(modifier, startsAtSameDate.withInput(inputDate));
78+
});
79+
80+
test('Processes date with custom logic', () {
81+
final modifierWithPrevious = _TestEveryModifier<EveryWeekday>(
82+
every: baseEvery,
83+
direction: DateDirection.previous,
84+
);
85+
final inputDate = DateTime(2023, DateTime.december, 5);
86+
final expectedDate = DateTime(2023, DateTime.december, 10);
87+
expect(
88+
modifierWithPrevious,
89+
startsAt(expectedDate).withInput(inputDate),
90+
);
91+
});
92+
93+
test('Combination with different directions', () {
94+
final nextModifier = _TestEveryModifier<EveryWeekday>(
95+
every: baseEvery,
96+
);
97+
final previousModifier = _TestEveryModifier<EveryWeekday>(
98+
every: baseEvery,
99+
direction: DateDirection.previous,
100+
);
101+
102+
// December 4, 2023 is Monday
103+
final inputDate = DateTime(2023, DateTime.december, 4);
104+
105+
// Next modifier should return the same date
106+
expect(nextModifier, startsAtSameDate.withInput(inputDate));
107+
108+
// Previous modifier should return one day earlier
109+
final expectedPrevious = DateTime(2023, DateTime.december, 3);
110+
expect(
111+
previousModifier,
112+
startsAt(expectedPrevious).withInput(inputDate),
113+
);
114+
});
115+
});
116+
117+
group('Methods', () {
118+
group('startDate', () {
119+
test('Returns same date when input is valid', () {
120+
// December 4, 2023 is Monday
121+
final validDate = DateTime(2023, DateTime.december, 4);
122+
expect(modifier, startsAtSameDate.withInput(validDate));
123+
});
124+
125+
test('Returns next valid date when input is invalid', () {
126+
// December 5, 2023 is Tuesday
127+
final invalidDate = DateTime(2023, DateTime.december, 5);
128+
// December 11, 2023 is Monday
129+
final expectedDate = DateTime(2023, DateTime.december, 11);
130+
expect(modifier, startsAt(expectedDate).withInput(invalidDate));
131+
});
132+
133+
test('Always processes the result through processDate', () {
134+
final modifierWithPrevious = _TestEveryModifier<EveryWeekday>(
135+
every: baseEvery,
136+
direction: DateDirection.previous,
137+
);
138+
// December 4, 2023 is Monday (valid)
139+
final validDate = DateTime(2023, DateTime.december, 4);
140+
// Expected: December 3, 2023 (one day earlier due to processDate)
141+
final expectedDate = DateTime(2023, DateTime.december, 3);
142+
expect(
143+
modifierWithPrevious,
144+
startsAt(expectedDate).withInput(validDate),
145+
);
146+
});
147+
});
148+
149+
group('next', () {
150+
test('Always generates date after input', () {
151+
// December 4, 2023 is Monday
152+
final date = DateTime(2023, DateTime.december, 4);
153+
expect(modifier, nextIsAfter.withInput(date));
154+
});
155+
156+
test('Returns next occurrence with processDate applied', () {
157+
// December 4, 2023 is Monday
158+
final date = DateTime(2023, DateTime.december, 4);
159+
// December 11, 2023 is Monday (next occurrence)
160+
final expectedDate = DateTime(2023, DateTime.december, 11);
161+
expect(modifier, hasNext(expectedDate).withInput(date));
162+
});
163+
164+
test('Applies processDate to the result', () {
165+
final modifierWithPrevious = _TestEveryModifier<EveryWeekday>(
166+
every: baseEvery,
167+
direction: DateDirection.previous,
168+
);
169+
// December 4, 2023 is Monday
170+
final date = DateTime(2023, DateTime.december, 4);
171+
// December 10, 2023 (December 11 minus one day due to processDate)
172+
final expectedDate = DateTime(2023, DateTime.december, 10);
173+
expect(modifierWithPrevious, hasNext(expectedDate).withInput(date));
174+
});
175+
});
176+
177+
group('previous', () {
178+
test('Always generates date before input', () {
179+
// December 11, 2023 is Monday
180+
final date = DateTime(2023, DateTime.december, 11);
181+
expect(modifier, previousIsBefore.withInput(date));
182+
});
183+
184+
test('Returns previous occurrence with processDate applied', () {
185+
// December 11, 2023 is Monday
186+
final date = DateTime(2023, DateTime.december, 11);
187+
// December 4, 2023 is Monday (previous occurrence)
188+
final expectedDate = DateTime(2023, DateTime.december, 4);
189+
expect(modifier, hasPrevious(expectedDate).withInput(date));
190+
});
191+
192+
test('Applies processDate to the result', () {
193+
final modifierWithPrevious = _TestEveryModifier<EveryWeekday>(
194+
every: baseEvery,
195+
direction: DateDirection.previous,
196+
);
197+
// December 11, 2023 is Monday
198+
final date = DateTime(2023, DateTime.december, 11);
199+
// December 3, 2023 (December 4 minus one day due to processDate)
200+
final expectedDate = DateTime(2023, DateTime.december, 3);
201+
expect(
202+
modifierWithPrevious,
203+
hasPrevious(expectedDate).withInput(date),
204+
);
205+
});
206+
});
207+
});
208+
209+
group('Edge Cases', () {
210+
test('Works with LimitedEvery base', () {
211+
final limitedBase = EverySkipInvalidModifier(
212+
every: baseEvery,
213+
invalidator: DateValidatorWeekdayCountInMonth(
214+
week: Week.first,
215+
day: Weekday.monday,
216+
),
217+
);
218+
final modifier = _TestEveryModifier<
219+
EverySkipInvalidModifier<EveryWeekday, DateValidator>>(
220+
every: limitedBase,
221+
);
222+
expect(modifier.every, equals(limitedBase));
223+
});
224+
225+
test('Handles processDate correctly with different directions', () {
226+
// Test that processDate is called with correct direction parameter
227+
final modifier = _TestEveryModifier<EveryWeekday>(
228+
every: baseEvery,
229+
direction: DateDirection.start,
230+
);
231+
// December 4, 2023 is Monday
232+
final date = DateTime(2023, DateTime.december, 4);
233+
expect(modifier, startsAtSameDate.withInput(date));
234+
});
235+
236+
test('Works with edge dates', () {
237+
// Test with year boundary
238+
final date = DateTime(2023, DateTime.december, 31);
239+
// Should work without throwing
240+
expect(() => modifier.startDate(date), returnsNormally);
241+
expect(() => modifier.next(date), returnsNormally);
242+
expect(() => modifier.previous(date), returnsNormally);
243+
});
244+
});
245+
});
246+
}

0 commit comments

Comments
 (0)