yanweiyuan3
2023-08-09 588bc7829387dfc761cc25f06f77d4c81818bd10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
 * @file        S&OP DateTimeSelector component to wrap common methods the team encounter during development
 * @description DateTimeSelector class extending Abstraction API's QDateTimeSelector.
 * All S&OP page objects inherit from our own class (inheriting e2e/Abstraction API), but we can propose common methods to them.
 * @author      Clarence (clarence.chan@3ds.com)
 * @copyright   Dassault Systèmes
 */
import { QDateTimeSelector } from '../e2elib/lib/api/pageobjects/qdatetimeselector.component';
import { ElementFinder } from '../e2elib/node_modules/protractor/built';
import { UIActionSOP } from './objectsop';
import { QUtils } from '../e2elib/lib/src/main/qutils.class';
import { QDateTimeOmitOptions } from '../e2elib/lib/api/types';
 
export class DateTimeSelectorSOP extends QDateTimeSelector implements UIActionSOP {
  private readonly _separator = '-';
  private readonly _omit: QDateTimeOmitOptions; // Hide the datetime portions that are not present for this field in web app
 
  public constructor(componentPath: string, omit: QDateTimeOmitOptions = {hour: true, minute: true, second: true}, isCustomPath?: boolean, elementObj?: ElementFinder) {
    super(componentPath, isCustomPath, elementObj);
    this._omit = omit;
  }
 
  public async clickActionLinkText(expectedActionLinkText: string): Promise<void> {
    const isActionLinkMatch = await this.hasActionLink() && await this.getActionLinkText() === expectedActionLinkText;
    expect(isActionLinkMatch).toBe(true, `Unable to proceed click action link for datetimeselector ${await this.getComponentLabel()}. Expecting action link text '${expectedActionLinkText}'.`);
 
    if (isActionLinkMatch) {
      await this.clickActionLink();
    }
  }
 
  public getDateFromString(value: string): Date {
    let date = new Date(1899, 11, 31, 0, 0, 0, 0); // This is default Quintiq value if datetime component only shows time
    let dateOnly = '';
    if (!this._omit.date) {
      const dateMatchArr = value.match(new RegExp('(\\d{1,2}-\\w{3}-\\d{4})', 'g'));
      if (dateMatchArr !== null) {
        dateOnly = dateMatchArr[0];
 
        const tokens = dateOnly.split(this._separator);
        date = new Date(`${tokens[1]} ${tokens[0]}, ${tokens[2]}`); // Format "Jan 1, 2020"
      }
    }
 
    const timeMatchArr = value.match(new RegExp('(\\d{2}:\\d{2}(:\\d{2})?)', 'g'));
    let timeOnly = '';
    if (timeMatchArr !== null) {
      timeOnly = timeMatchArr[0];
    }
 
    const timeTokens = timeOnly.split(':');
    if (!this._omit.hour) {
      const hourToken = timeTokens.shift();
      date.setHours(Number(hourToken));
    }
 
    if (!this._omit.minute) {
      const minToken = timeTokens.shift();
      date.setMinutes(Number(minToken));
    }
 
    if (!this._omit.second) {
      const secToken = timeTokens.shift();
      date.setSeconds(Number(secToken));
    }
 
    return date;
  }
 
