44
55namespace Test \TinyBlocks \Time ;
66
7+ use PHPUnit \Framework \Attributes \DataProvider ;
78use PHPUnit \Framework \TestCase ;
89use TinyBlocks \Time \DayOfWeek ;
910use TinyBlocks \Time \Instant ;
@@ -116,9 +117,13 @@ public function testDayOfWeekFromInstantOnSunday(): void
116117 public function testDayOfWeekWeekdayAndWeekendAreMutuallyExclusive (): void
117118 {
118119 /** @Then every day should be exactly one of weekday or weekend */
119- foreach (DayOfWeek::cases () as $ day ) {
120- self ::assertNotSame ($ day ->isWeekday (), $ day ->isWeekend ());
121- }
120+ self ::assertNotSame (DayOfWeek::Monday->isWeekday (), DayOfWeek::Monday->isWeekend ());
121+ self ::assertNotSame (DayOfWeek::Tuesday->isWeekday (), DayOfWeek::Tuesday->isWeekend ());
122+ self ::assertNotSame (DayOfWeek::Wednesday->isWeekday (), DayOfWeek::Wednesday->isWeekend ());
123+ self ::assertNotSame (DayOfWeek::Thursday->isWeekday (), DayOfWeek::Thursday->isWeekend ());
124+ self ::assertNotSame (DayOfWeek::Friday->isWeekday (), DayOfWeek::Friday->isWeekend ());
125+ self ::assertNotSame (DayOfWeek::Saturday->isWeekday (), DayOfWeek::Saturday->isWeekend ());
126+ self ::assertNotSame (DayOfWeek::Sunday->isWeekday (), DayOfWeek::Sunday->isWeekend ());
122127 }
123128
124129 public function testDayOfWeekExactlyFiveWeekdays (): void
@@ -142,4 +147,193 @@ public function testDayOfWeekExactlyTwoWeekendDays(): void
142147
143148 self ::assertCount (2 , $ weekends );
144149 }
150+
151+ #[DataProvider('sameDayDistanceDataProvider ' )]
152+ public function testDayOfWeekDistanceToSameDayReturnsZero (DayOfWeek $ day ): void
153+ {
154+ /** @Given the same day of the week */
155+ /** @Then the distance to itself should be zero */
156+ self ::assertSame (0 , $ day ->distanceTo (other: $ day ));
157+ }
158+
159+ #[DataProvider('forwardDistanceDataProvider ' )]
160+ public function testDayOfWeekDistanceToForward (DayOfWeek $ from , DayOfWeek $ to , int $ expectedDistance ): void
161+ {
162+ /** @Given a starting day and a target day */
163+ /** @Then the forward distance should match the expected value */
164+ self ::assertSame ($ expectedDistance , $ from ->distanceTo (other: $ to ));
165+ }
166+
167+ #[DataProvider('wrapAroundDistanceDataProvider ' )]
168+ public function testDayOfWeekDistanceToWrapsAroundWeek (DayOfWeek $ from , DayOfWeek $ to , int $ expectedDistance ): void
169+ {
170+ /** @Given a starting day that is after the target day in the week */
171+ /** @Then the distance should wrap forward through the end of the week */
172+ self ::assertSame ($ expectedDistance , $ from ->distanceTo (other: $ to ));
173+ }
174+
175+ #[DataProvider('asymmetricDistanceDataProvider ' )]
176+ public function testDayOfWeekDistanceToIsNotSymmetric (
177+ DayOfWeek $ from ,
178+ DayOfWeek $ to ,
179+ int $ expectedForward ,
180+ int $ expectedBackward
181+ ): void {
182+ /** @Given two distinct days of the week */
183+ /** @Then the forward and backward distances should differ */
184+ self ::assertSame ($ expectedForward , $ from ->distanceTo (other: $ to ));
185+ self ::assertSame ($ expectedBackward , $ to ->distanceTo (other: $ from ));
186+
187+ /** @And together they should complete a full week */
188+ self ::assertSame (7 , $ expectedForward + $ expectedBackward );
189+ }
190+
191+ #[DataProvider('allPairsDistanceDataProvider ' )]
192+ public function testDayOfWeekDistanceToNeverExceedsSix (DayOfWeek $ from , DayOfWeek $ to ): void
193+ {
194+ /** @Given any pair of days */
195+ $ distance = $ from ->distanceTo (other: $ to );
196+
197+ /** @Then the distance should be in the range [0, 6] */
198+ self ::assertGreaterThanOrEqual (0 , $ distance );
199+ self ::assertLessThanOrEqual (6 , $ distance );
200+ }
201+
202+ public static function sameDayDistanceDataProvider (): array
203+ {
204+ return [
205+ 'Monday to Monday ' => ['day ' => DayOfWeek::Monday],
206+ 'Tuesday to Tuesday ' => ['day ' => DayOfWeek::Tuesday],
207+ 'Wednesday to Wednesday ' => ['day ' => DayOfWeek::Wednesday],
208+ 'Thursday to Thursday ' => ['day ' => DayOfWeek::Thursday],
209+ 'Friday to Friday ' => ['day ' => DayOfWeek::Friday],
210+ 'Saturday to Saturday ' => ['day ' => DayOfWeek::Saturday],
211+ 'Sunday to Sunday ' => ['day ' => DayOfWeek::Sunday]
212+ ];
213+ }
214+
215+ public static function forwardDistanceDataProvider (): array
216+ {
217+ return [
218+ 'Monday to Tuesday ' => [
219+ 'from ' => DayOfWeek::Monday,
220+ 'to ' => DayOfWeek::Tuesday,
221+ 'expectedDistance ' => 1
222+ ],
223+ 'Monday to Wednesday ' => [
224+ 'from ' => DayOfWeek::Monday,
225+ 'to ' => DayOfWeek::Wednesday,
226+ 'expectedDistance ' => 2
227+ ],
228+ 'Monday to Thursday ' => [
229+ 'from ' => DayOfWeek::Monday,
230+ 'to ' => DayOfWeek::Thursday,
231+ 'expectedDistance ' => 3
232+ ],
233+ 'Monday to Friday ' => [
234+ 'from ' => DayOfWeek::Monday,
235+ 'to ' => DayOfWeek::Friday,
236+ 'expectedDistance ' => 4
237+ ],
238+ 'Monday to Saturday ' => [
239+ 'from ' => DayOfWeek::Monday,
240+ 'to ' => DayOfWeek::Saturday,
241+ 'expectedDistance ' => 5
242+ ],
243+ 'Monday to Sunday ' => [
244+ 'from ' => DayOfWeek::Monday,
245+ 'to ' => DayOfWeek::Sunday,
246+ 'expectedDistance ' => 6
247+ ],
248+ 'Tuesday to Thursday ' => [
249+ 'from ' => DayOfWeek::Tuesday,
250+ 'to ' => DayOfWeek::Thursday,
251+ 'expectedDistance ' => 2
252+ ],
253+ 'Wednesday to Saturday ' => [
254+ 'from ' => DayOfWeek::Wednesday,
255+ 'to ' => DayOfWeek::Saturday,
256+ 'expectedDistance ' => 3
257+ ]
258+ ];
259+ }
260+
261+ public static function wrapAroundDistanceDataProvider (): array
262+ {
263+ return [
264+ 'Friday to Monday ' => ['from ' => DayOfWeek::Friday, 'to ' => DayOfWeek::Monday, 'expectedDistance ' => 3 ],
265+ 'Saturday to Monday ' => [
266+ 'from ' => DayOfWeek::Saturday,
267+ 'to ' => DayOfWeek::Monday,
268+ 'expectedDistance ' => 2
269+ ],
270+ 'Sunday to Monday ' => ['from ' => DayOfWeek::Sunday, 'to ' => DayOfWeek::Monday, 'expectedDistance ' => 1 ],
271+ 'Wednesday to Monday ' => [
272+ 'from ' => DayOfWeek::Wednesday,
273+ 'to ' => DayOfWeek::Monday,
274+ 'expectedDistance ' => 5
275+ ],
276+ 'Saturday to Thursday ' => [
277+ 'from ' => DayOfWeek::Saturday,
278+ 'to ' => DayOfWeek::Thursday,
279+ 'expectedDistance ' => 5
280+ ],
281+ 'Thursday to Tuesday ' => [
282+ 'from ' => DayOfWeek::Thursday,
283+ 'to ' => DayOfWeek::Tuesday,
284+ 'expectedDistance ' => 5
285+ ],
286+ 'Sunday to Wednesday ' => [
287+ 'from ' => DayOfWeek::Sunday,
288+ 'to ' => DayOfWeek::Wednesday,
289+ 'expectedDistance ' => 3
290+ ]
291+ ];
292+ }
293+
294+ public static function asymmetricDistanceDataProvider (): array
295+ {
296+ return [
297+ 'Monday and Wednesday ' => [
298+ 'from ' => DayOfWeek::Monday,
299+ 'to ' => DayOfWeek::Wednesday,
300+ 'expectedForward ' => 2 ,
301+ 'expectedBackward ' => 5
302+ ],
303+ 'Tuesday and Friday ' => [
304+ 'from ' => DayOfWeek::Tuesday,
305+ 'to ' => DayOfWeek::Friday,
306+ 'expectedForward ' => 3 ,
307+ 'expectedBackward ' => 4
308+ ],
309+ 'Thursday and Sunday ' => [
310+ 'from ' => DayOfWeek::Thursday,
311+ 'to ' => DayOfWeek::Sunday,
312+ 'expectedForward ' => 3 ,
313+ 'expectedBackward ' => 4
314+ ],
315+ 'Saturday and Monday ' => [
316+ 'from ' => DayOfWeek::Saturday,
317+ 'to ' => DayOfWeek::Monday,
318+ 'expectedForward ' => 2 ,
319+ 'expectedBackward ' => 5
320+ ]
321+ ];
322+ }
323+
324+ public static function allPairsDistanceDataProvider (): array
325+ {
326+ $ pairs = [];
327+
328+ $ days = DayOfWeek::cases ();
329+
330+ foreach ($ days as $ from ) {
331+ foreach ($ days as $ to ) {
332+ $ label = sprintf ('%s to %s ' , $ from ->name , $ to ->name );
333+ $ pairs [$ label ] = ['from ' => $ from , 'to ' => $ to ];
334+ }
335+ }
336+
337+ return $ pairs ;
338+ }
145339}
0 commit comments