1+ using System ;
2+ using System . Globalization ;
3+ using System . Text . RegularExpressions ;
4+ using System . Threading ;
5+ using System . Threading . Tasks ;
6+ using CSF . Screenplay . Selenium . Elements ;
7+ using static CSF . Screenplay . Selenium . PerformableBuilder ;
8+
9+ namespace CSF . Screenplay . Selenium . Actions
10+ {
11+ /// <summary>
12+ /// A <see cref="IPerformable"/> which represents an actor entering a date value into an <c><input type="date"></c> element.
13+ /// </summary>
14+ /// <remarks>
15+ /// <para>
16+ /// Note that this task is culture-sensitive. Ensure that the date value is entered into the browser using the culture in which the browser is
17+ /// running.
18+ /// If no culture information is specified then this task defaults to the current culture: <see cref="CultureInfo.CurrentCulture"/>.
19+ /// However, this is not certain to be correct, particularly in remote/cloud configurations where the web browser is operating on different
20+ /// infrastructure to the computer which is executing the Screenplay performance. These two computers might be operating in different cultures.
21+ /// </para>
22+ /// <para>
23+ /// If the date specified to this task is <see langword="null"/> then this task will clear the date from the target.
24+ /// </para>
25+ /// </remarks>
26+ /// <example>
27+ /// <para>
28+ /// For example, a British English browser <c>en-GB</c> expects dates to be entered in the format ddMMyyyy.
29+ /// However, a US English browser <c>en-US</c> expects dates to be entered in the format MMddyyyy.
30+ /// </para>
31+ /// </example>
32+ public class EnterTheDate : IPerformable , ICanReport
33+ {
34+ const string nonNumericPattern = @"\D" ;
35+ static readonly Regex nonNumeric = new Regex ( nonNumericPattern , RegexOptions . Compiled | RegexOptions . IgnoreCase | RegexOptions . CultureInvariant ) ;
36+
37+ readonly DateTime ? date ;
38+ readonly ITarget target ;
39+ readonly CultureInfo culture ;
40+
41+ string GetShortDatePattern ( ) => culture . DateTimeFormat . ShortDatePattern ;
42+
43+ string FormatDate ( ) => date . HasValue ? date . Value . ToString ( GetShortDatePattern ( ) ) : null ;
44+
45+ /// <inheritdoc/>
46+ public ValueTask PerformAsAsync ( ICanPerform actor , CancellationToken cancellationToken = default )
47+ {
48+ if ( ! date . HasValue )
49+ return actor . PerformAsync ( ClearTheContentsOf ( target ) , cancellationToken ) ;
50+
51+ var dateText = nonNumeric . Replace ( FormatDate ( ) , string . Empty ) ;
52+ return actor . PerformAsync ( EnterTheText ( dateText ) . Into ( target ) , cancellationToken ) ;
53+ }
54+
55+ /// <inheritdoc/>
56+ public ReportFragment GetReportFragment ( Actor actor , IFormatsReportFragment formatter )
57+ {
58+ return date . HasValue
59+ ? formatter . Format ( "{Actor} enters the date {Date} into {Target}" , actor . Name , FormatDate ( ) , target )
60+ : formatter . Format ( "{Actor} clears the date from {Target}" , actor . Name , date , target ) ;
61+ }
62+
63+ /// <summary>
64+ /// Initializes a new instance of the <see cref="EnterTheDate"/> class with the specified date.
65+ /// </summary>
66+ /// <param name="date">The date to enter into the element.</param>
67+ /// <param name="target">The element into which to enter the data</param>
68+ /// <param name="culture">The culture for which to enter the date</param>
69+ public EnterTheDate ( DateTime ? date , ITarget target , CultureInfo culture = null )
70+ {
71+ this . date = date ;
72+ this . target = target ?? throw new ArgumentNullException ( nameof ( target ) ) ;
73+ this . culture = culture ?? CultureInfo . CurrentCulture ;
74+ }
75+ }
76+ }
0 commit comments