  /**
   * Returns the string representation of the datetimeselector for the visible datetime portions only.
   * Thus not able use Abstraction API getDate/getDateTime methods as that returns Date.
   * Example: If datetimeselector showing only hours and minutes, we will return only what is visible as string value.
   *
   * @returns Full datetime value string that potential to be returned is "1-Jan-2020 14:30:20" (down to the seconds). Or just either the date or time portion as string.
   */
  public async getValueString(): Promise<string> {
    let dateStr = '';
    // If field showing date, format the date str with format "1-Jan-2020"
    if (!this._omit.date) {
      const day = (await this.getDay()).padStart(2, '0');
      const month = await this.getMonth();
      const year = await this.getYear();
      dateStr = `${day}${this._separator}${month}${this._separator}${year}`;
    }
 
    // If field showing any time portions, format the string value
    let timeStr = '';
    if (!this._omit.hour) {
      timeStr = timeStr + (await this.getHour()).padStart(2, '0');
    }
 
    if (!this._omit.minute) {
      if (timeStr !== '') {
        timeStr = `${timeStr  }:`;
      }
 
      timeStr = timeStr + (await this.getMinute()).padStart(2, '0');
    }
 
    if (!this._omit.second) {
      if (timeStr !== '') {
        timeStr = `${timeStr  }:`;
      }
 
      timeStr = timeStr + (await this.getSecond()).padStart(2, '0');
    }
 
    // Format the final string to return (either both date+time available, or only one of them).
    const spaceBetweenDateAndTime = (dateStr !== '' && timeStr !== '') ? ' ' : ''; // If both date+time available, put a space between them.
    const finalDateStr = `${dateStr}${spaceBetweenDateAndTime}${timeStr}`;
 
    return finalDateStr;
  }
 
  public async setValue(value: string): Promise<void> {
    // Convert user input string into Date object
    const dateTime: Date = this.getDateFromString(value);
 
    // Send the Date object into Abstraction API method which knows how to fill in our datetimeselector in web app
    await this.setDateTime(dateTime, this._omit);
  }
 
  public async toggleValue(): Promise<void> {
    const previousDateValue = await this.getValueString();
    const previousDate = this.getDateFromString(previousDateValue);
    previousDate.setDate(previousDate.getDate() + 1);
    previousDate.setHours(previousDate.getHours() + 1);
    previousDate.setMinutes (previousDate.getMinutes() + 1);
    previousDate.setSeconds(previousDate.getSeconds() + 1);
    await this.setDateTime(previousDate, this._omit);
  }
 
  public async verifyBatchEditEnabled(expectedEnable: boolean, expectedActionLinkText: string): Promise<void> {
    const isBatchEditEnableDisableOK = await this.hasActionLink() &&
                                       await this.getActionLinkText() === expectedActionLinkText &&
                                       !await this.isDisabled() === expectedEnable;
    expect(isBatchEditEnableDisableOK).toBe(true, `Verify datetimeselector ${await this.getComponentLabel()} supports batch edit (expected enable = ${expectedEnable} & action link = ${expectedActionLinkText}).`);
  }
 
  public async verifyHasMaskError(expectedValue: boolean): Promise<void> {
    // Implements UIActionSOP
    await this.hasMaskError(expectedValue);
  }
 
  public async verifyTooltip(expectedValue: string): Promise<void> {
    const tooltip = await QUtils.getTooltip(this.tooltipLabelElement, true, true, true);
    expect(tooltip).toBe(expectedValue, `Hover ${await this.getComponentLabel()} to verify tooltip.`);
  }
 
  public async verifyEnabled(expectedEnable: boolean): Promise<void> {
    expect(!await this.isDisabled()).toBe(expectedEnable, `Verify enable state for datetimeselector ${await this.getComponentLabel()}.`);
  }
 
  public async verifyValue(expectedValue: string): Promise<void> {
    const actualDate = await this.getDateTime(); // Get Date object from the datetimeselector component in web app
    const expectedDate = this.getDateFromString(expectedValue); // Get Date object from user expected string
 
    // Cannot direct compare Dates, use valueOf which returns the primitive underlying value such as 823230245000
    const datesEqual = actualDate.valueOf() === expectedDate.valueOf();
    expect(datesEqual).toBe(true, `Verify value fail for datetimeselector ${await this.getComponentLabel()}. Expected = ${expectedValue}, actual = ${await this.getValueString()}.`);
  }
 
  public async verifyVisible(expectedValue: string): Promise<void> {
    expect(await this.isVisible()).toBe(expectedValue.toLowerCase() === 'true', `Verify visible state for datetimeselector ${await this.getComponentLabel()}.`);
  }
 }