@zeesoft/i18n-verify 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,142 @@
1
- "use strict";const v=require("fs"),Z=require("path"),ye=require("console-table-printer"),he=require("chrome-remote-interface"),Q=require("globalize"),X=require("cldr-data"),b=require("chrono-node"),E=require("luxon"),Ie=require("@isdk/detect-text-language"),J=require("jimp"),z={NIGHT_WATCH:"nightwatch",WEB_DRIVER_IO:"webio",CYPRESS:"cypress",SELENIUMJS:"seleniumJS"},d={GRB_GREEN:"rgb(0, 154, 61)",GRB_RED:"rgb(255, 0, 0)",GRB_YELLOW:"rgb(255, 255, 0)",GRB_BLUE:"rgb(0, 0, 255)",ANSI_GREEN:"\x1B[32m",ANSI_RED:"\x1B[31m",ANSI_YELLOW:"\x1B[33m"},r={STRING_LOCALIZED:"STRING_LOCALIZED",STRING_PARTIALLY_LOCALIZED:"STRING_PARTIALLY_LOCALIZED",NUMBER_LOCALIZED:"NUMBER_LOCALIZED",CURRENCY_LOCALIZED:"CURRENCY_LOCALIZED",PERCENTAGE_LOCALIZED:"PERCENTAGE_LOCALIZED",DATE_LOCALIZED:"DATE_LOCALIZED",TIME_LOCALIZED:"TIME_LOCALIZED",DATE_TIME_LOCALIZED:"DATE_TIME_LOCALIZED",STRING_NOT_LOCALIZED:"STRING_NOT_LOCALIZED",NUMBER_NOT_LOCALIZED:"NUMBER_NOT_LOCALIZED",CURRENCY_NOT_LOCALIZED:"CURRENCY_NOT_LOCALIZED",PERCENTAGE_NOT_LOCALIZED:"PERCENTAGE_NOT_LOCALIZED",DATE_NOT_LOCALIZED:"DATE_NOT_LOCALIZED",TIME_NOT_LOCALIZED:"TIME_NOT_LOCALIZED",DATE_TIME_NOT_LOCALIZED:"DATE_TIME_NOT_LOCALIZED",TRUNCATION_ISSUE:"TRUNCATION_ISSUE",OVERLAPPING_ISSUE:"OVERLAPPING_ISSUE",ENCODING_ISSUE:"ENCODING_ISSUE",DNT:"DNT",IGNORE:"IGNORE",UNTRANSLATED:"UNTRANSLATED",AUTO_IGNORE:"AUTO_IGNORE",USER_INPUT:"USER_INPUT",REVIEWED:"REVIEWED"},R={[r.STRING_LOCALIZED]:0,[r.STRING_NOT_LOCALIZED]:0,[r.STRING_PARTIALLY_LOCALIZED]:0,[r.NUMBER_LOCALIZED]:0,[r.NUMBER_NOT_LOCALIZED]:0,[r.DATE_LOCALIZED]:0,[r.DATE_NOT_LOCALIZED]:0,[r.DATE_TIME_LOCALIZED]:0,[r.DATE_TIME_NOT_LOCALIZED]:0,[r.TIME_LOCALIZED]:0,[r.TIME_NOT_LOCALIZED]:0,[r.CURRENCY_LOCALIZED]:0,[r.CURRENCY_NOT_LOCALIZED]:0,[r.PERCENTAGE_LOCALIZED]:0,[r.PERCENTAGE_NOT_LOCALIZED]:0,[r.TRUNCATION_ISSUE]:0,[r.OVERLAPPING_ISSUE]:0,[r.ENCODING_ISSUE]:0,[r.DNT]:0,[r.IGNORE]:0,[r.UNTRANSLATED]:0,[r.AUTO_IGNORE]:0,[r.USER_INPUT]:0,[r.REVIEWED]:0},de={[r.STRING_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.STRING_PARTIALLY_LOCALIZED]:[d.GRB_YELLOW,d.ANSI_YELLOW],[r.NUMBER_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.DATE_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.TIME_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.DATE_TIME_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.CURRENCY_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.PERCENTAGE_LOCALIZED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.STRING_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.DATE_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.DATE_TIME_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.TIME_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.NUMBER_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.CURRENCY_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.PERCENTAGE_NOT_LOCALIZED]:[d.GRB_RED,d.ANSI_RED],[r.TRUNCATION_ISSUE]:[d.GRB_RED,d.ANSI_RED],[r.OVERLAPPING_ISSUE]:[d.GRB_RED,d.ANSI_RED],[r.ENCODING_ISSUE]:[d.GRB_RED,d.ANSI_RED],[r.DNT]:[d.GRB_GREEN,d.ANSI_GREEN],[r.IGNORE]:[d.GRB_GREEN,d.ANSI_GREEN],[r.UNTRANSLATED]:[d.GRB_GREEN,d.ANSI_GREEN],[r.AUTO_IGNORE]:[d.GRB_GREEN,d.ANSI_GREEN],[r.USER_INPUT]:[d.GRB_GREEN,d.ANSI_GREEN],[r.REVIEWED]:[d.GRB_GREEN,d.ANSI_GREEN]},be={[r.STRING_LOCALIZED]:"string is localized",[r.STRING_PARTIALLY_LOCALIZED]:"string is partially localized",[r.NUMBER_LOCALIZED]:"number is localized",[r.DATE_LOCALIZED]:"date is localized",[r.DATE_TIME_LOCALIZED]:"dateTime is localized",[r.TIME_LOCALIZED]:"time is localized",[r.CURRENCY_LOCALIZED]:"currency is localized",[r.PERCENTAGE_LOCALIZED]:"percentage is localized",[r.STRING_NOT_LOCALIZED]:"string is not localized",[r.DATE_NOT_LOCALIZED]:"date is not localized",[r.DATE_TIME_NOT_LOCALIZED]:"dateTime is not localized",[r.TIME_NOT_LOCALIZED]:"time is not localized",[r.NUMBER_NOT_LOCALIZED]:"number is not localized",[r.CURRENCY_NOT_LOCALIZED]:"currency is not localized",[r.PERCENTAGE_NOT_LOCALIZED]:"percentage is not localized",[r.TRUNCATION_ISSUE]:"truncation issue detected",[r.OVERLAPPING_ISSUE]:"overlapping issue detected",[r.ENCODING_ISSUE]:"encoding issue detected",[r.DNT]:"do not translate",[r.IGNORE]:"ignored this issue",[r.UNTRANSLATED]:"string is untranslated",[r.AUTO_IGNORE]:"automatically ignored issue",[r.USER_INPUT]:"user input field",[r.REVIEWED]:"string has been reviewed"},ue={EMAIL:/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}\b/gi,URL:/^(https?:\/\/)?(www\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?$/},Se="zqa_",De=[".txt",".json"],K=`//*[not(self::script or self::style or self::noscript)]
1
+ import fs, { existsSync, statSync, readFileSync, mkdirSync, writeFileSync, readdirSync, appendFileSync, copyFileSync } from "fs";
2
+ import path, { join, dirname, extname } from "path";
3
+ import { Table } from "console-table-printer";
4
+ import CDP from "chrome-remote-interface";
5
+ import Globalize from "globalize";
6
+ import CldrData from "cldr-data";
7
+ import { en, uk, nl, ru, zh, ja, pt, fr, es, de } from "chrono-node";
8
+ import { DateTime } from "luxon";
9
+ import { detectTextLangEx } from "@isdk/detect-text-language";
10
+ import Jimp from "jimp";
11
+ const SYSTEM_TYPES = {
12
+ NIGHT_WATCH: "nightwatch",
13
+ WEB_DRIVER_IO: "webio",
14
+ CYPRESS: "cypress",
15
+ SELENIUMJS: "seleniumJS"
16
+ };
17
+ const COLOR = {
18
+ GRB_GREEN: "rgb(0, 154, 61)",
19
+ GRB_RED: "rgb(255, 0, 0)",
20
+ GRB_YELLOW: "rgb(255, 255, 0)",
21
+ GRB_BLUE: "rgb(0, 0, 255)",
22
+ ANSI_GREEN: "\x1B[32m",
23
+ ANSI_RED: "\x1B[31m",
24
+ ANSI_YELLOW: "\x1B[33m"
25
+ };
26
+ const I18N_STATUS = {
27
+ STRING_LOCALIZED: "STRING_LOCALIZED",
28
+ STRING_PARTIALLY_LOCALIZED: "STRING_PARTIALLY_LOCALIZED",
29
+ NUMBER_LOCALIZED: "NUMBER_LOCALIZED",
30
+ CURRENCY_LOCALIZED: "CURRENCY_LOCALIZED",
31
+ PERCENTAGE_LOCALIZED: "PERCENTAGE_LOCALIZED",
32
+ DATE_LOCALIZED: "DATE_LOCALIZED",
33
+ TIME_LOCALIZED: "TIME_LOCALIZED",
34
+ DATE_TIME_LOCALIZED: "DATE_TIME_LOCALIZED",
35
+ STRING_NOT_LOCALIZED: "STRING_NOT_LOCALIZED",
36
+ NUMBER_NOT_LOCALIZED: "NUMBER_NOT_LOCALIZED",
37
+ CURRENCY_NOT_LOCALIZED: "CURRENCY_NOT_LOCALIZED",
38
+ PERCENTAGE_NOT_LOCALIZED: "PERCENTAGE_NOT_LOCALIZED",
39
+ DATE_NOT_LOCALIZED: "DATE_NOT_LOCALIZED",
40
+ TIME_NOT_LOCALIZED: "TIME_NOT_LOCALIZED",
41
+ DATE_TIME_NOT_LOCALIZED: "DATE_TIME_NOT_LOCALIZED",
42
+ TRUNCATION_ISSUE: "TRUNCATION_ISSUE",
43
+ OVERLAPPING_ISSUE: "OVERLAPPING_ISSUE",
44
+ ENCODING_ISSUE: "ENCODING_ISSUE",
45
+ DNT: "DNT",
46
+ IGNORE: "IGNORE",
47
+ UNTRANSLATED: "UNTRANSLATED",
48
+ AUTO_IGNORE: "AUTO_IGNORE",
49
+ USER_INPUT: "USER_INPUT",
50
+ REVIEWED: "REVIEWED"
51
+ };
52
+ const REPORT_COUNTS = {
53
+ [I18N_STATUS.STRING_LOCALIZED]: 0,
54
+ [I18N_STATUS.STRING_NOT_LOCALIZED]: 0,
55
+ [I18N_STATUS.STRING_PARTIALLY_LOCALIZED]: 0,
56
+ [I18N_STATUS.NUMBER_LOCALIZED]: 0,
57
+ [I18N_STATUS.NUMBER_NOT_LOCALIZED]: 0,
58
+ [I18N_STATUS.DATE_LOCALIZED]: 0,
59
+ [I18N_STATUS.DATE_NOT_LOCALIZED]: 0,
60
+ [I18N_STATUS.DATE_TIME_LOCALIZED]: 0,
61
+ [I18N_STATUS.DATE_TIME_NOT_LOCALIZED]: 0,
62
+ [I18N_STATUS.TIME_LOCALIZED]: 0,
63
+ [I18N_STATUS.TIME_NOT_LOCALIZED]: 0,
64
+ [I18N_STATUS.CURRENCY_LOCALIZED]: 0,
65
+ [I18N_STATUS.CURRENCY_NOT_LOCALIZED]: 0,
66
+ [I18N_STATUS.PERCENTAGE_LOCALIZED]: 0,
67
+ [I18N_STATUS.PERCENTAGE_NOT_LOCALIZED]: 0,
68
+ [I18N_STATUS.TRUNCATION_ISSUE]: 0,
69
+ [I18N_STATUS.OVERLAPPING_ISSUE]: 0,
70
+ [I18N_STATUS.ENCODING_ISSUE]: 0,
71
+ [I18N_STATUS.DNT]: 0,
72
+ [I18N_STATUS.IGNORE]: 0,
73
+ [I18N_STATUS.UNTRANSLATED]: 0,
74
+ [I18N_STATUS.AUTO_IGNORE]: 0,
75
+ [I18N_STATUS.USER_INPUT]: 0,
76
+ [I18N_STATUS.REVIEWED]: 0
77
+ };
78
+ const STATUS_COLOR = {
79
+ [I18N_STATUS.STRING_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
80
+ [I18N_STATUS.STRING_PARTIALLY_LOCALIZED]: [
81
+ COLOR.GRB_YELLOW,
82
+ COLOR.ANSI_YELLOW
83
+ ],
84
+ [I18N_STATUS.NUMBER_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
85
+ [I18N_STATUS.DATE_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
86
+ [I18N_STATUS.TIME_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
87
+ [I18N_STATUS.DATE_TIME_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
88
+ [I18N_STATUS.CURRENCY_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
89
+ [I18N_STATUS.PERCENTAGE_LOCALIZED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
90
+ [I18N_STATUS.STRING_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
91
+ [I18N_STATUS.DATE_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
92
+ [I18N_STATUS.DATE_TIME_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
93
+ [I18N_STATUS.TIME_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
94
+ [I18N_STATUS.NUMBER_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
95
+ [I18N_STATUS.CURRENCY_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
96
+ [I18N_STATUS.PERCENTAGE_NOT_LOCALIZED]: [COLOR.GRB_RED, COLOR.ANSI_RED],
97
+ [I18N_STATUS.TRUNCATION_ISSUE]: [COLOR.GRB_RED, COLOR.ANSI_RED],
98
+ [I18N_STATUS.OVERLAPPING_ISSUE]: [COLOR.GRB_RED, COLOR.ANSI_RED],
99
+ [I18N_STATUS.ENCODING_ISSUE]: [COLOR.GRB_RED, COLOR.ANSI_RED],
100
+ [I18N_STATUS.DNT]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
101
+ [I18N_STATUS.IGNORE]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
102
+ [I18N_STATUS.UNTRANSLATED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
103
+ [I18N_STATUS.AUTO_IGNORE]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
104
+ [I18N_STATUS.USER_INPUT]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN],
105
+ [I18N_STATUS.REVIEWED]: [COLOR.GRB_GREEN, COLOR.ANSI_GREEN]
106
+ };
107
+ const STATUS_INFO = {
108
+ [I18N_STATUS.STRING_LOCALIZED]: "string is localized",
109
+ [I18N_STATUS.STRING_PARTIALLY_LOCALIZED]: "string is partially localized",
110
+ [I18N_STATUS.NUMBER_LOCALIZED]: "number is localized",
111
+ [I18N_STATUS.DATE_LOCALIZED]: "date is localized",
112
+ [I18N_STATUS.DATE_TIME_LOCALIZED]: "dateTime is localized",
113
+ [I18N_STATUS.TIME_LOCALIZED]: "time is localized",
114
+ [I18N_STATUS.CURRENCY_LOCALIZED]: "currency is localized",
115
+ [I18N_STATUS.PERCENTAGE_LOCALIZED]: "percentage is localized",
116
+ [I18N_STATUS.STRING_NOT_LOCALIZED]: "string is not localized",
117
+ [I18N_STATUS.DATE_NOT_LOCALIZED]: "date is not localized",
118
+ [I18N_STATUS.DATE_TIME_NOT_LOCALIZED]: "dateTime is not localized",
119
+ [I18N_STATUS.TIME_NOT_LOCALIZED]: "time is not localized",
120
+ [I18N_STATUS.NUMBER_NOT_LOCALIZED]: "number is not localized",
121
+ [I18N_STATUS.CURRENCY_NOT_LOCALIZED]: "currency is not localized",
122
+ [I18N_STATUS.PERCENTAGE_NOT_LOCALIZED]: "percentage is not localized",
123
+ [I18N_STATUS.TRUNCATION_ISSUE]: "truncation issue detected",
124
+ [I18N_STATUS.OVERLAPPING_ISSUE]: "overlapping issue detected",
125
+ [I18N_STATUS.ENCODING_ISSUE]: "encoding issue detected",
126
+ [I18N_STATUS.DNT]: "do not translate",
127
+ [I18N_STATUS.IGNORE]: "ignored this issue",
128
+ [I18N_STATUS.UNTRANSLATED]: "string is untranslated",
129
+ [I18N_STATUS.AUTO_IGNORE]: "automatically ignored issue",
130
+ [I18N_STATUS.USER_INPUT]: "user input field",
131
+ [I18N_STATUS.REVIEWED]: "string has been reviewed"
132
+ };
133
+ const PATTERNS = {
134
+ EMAIL: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}\b/gi,
135
+ URL: /^(https?:\/\/)?(www\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?$/
136
+ };
137
+ const USER_INPUT_PRE_FIX = "zqa_";
138
+ const RES_FILE_EXTENSIONS = [".txt", ".json"];
139
+ const SMART_SELECTOR = `//*[not(self::script or self::style or self::noscript)]
2
140
  [string-length(normalize-space(.)) > 0]
3
141
  [not(*)]
4
142
  [not(ancestor::*[
@@ -36,8 +174,280 @@
36
174
  or contains(@aria-hidden, 'true')
37
175
  or @hidden
38
176
  ])]
39
- `,V=!0,Te=["☐","�","퟿","â€","î","ÃÂ","í","ü","é","é","æ•°","据","ラã"],C=".i18n-verify.rc",k={HTML:"html",ASCII_TABLE:"ascii_table"},ee="metrics.cache",Ce="report",N={SANITY:"sanity",I18N:"i18n",CONTEXT:"context"},G={BOOKMARK:"bookmark",CATEGORY:"category",FILE_NAME:"fileName",SCREENSHOT:"screenshot",STRINGS:"strings"};class H{constructor(e){this.$driver=e}checkIfNullOrEmpty(e){return![null,"",void 0].includes(e)}getElement(){throw new Error("implementation is missing")}getElements(){throw new Error("implementation is missing")}getText(){throw new Error("implementation is missing")}getTitle(){throw new Error("implementation is missing")}getPlaceholderText(){throw new Error("implementation is missing")}getAltText(){throw new Error("implementation is missing")}getWidth(){throw new Error("implementation is missing")}getHeight(){throw new Error("implementation is missing")}getTagName(){throw new Error("implementation is missing")}getValue(){throw new Error("implementation is missing")}getLocation(){throw new Error("implementation is missing")}getElementDimension(){throw new Error("implementation is missing")}getElementID(){throw new Error("implementation is missing")}isElementDisplayed(){throw new Error("implementation is missing")}isElementPresent(){throw new Error("implementation is missing")}getElementString(){throw new Error("implementation is missing")}getElementStrings(){throw new Error("implementation is missing")}captureScreenshot(){throw new Error("implementation is missing")}getElementsCount(){throw new Error("implementation is missing")}switchToIFrame(){throw new Error("implementation is missing")}switchToParentFrame(){throw new Error("implementation is missing")}pause(){throw new Error("implementation is missing")}onScreenStringHighlight(){throw new Error("implementation is missing")}checkIfIframeIsPresent(){throw new Error("implementation is missing")}checkIfIframeBodyIsEmpty(){throw new Error("implementation is missing")}printOnConsole(e){console.log(e)}}const te=i=>F(i)&&v.statSync(i).isDirectory(),x=i=>F(i)&&v.statSync(i).isFile(),F=i=>v.existsSync(i),Ne=i=>!F(i)&&v.mkdirSync(i,{recursive:!0}),j=(i,e=!0)=>{(!F(i)||!te(i))&&(e&&f.debug(`Folder doesn't exists, creating \x1B[34m${i}\x1B[0m`),Ne(i))},M=i=>x(i)?v.readFileSync(i,{encoding:"utf-8"}):"",ae=i=>te(i)?v.readdirSync(i):[],xe=i=>x(i)?Z.extname(i):"",g=(...i)=>i?.every(e=>typeof e=="string")?Z.join(...i):"",q=(i,e,t="utf-8")=>v.writeFileSync(i,e,{encoding:t}),Ae=(i,e,t="utf-8")=>{if(!(!i||!e))try{v.appendFileSync(i,e+`
40
- `,{encoding:t,flag:"a"})}catch(a){f.error(a)}},Oe=i=>Z.dirname(i),O=i=>i.replace(/[^a-zA-Z0-9]+/g,"_"),_e=i=>v.readFileSync(i).toString("base64");class Re{#e;#t;#r;#a;#i;#n;constructor({appName:e,reportTime:t,isContext:a,isSanity:n,defaultLocale:s,reportFolderTimestamp:o}){this.#e=e,this.#r=t,this.#a=a,this.#i=n,this.#t=s,this.#n=o}getAppName(){return this.#e}getReportTime(){return this.#r}isSanityRun(){return this.#i}isContextRun(){return this.#a}getDefaultLocale(){return this.#t}getDefaultLocale(){return this.#t}getReportFolderTimestamp(){return this.#n}}class Ee{#e;$generatedContent;$type;constructor(e){this.$type=e}generate(e){this.#e=e,this.$generatedContent=this.buildContent()}export(e,t=Ce){this.write(e,t,this.$generatedContent),f.info(`Exported consolidated I18n Verification ${this.$type} report in ${e}`)}write(e,t,a){throw new Error("should be implemented by child report classes")}buildContent(){throw new Error("should be implemented by child report classes")}getMetaInfo(){return{defaultLocale:this.#e.getDefaultLocale(),appName:this.#e.getAppName(),reportTime:this.#e.getReportTime(),isSanity:this.#e.isSanityRun(),isContext:this.#e.isContextRun(),reportFolderTimestamp:this.#e.getReportFolderTimestamp()}}}function ze(){return`<header><div class="logo">zAutomate.AI</div><div class="report-timestamp"><span class="info"></span></div></header>
177
+ `;
178
+ const DEBUG_MODE = true;
179
+ const GARBLED_CHARACTERS = [
180
+ "☐",
181
+ "�",
182
+ "퟿",
183
+ "â€",
184
+ "î",
185
+ "ÃÂ",
186
+ "í",
187
+ "ü",
188
+ "é",
189
+ "é",
190
+ "æ•°",
191
+ "据",
192
+ "ラã"
193
+ ];
194
+ const CONFIG_FILE_NAME = ".i18n-verify.rc";
195
+ const SUPPORTED_REPORT_TYPES = {
196
+ HTML: "html",
197
+ ASCII_TABLE: "ascii_table"
198
+ };
199
+ const CACHE_FILE_NAME = "metrics.cache";
200
+ const DEFAULT_REPORT_NAME = "report";
201
+ const RUN_MODE = {
202
+ SANITY: "sanity",
203
+ I18N: "i18n",
204
+ CONTEXT: "context"
205
+ };
206
+ const CONTEXT_FILE_KEYS = {
207
+ BOOKMARK: "bookmark",
208
+ CATEGORY: "category",
209
+ FILE_NAME: "fileName",
210
+ SCREENSHOT: "screenshot",
211
+ STRINGS: "strings"
212
+ };
213
+ class BaseDriver {
214
+ constructor(driver) {
215
+ this.$driver = driver;
216
+ }
217
+ checkIfNullOrEmpty(value) {
218
+ return ![null, "", void 0].includes(value);
219
+ }
220
+ getElement() {
221
+ throw new Error("implementation is missing");
222
+ }
223
+ getElements() {
224
+ throw new Error("implementation is missing");
225
+ }
226
+ getText() {
227
+ throw new Error("implementation is missing");
228
+ }
229
+ getTitle() {
230
+ throw new Error("implementation is missing");
231
+ }
232
+ getPlaceholderText() {
233
+ throw new Error("implementation is missing");
234
+ }
235
+ getAltText() {
236
+ throw new Error("implementation is missing");
237
+ }
238
+ getWidth() {
239
+ throw new Error("implementation is missing");
240
+ }
241
+ getHeight() {
242
+ throw new Error("implementation is missing");
243
+ }
244
+ getTagName() {
245
+ throw new Error("implementation is missing");
246
+ }
247
+ getValue() {
248
+ throw new Error("implementation is missing");
249
+ }
250
+ getLocation() {
251
+ throw new Error("implementation is missing");
252
+ }
253
+ getElementDimension() {
254
+ throw new Error("implementation is missing");
255
+ }
256
+ getElementID() {
257
+ throw new Error("implementation is missing");
258
+ }
259
+ isElementDisplayed() {
260
+ throw new Error("implementation is missing");
261
+ }
262
+ isElementPresent() {
263
+ throw new Error("implementation is missing");
264
+ }
265
+ getElementString() {
266
+ throw new Error("implementation is missing");
267
+ }
268
+ getElementStrings() {
269
+ throw new Error("implementation is missing");
270
+ }
271
+ captureScreenshot() {
272
+ throw new Error("implementation is missing");
273
+ }
274
+ getElementsCount() {
275
+ throw new Error("implementation is missing");
276
+ }
277
+ switchToIFrame() {
278
+ throw new Error("implementation is missing");
279
+ }
280
+ switchToParentFrame() {
281
+ throw new Error("implementation is missing");
282
+ }
283
+ pause() {
284
+ throw new Error("implementation is missing");
285
+ }
286
+ onScreenStringHighlight() {
287
+ throw new Error("implementation is missing");
288
+ }
289
+ checkIfIframeIsPresent() {
290
+ throw new Error("implementation is missing");
291
+ }
292
+ checkIfIframeBodyIsEmpty() {
293
+ throw new Error("implementation is missing");
294
+ }
295
+ printOnConsole(str) {
296
+ console.log(str);
297
+ }
298
+ }
299
+ const dirExists = (path2) => pathExists(path2) && statSync(path2).isDirectory();
300
+ const fileExists = (path2) => pathExists(path2) && statSync(path2).isFile();
301
+ const pathExists = (path2) => existsSync(path2);
302
+ const createFolder = (path2) => !pathExists(path2) && mkdirSync(path2, { recursive: true });
303
+ const ensureDirectoryExists = (path2, log2 = true) => {
304
+ if (!pathExists(path2) || !dirExists(path2)) {
305
+ log2 && Logger$1.debug(`Folder doesn't exists, creating \x1B[34m${path2}\x1B[0m`);
306
+ createFolder(path2);
307
+ }
308
+ };
309
+ const getFileContent = (path2) => fileExists(path2) ? readFileSync(path2, { encoding: "utf-8" }) : "";
310
+ const getDirContents = (path2) => dirExists(path2) ? readdirSync(path2) : [];
311
+ const getFileExtenstion = (path2) => fileExists(path2) ? extname(path2) : "";
312
+ const joinPaths = (...paths) => paths?.every((p) => typeof p == "string") ? join(...paths) : "";
313
+ const saveToFile = (path2, content, encoding = "utf-8") => writeFileSync(path2, content, {
314
+ encoding
315
+ });
316
+ const addContentToFile = (path2, content, encoding = "utf-8") => {
317
+ if (!path2 || !content) return;
318
+ try {
319
+ appendFileSync(path2, content + "\n", {
320
+ encoding,
321
+ flag: "a"
322
+ });
323
+ } catch (err) {
324
+ Logger$1.error(err);
325
+ }
326
+ };
327
+ const getDirPath = (filePath) => dirname(filePath);
328
+ const toFileNameFormat = (name) => name.replace(/[^a-zA-Z0-9]+/g, "_");
329
+ const imageToBase64 = (imagePath) => {
330
+ const imgInput = readFileSync(imagePath);
331
+ return imgInput.toString("base64");
332
+ };
333
+ class ReportData {
334
+ /**
335
+ * @type {String}
336
+ */
337
+ #appName;
338
+ /**
339
+ * @type {String}
340
+ */
341
+ #defaultLocale;
342
+ /**
343
+ * @type {String}
344
+ */
345
+ #reportTime;
346
+ /**
347
+ * @type {Boolean}
348
+ */
349
+ #isContext;
350
+ /**
351
+ * @type {Boolean}
352
+ */
353
+ #isSanity;
354
+ /**
355
+ * @type {String}
356
+ */
357
+ #reportFolderTimestamp;
358
+ constructor({
359
+ appName,
360
+ reportTime,
361
+ isContext,
362
+ isSanity,
363
+ defaultLocale,
364
+ reportFolderTimestamp
365
+ }) {
366
+ this.#appName = appName;
367
+ this.#reportTime = reportTime;
368
+ this.#isContext = isContext;
369
+ this.#isSanity = isSanity;
370
+ this.#defaultLocale = defaultLocale;
371
+ this.#reportFolderTimestamp = reportFolderTimestamp;
372
+ }
373
+ getAppName() {
374
+ return this.#appName;
375
+ }
376
+ getReportTime() {
377
+ return this.#reportTime;
378
+ }
379
+ isSanityRun() {
380
+ return this.#isSanity;
381
+ }
382
+ isContextRun() {
383
+ return this.#isContext;
384
+ }
385
+ getDefaultLocale() {
386
+ return this.#defaultLocale;
387
+ }
388
+ getDefaultLocale() {
389
+ return this.#defaultLocale;
390
+ }
391
+ getReportFolderTimestamp() {
392
+ return this.#reportFolderTimestamp;
393
+ }
394
+ }
395
+ class BaseReport {
396
+ /**
397
+ * @type {ReportData}
398
+ */
399
+ #reportData;
400
+ /**
401
+ * @type {String | any}
402
+ */
403
+ $generatedContent;
404
+ /**
405
+ * @type {String}
406
+ */
407
+ $type;
408
+ constructor(type) {
409
+ this.$type = type;
410
+ }
411
+ generate(data2) {
412
+ this.#reportData = data2;
413
+ this.$generatedContent = this.buildContent();
414
+ }
415
+ export(path2, name = DEFAULT_REPORT_NAME) {
416
+ this.write(path2, name, this.$generatedContent);
417
+ Logger$1.info(
418
+ `Exported consolidated I18n Verification ${this.$type} report in ${path2}`
419
+ );
420
+ }
421
+ write(path2, name, data2) {
422
+ throw new Error("should be implemented by child report classes");
423
+ }
424
+ buildContent() {
425
+ throw new Error("should be implemented by child report classes");
426
+ }
427
+ /**
428
+ *
429
+ * @returns {{
430
+ * appName: String,
431
+ * defaultLocale: String,
432
+ * reportTime: String,
433
+ * isSanity: Boolean
434
+ * isContext: Boolean
435
+ * reportFolderTimestamp: String
436
+ * }}
437
+ */
438
+ getMetaInfo() {
439
+ return {
440
+ defaultLocale: this.#reportData.getDefaultLocale(),
441
+ appName: this.#reportData.getAppName(),
442
+ reportTime: this.#reportData.getReportTime(),
443
+ isSanity: this.#reportData.isSanityRun(),
444
+ isContext: this.#reportData.isContextRun(),
445
+ reportFolderTimestamp: this.#reportData.getReportFolderTimestamp()
446
+ };
447
+ }
448
+ }
449
+ function getBodyData() {
450
+ return `<header><div class="logo">zAutomate.AI</div><div class="report-timestamp"><span class="info"></span></div></header>
41
451
  <main>
42
452
  <div class="sidebar">
43
453
  <ul class="menu" id="menu">
@@ -158,7 +568,10 @@
158
568
  </div>
159
569
  </div>
160
570
  </div>
161
- </main>`}function Me(){return`html {
571
+ </main>`;
572
+ }
573
+ function getCssData() {
574
+ return `html {
162
575
  width: 100vw;
163
576
  height: 100vh;
164
577
  }
@@ -1103,7 +1516,18 @@
1103
1516
  background: #00000014 !important;
1104
1517
  transform: none !important;
1105
1518
  transition: none !important;
1106
- }`}function Pe({appName:i,reportTime:e,script:t,style:a,body:n,dataFilePaths:s=[],logData:o}){return`<!DOCTYPE html>
1519
+ }`;
1520
+ }
1521
+ function renderHtml({
1522
+ appName,
1523
+ reportTime,
1524
+ script,
1525
+ style,
1526
+ body,
1527
+ dataFilePaths = [],
1528
+ logData
1529
+ }) {
1530
+ return `<!DOCTYPE html>
1107
1531
  <html lang="en">
1108
1532
  <head>
1109
1533
  <meta charset="UTF-8" />
@@ -1117,17 +1541,19 @@
1117
1541
  name="description"
1118
1542
  content="zAutomate.AI report"
1119
1543
  />
1120
- <title>${i} - zAutomate.AI report | ${e}</title>
1544
+ <title>${appName} - zAutomate.AI report | ${reportTime}</title>
1121
1545
  <!-- 3rd party dependencies -->
1122
1546
  <link
1123
1547
  rel="stylesheet"
1124
1548
  href="https://cdn.datatables.net/2.0.3/css/dataTables.dataTables.min.css"
1125
1549
  />
1126
- ${s.map(u=>`<script
1127
- src="${u}"
1550
+ ${dataFilePaths.map(
1551
+ (v) => `<script
1552
+ src="${v}"
1128
1553
  type="text/javascript">
1129
- <\/script>`).join("")}
1130
- ${o?`<script type="text/javascript" async/>window.logData = \`${o}\`;<\/script>`:""}
1554
+ <\/script>`
1555
+ ).join("")}
1556
+ ${logData ? `<script type="text/javascript" async/>window.logData = \`${logData}\`;<\/script>` : ""}
1131
1557
  <script
1132
1558
  src="https://code.jquery.com/jquery-3.7.1.slim.min.js"
1133
1559
  integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8="
@@ -1140,17 +1566,19 @@
1140
1566
  defer
1141
1567
  ><\/script>
1142
1568
  <style>
1143
- ${a}
1569
+ ${style}
1144
1570
  </style>
1145
1571
  </head>
1146
1572
  <body>
1147
- ${n}
1573
+ ${body}
1148
1574
  </body>
1149
1575
  <script type="text/javascript" defer>
1150
- ${t}
1576
+ ${script}
1151
1577
  <\/script>
1152
1578
  </html>
1153
- `}const Be=()=>`(() => {
1579
+ `;
1580
+ }
1581
+ const menuBar = () => `(() => {
1154
1582
  // for sidebar menu
1155
1583
  // hide insights tab
1156
1584
  if(DataStore.hasRuntimeError() || !DataStore.ranSuccessfully() || DataStore.isContextRun()) {
@@ -1279,7 +1707,8 @@
1279
1707
  'header .report-timestamp .info'
1280
1708
  ).innerHTML = \`Report generated at: \${toLocaleString(Datastore.getTimestamp())}\`;
1281
1709
  });
1282
- })();`,$e=()=>`//overview content
1710
+ })();`;
1711
+ const overview = () => `//overview content
1283
1712
  (() => {
1284
1713
  if (DataStore.hasRuntimeError()) {
1285
1714
  document.getElementById('overview').innerHtml =
@@ -2970,7 +3399,8 @@
2970
3399
  }
2971
3400
  }
2972
3401
  });
2973
- })();`,ke=()=>`// insights content
3402
+ })();`;
3403
+ const insight = () => `// insights content
2974
3404
  (() => {
2975
3405
  if (!DataStore.ranSuccessfully()) {
2976
3406
  document.getElementById('overview').innerHTML =
@@ -3220,7 +3650,8 @@
3220
3650
  }
3221
3651
  }
3222
3652
  });
3223
- })();`,Ue=()=>`// locale grid
3653
+ })();`;
3654
+ const localeGrid = () => `// locale grid
3224
3655
  (() => {
3225
3656
  if (!DataStore.ranSuccessfully()) {
3226
3657
  return;
@@ -3431,16 +3862,17 @@
3431
3862
  };
3432
3863
  });
3433
3864
  })();
3434
- `,Ge=i=>`// DataStore
3865
+ `;
3866
+ const data = (metaData) => `// DataStore
3435
3867
  (() => {
3436
3868
  // prepare appData and set DataStore
3437
3869
  var appData = {
3438
- appName: '${i.appName}',
3439
- defaultLocale: '${i.defaultLocale}',
3440
- sanityRun: ${i.isSanity},
3441
- contextRun: ${i.isContext},
3442
- timeStamp: '${i.reportTime}',
3443
- reportFolderTimestamp: '${i.reportFolderTimestamp}',
3870
+ appName: '${metaData.appName}',
3871
+ defaultLocale: '${metaData.defaultLocale}',
3872
+ sanityRun: ${metaData.isSanity},
3873
+ contextRun: ${metaData.isContext},
3874
+ timeStamp: '${metaData.reportTime}',
3875
+ reportFolderTimestamp: '${metaData.reportFolderTimestamp}',
3444
3876
  pagesByLocale: {},
3445
3877
  metaData: {
3446
3878
  stats: {},
@@ -3528,7 +3960,8 @@
3528
3960
  }
3529
3961
 
3530
3962
  DataStore = new SimpleDataStore();
3531
- })();`,je=()=>`var DataStore;
3963
+ })();`;
3964
+ const global = () => `var DataStore;
3532
3965
  // global functions
3533
3966
  function openImageViewer(imageSrc) {
3534
3967
  var imageView = document.getElementById('imageView');
@@ -3572,7 +4005,8 @@
3572
4005
  }
3573
4006
  } else {
3574
4007
  window.isStandaloneReport = true;
3575
- }`,Ze=()=>`// log content
4008
+ }`;
4009
+ const log = () => `// log content
3576
4010
  (() => {
3577
4011
  document.addEventListener('DOMContentLoaded', function () {
3578
4012
  const pre = document.querySelector('#log .log-content pre');
@@ -3583,21 +4017,2671 @@
3583
4017
  pre.textContent = window.logData || (DataStore.hasRuntimeError() ? 'We are facing internal issue. Please try again after sometime.' : 'No log data found!');
3584
4018
  });
3585
4019
  });
3586
- })();`,Fe=i=>`${je()}
3587
- ${Ge(i)}
3588
- ${Be()}
3589
- ${$e()}
3590
- ${ke()}
3591
- ${Ue()}
3592
- ${Ze()}`;class Ve extends Ee{constructor(){super(k.HTML)}buildContent(){const e=this.getMetaInfo(),t=Fe(e),a=Me(),n=ze(),s=[],o=g(l.getReportPath(),"logs","log"),u=c.isSanityRun()||c.isContextRun(),h=[c.getQALocale(),...c.getOptions()?.supportedLocales||[]].filter(Boolean).map(L=>O(L)),p=ae(l.getReportPath()).filter(L=>h.includes(L)),U=p.length===1&&p[0]===O(c.getDefaultLocale());let T="";if(p.forEach(L=>(u||L!==e.defaultLocale||L===e.defaultLocale&&U)&&x(g(l.getReportPath(),L,ee))&&s.push(g(L,ee).replace(/\\/g,"/"))),x(o)){const L=[e.appName,...c.getL10nReportsPath().split(/[\\/]+/g),c.getMode()];L.push(l.getReportTimeStamp()),T=M(o).replace(new RegExp(l.getReportPath().replace(/\\/g,"\\\\"),"g"),g(...L)).replace(/\\/g,"\\\\").replace(/`/g,"\\`")}return Pe({appName:e.appName,reportTime:e.reportTime,body:n,script:t,style:a,dataFilePaths:s,logData:T})}write(e,t,a){q(g(e,`${t}.html`),a,"utf-8")}}class W extends Ee{#e;#t=!1;static#r="STATUS";static#a="COUNTS";constructor(){super(k.ASCII_TABLE),this.#i()}#i(){this.#e=new ye.Table({style:{headerTop:{left:"\x1B[94m╔\x1B[0m",mid:"\x1B[94m╦\x1B[0m",right:"\x1B[94m╗\x1B[0m",other:"\x1B[94m═"},headerBottom:{left:"\x1B[94m╟\x1B[0m",mid:"\x1B[94m╬\x1B[0m",right:"\x1B[94m╢\x1B[0m",other:"\x1B[94m═"},tableBottom:{left:"\x1B[94m╚\x1B[0m",mid:"\x1B[94m╩\x1B[0m",right:"\x1B[94m╝\x1B[0m",other:"\x1B[94m═\x1B[0m"},vertical:"\x1B[94m║\x1B[0m"},columns:[{name:W.#r,alignment:"left"},{name:W.#a,alignment:"center"}]})}buildContent(){if(R[r.REVIEWED]>0){this.#t=!0;for(const e in R)e!==r.REVIEWED?R.hasOwnProperty(e)&&this.#e.addRows([{STATUS:e,COUNTS:`${R[e]}`}]):(this.#e.addRows([{STATUS:"\x1B[94m"+"═".repeat(28)+"\x1B[0m",COUNTS:"\x1B[94m"+"═".repeat(8)+"\x1B[0m"}]),this.#e.addRows([{STATUS:"OVERALL_REVIEWED",COUNTS:`${R[e]}`}]))}}export(){this.#t?this.#e.printTable():f.info("There are no visbile elements with UI strings")}}class re{static#e(e){switch(e){case k.HTML:return new Ve;case k.ASCII_TABLE:return new W;default:throw new Error("unsupported report type requested")}}static export(e,t,a){const n=re.#e(e),s=new Re({appName:c.getAppName(),reportTime:new Date().toLocaleString(),isContext:c.isContextRun(),isSanity:c.isSanityRun(),defaultLocale:c.getDefaultLocale(),reportFolderTimestamp:l.getReportTimeStamp()});n.generate(s),n.export(t,a)}}class S{static#e;static#t;static init(){S.#t=g(l.getReportPath(),O(c.getLocale())),S.#e=g(S.#t,ee),this.#r()}static exists(){return x(S.#e)}static save(e){this.#r();const t=`!window.rawData && (window.rawData={'${c.getLocale()}':{}});window.rawData['${c.getLocale()}']=${JSON.stringify(e)};`;q(S.#e,t)}static getData(){if(this.exists())try{return JSON.parse(M(S.#e).replace(new RegExp(`(\\!window.rawData && \\(window\\.rawData=\\{'${c.getLocale()}':\\{\\}\\}\\);window\\.rawData\\['${c.getLocale()}'\\]=)|(;$)`,"g"),""))}catch{return{}}else return{}}static#r(){j(S.#t)}static getCacheDirPath(){return S.#t}}class We{#e;#t;#r;#a;#i;#n;#s;#o;#l;#c;#d;#m;#p;#g;#h;#E;#f;#v;#w;#L;#u;#y;#I;#b;#S;constructor(e={}){this.#e=e?.localizedStrings||0,this.#t=e?.notLocalizedStrings||0,this.#r=e?.untranslatedStrings||0,this.#a=e?.partialStrings||0,this.#i=e?.localizedDateTime||0,this.#n=e?.localizedDate||0,this.#s=e?.localizedTime||0,this.#o=e?.notLocalizedDateTime||0,this.#l=e?.notLocalizedDate||0,this.#c=e?.notLocalizedTime||0,this.#d=e?.localizedNumber||0,this.#m=e?.notLocalizedNumber||0,this.#p=e?.localizedCurrency||0,this.#g=e?.notLocalizedCurrency||0,this.#h=e?.localizedPercentage||0,this.#E=e?.notLocalizedPercentage||0,this.#f=e?.ignored||0,this.#v=e?.dnt||0,this.#w=e?.autoIgnored||0,this.#L=e?.userInput||0,this.#u=e?.encoding||0,this.#y=e?.truncation||0,this.#I=e?.overlapping||0,this.#b=e?.reviewed||0,this.#S=e?.context||0}getLocalizedStrings(){return this.#e}setLocalizedStrings(e){this.#e=e}getUntranslatedStrings(){return this.#r}setUntranslatedStrings(e){this.#r=e}getNotLocalizedStrings(){return this.#t}setNotLocalizedStrings(e){this.#t=e}getPartialStrings(){return this.#a}setPartialStrings(e){this.#a=e}getLocalizedDateTime(){return this.#i}setLocalizedDateTime(e){this.#i=e}getLocalizedDate(){return this.#n}setLocalizedDate(e){this.#n=e}getLocalizedTime(){return this.#s}setLocalizedTime(e){this.#s=e}getNotLocalizedDateTime(){return this.#o}setNotLocalizedDateTime(e){this.#o=e}getNotLocalizedDate(){return this.#l}setNotLocalizedDate(e){this.#l=e}getNotLocalizedTime(){return this.#c}setNotLocalizedTime(e){this.#c=e}getLocalizedNumber(){return this.#d}setLocalizedNumber(e){this.#d=e}getNotLocalizeNumber(){return this.#m}setNotLocalizeNumber(e){this.#m=e}getCurrency(){return this.#p}setCurrency(e){this.#p=e}getNotLocalizeCurrency(){return this.#g}setNotLocalizeCurrency(e){this.#g=e}getPercentage(){return this.#h}setPercentage(e){this.#h=e}getNotLocalizePercentage(){return this.#E}setNotLocalizePercentage(e){this.#E=e}getIgnored(){return this.#f}setIgnored(e){this.#f=e}getUserInput(){return this.#L}setUserInput(e){this.#L=e}getDnt(){return this.#v}setDnt(e){this.#v=e}getAutoIgnored(){return this.#w}setAutoIgnored(e){this.#w=e}getEncoding(){return this.#u}setEncoding(e){this.#u=e}getTruncation(){return this.#y}setTruncation(e){this.#y=e}getOverlapping(){return this.#I}setOverlapping(e){this.#I=e}getReviewed(){return this.#b}setReviewed(e){this.#b=e}getContext(){return this.#S}setContext(e){this.#S=e}incrementByType(e){switch(e){case r.STRING_LOCALIZED:++this.#e;break;case r.STRING_NOT_LOCALIZED:++this.#t;break;case r.UNTRANSLATED:++this.#r;break;case r.STRING_PARTIALLY_LOCALIZED:++this.#a;break;case r.AUTO_IGNORE:++this.#w;break;case r.IGNORE:++this.#f;break;case r.DNT:++this.#v;break;case r.ENCODING_ISSUE:++this.#u;break;case r.DATE_LOCALIZED:++this.#n;break;case r.TIME_LOCALIZED:++this.#s;break;case r.DATE_TIME_LOCALIZED:++this.#i;break;case r.DATE_NOT_LOCALIZED:++this.#l;break;case r.TIME_NOT_LOCALIZED:++this.#c;break;case r.DATE_TIME_NOT_LOCALIZED:++this.#o;break;case r.NUMBER_LOCALIZED:++this.#d;break;case r.NUMBER_NOT_LOCALIZED:++this.#m;break;case r.CURRENCY_LOCALIZED:++this.#p;break;case r.CURRENCY_NOT_LOCALIZED:++this.#g;break;case r.PERCENTAGE_LOCALIZED:++this.#h;break;case r.PERCENTAGE_NOT_LOCALIZED:++this.#E;break;case r.TRUNCATION_ISSUE:++this.#y;break;case r.OVERLAPPING_ISSUE:++this.#I;break;case r.REVIEWED:++this.#b;break;case r.USER_INPUT:++this.#L;break;case"context":++this.#S;break}}toJSON(){return{localizedStrings:this.#e,notLocalizedStrings:this.#t,untranslatedStrings:this.#r,partialStrings:this.#a,localizedDateTime:this.#i,localizedDate:this.#n,localizedTime:this.#s,notLocalizedDateTime:this.#o,notLocalizedDate:this.#l,notLocalizedTime:this.#c,localizedNumber:this.#d,notLocalizedNumber:this.#m,localizedCurrency:this.#p,notLocalizedCurrency:this.#g,localizedPercentage:this.#h,notLocalizedPercentage:this.#E,ignored:this.#f,dnt:this.#v,autoIgnored:this.#w,userInput:this.#L,encoding:this.#u,truncation:this.#y,overlapping:this.#I,reviewed:this.#b,context:this.#S}}}class Ye{#e;constructor(e={}){this.#e=new We(e.stats)}getStats(){return this.#e}setStats(e){this.#e=e}toJSON(){return{stats:this.#e}}}class me{#e;#t;#r;constructor(e){this.#e=e?.type||"",this.#t=e?.imagePath||"",this.#r=e?.description||""}getType(){return this.#e}setType(e){this.#e=e}getImagePath(){return this.#t}setImagePath(e){this.#t=e}getDescription(){return this.#r}setDescription(e){this.#r=e}toJSON(){return{type:this.#e,description:this.#r,imagePath:this.#t}}}class ie{#e={};constructor(e){if(e)for(const t in e)e[t].forEach(a=>{this.#e[t]||(this.#e[t]=[]),this.#e[t].push(new me(a))})}getStringData(e){return this.#e[e]||[]}setStringData(e,t){return!this.#e[e]&&(this.#e[e]=[]),this.#e[e].push(new me(t)),!0}checkAndAdd(e,t){!this.#e[e]&&(this.#e[e]=[]);const a=this.getStringData(e).some(n=>n.getDescription()!==t.description||n.getImagePath()!==t.imagePath||n.getType()!==n.type);return a&&this.setStringData(e,t),a}hasStringData(e){return e in this.#e}static createNew(e,t){return t=Array.isArray(t)?t:[t],new ie({data:{[e]:t}})}toJSON(){return this.#e}}class B{#e;#t;constructor(e={}){this.#e=new Ye(e.metaData),this.#t=new ie(e.stringsData)}getMetaData(){return this.#e}setMetaData(e){this.#e=e}getStringEntry(e){return this.#t.getStringData(e)}static addString(e,t,a,n){const s=B.getInstance(),o=s.#r(e,t,a,n.replace(/\\/g,"/"));return o&&s.save(),o}#r(e,t,a,n){let s=!1;const o={type:t,description:a,imagePath:n};return this.#t.hasStringData(e)?s=this.#t.checkAndAdd(e,o):s=this.#t.setStringData(e,o),s&&this.#e.getStats().incrementByType(t),s}static incrementCountByType(e){const t=B.getInstance();t.#e.getStats().incrementByType(e),t.save()}toJSON(){return{metaData:this.#e,stringsData:this.#t}}save(){S.save(this)}remove(){S.delete()}static getInstance(){return new B(S.getData())}}class l{static#e;static#t;static setup(){l.#t||(l.#t=l.#r());const e=Z.resolve();l.#e=g(e,c.getL10nReportsPath(),c.getMode(),l.#t)}static getReportTimeStamp(){return l.#t}static getReportPath(){return l.#e}static reviewedReports(e=null,t=null){return l.#a(r.REVIEWED,e,t)}static getContextPath(){return this.#i()}static[r.STRING_LOCALIZED](e,t){return l.#a(r.STRING_LOCALIZED,e,t)}static[r.STRING_NOT_LOCALIZED](e,t){return l.#a(r.STRING_NOT_LOCALIZED,e,t)}static[r.STRING_PARTIALLY_LOCALIZED](e,t){return l.#a(r.STRING_PARTIALLY_LOCALIZED,e,t)}static[r.DNT](e,t){return l.#a(r.DNT,e,t)}static[r.IGNORE](e,t){return l.#a(r.IGNORE,e,t)}static[r.AUTO_IGNORE](e,t){return l.#a(r.AUTO_IGNORE,e,t)}static[r.UNTRANSLATED](e,t){return l.#a(r.UNTRANSLATED,e,t)}static[r.ENCODING_ISSUE](e,t){return l.#a(r.ENCODING_ISSUE,e,t)}static[r.DATE_TIME_LOCALIZED](e,t){return l.#a(r.DATE_TIME_LOCALIZED,e,t)}static[r.DATE_TIME_NOT_LOCALIZED](e,t){return l.#a(r.DATE_TIME_NOT_LOCALIZED,e,t)}static[r.DATE_LOCALIZED](e,t){return l.#a(r.DATE_LOCALIZED,e,t)}static[r.DATE_NOT_LOCALIZED](e,t){return l.#a(r.DATE_NOT_LOCALIZED,e,t)}static[r.TIME_LOCALIZED](e,t){return l.#a(r.TIME_LOCALIZED,e,t)}static[r.TIME_NOT_LOCALIZED](e,t){return l.#a(r.TIME_NOT_LOCALIZED,e,t)}static[r.CURRENCY_LOCALIZED](e,t){return l.#a(r.CURRENCY_LOCALIZED,e,t)}static[r.CURRENCY_NOT_LOCALIZED](e,t){return l.#a(r.CURRENCY_NOT_LOCALIZED,e,t)}static[r.PERCENTAGE_LOCALIZED](e,t){return l.#a(r.PERCENTAGE_LOCALIZED,e,t)}static[r.PERCENTAGE_NOT_LOCALIZED](e,t){return l.#a(r.PERCENTAGE_NOT_LOCALIZED,e,t)}static[r.NUMBER_LOCALIZED](e,t){return l.#a(r.NUMBER_LOCALIZED,e,t)}static[r.NUMBER_NOT_LOCALIZED](e,t){return l.#a(r.NUMBER_NOT_LOCALIZED,e,t)}static incrementCount(e,t,a,n){R.hasOwnProperty(e)&&(R[e]++,B.addString(t,e,n,a.replace(l.#e,"")))}static#r(){const e=new Date,t=e.getFullYear(),a=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0"),o=String(e.getMinutes()).padStart(2,"0");return`${t}-${a}-${n}-${s}-${o}`}static#a=(e,t,a)=>{const n=g(l.#e,O(c.getLocale()),"screenshots",String(e).toLowerCase());if(j(n,V),t!=null){const s=g(l.#e,O(c.getLocale()),"strings");j(s,V);let o="";const u=g(s,e+".txt");F(u)?(M(u).includes(a)||(o+=`
3593
- |<<<<<<<<<<<<<------${a}------>>>>>>>>>>>>>|
3594
- `),o+=t):(o+=`
3595
- |<<<<<<<<<<<<<------${a}------>>>>>>>>>>>>>|
3596
- `,o+=t),Ae(u,o)}return n};static#i=()=>{const e=g(l.#e,O(c.getLocale()),"contexts");return j(e,V),e};static#n(e){re.export(e,l.#e)}static generateHtml(){l.#n(k.HTML)}static generateAsciiTable(){l.#n(k.ASCII_TABLE)}}let f=class w{static#e=!1;static#t;static#r=[];static info(e){w.#a("info",e)}static warn(e){w.#a("warn",e)}static error(e,t){w.#a("errr",e,t)}static debug(e){w.#a("dbug",e)}static#a(e,t,a=""){const n={INFO:"\x1B[37m",WARN:"\x1B[33m",ERRR:"\x1B[31m",DBUG:"\x1B[34m"};e=e.toUpperCase();let s=n[e]||n.DEFAULT;a=a?` reason: ${a.toString()}`:"";let o=`[${new Date().toLocaleString()}] [${s}${e}\x1B[0m] [${c.getLocale()}] - ${t}${a}`;switch(e){case"INFO":console.info(o);break;case"WARN":console.warn(o);break;case"ERRR":console.error(o);break;case"DBUG":console.debug(o);break;default:console.log(o)}o=o.replace(/\x1b\[\d+m/g,""),w.#i(`${o}
3597
- `)}static#i=e=>{if(w.#e)w.#r.push(e),w.#t=setInterval(()=>{w.#e||(clearInterval(w.#t),e=w.#r.join(`
3598
- `),w.#r=[],e&&w.#i(e))},10);else{w.#e=!0;const t=g(l.getReportPath(),"logs"),a=g(t,"log");j(t,V),v.appendFileSync(a,e),w.#e=!1}}};class He extends H{constructor(e){super(e)}async getElement(e,t=!1){return await this.$driver.element.find({selector:e,locateStrategy:e.startsWith("/")?"xpath":"css selector",suppressNotFoundErrors:t})}async getElements(e,t=!1){return await this.$driver.element.findAll({selector:e,locateStrategy:e.startsWith("/")?"xpath":"css selector",suppressNotFoundErrors:t})}async getText(e){return await e.getText()}async getTitle(e){return await e.getAttribute("title")}async getPlaceholderText(e){return await e.getAttribute("placeholder")}async getAltText(e){return await e.getAttribute("alt")}async getTagName(e){return await e.getTagName()}async getValue(e){return await e.getAttribute("value")}async getElementID(e){return await e.getAttribute("id")}async getElementDimension(e){const t=await e.getRect();if(![null,"",void 0].includes(t))return[t.x,t.y,t.height,t.width]}async isElementDisplayed(e){return await this.$driver.isVisible(e)}async isElementPresent(e){return await this.$driver.isPresent(e)}async getElementStrings(e){const t=[];return this.isElementDisplayed(e)&&[{type:"eleTxt",value:await this.getText(e)},{type:"altTxt",value:await this.getAltText(e)},{type:"titleTxt",value:await this.getTitle(e)},{type:"placeTxt",value:await this.getPlaceholderText(e)},{type:"valueTxt",value:await this.getValue(e)}].forEach(({value:n})=>{this.checkIfNullOrEmpty(n)&&t.push(n)}),t}async getElementString(e){let t=null;const a=[this.getText,this.getAltText,this.getTitle,this.getPlaceholderText,this.getValue];for(const n of a)if(t=await n(e),t!==null)return t;return t}async captureScreenshot(e){await qe(this.$driver,e)}async getElementsCount(e){return e.length}async switchToIFrame(e,t){return new Promise(a=>{this.$driver.frame(e,function(){a(!0)})})}async switchToParentFrame(){return new Promise(e=>this.$driver.frame(null,function(){e(!0)}))}pause(e){this.$driver.pause(e*1e3)}async onScreenStringHighlight(e,t){await this.$driver.execute((a,n)=>{const s=window.getComputedStyle(a).border;a.style.border=`3px solid ${n}`,setTimeout(()=>{a.style.border=s},40)},[e,t])}async checkIfIframeIsPresent(){return new Promise(e=>{this.$driver.isPresent({selector:"//iframe",locateStrategy:"xpath",suppressNotFoundErrors:!0},t=>{e(t.value)})})}async checkIfIframeBodyIsEmpty(){return(await this.$driver.executeScript(function(){return document.body.innerHTML})).trim()===""}}const qe=async(i,e)=>{const t=await he({host:"localhost",port:Qe(i)}),{Page:a}=t;await a.enable();const{data:n}=await a.captureScreenshot({format:"png",captureBeyondViewport:!0}),s=Buffer.from(n,"base64");v.writeFileSync(e,s),f.debug(`Screenshot saved as: ${e}`),await t.close()},Qe=i=>{const e=i?.capabilities?.["goog:chromeOptions"]?.debuggerAddress;return e&&e.split(":")?.[1]||9229};class Xe extends H{constructor(e){super(e)}async getElement(e){return await this.$driver.$(e)}async getElements(e){return await this.$driver.$$(e)}async getText(e){return await $(e).getText()}async getTitle(e){return await $(e).getAttribute("title")}async getPlaceholderText(e){return await $(e).getAttribute("placeholder")}async getAltText(e){return await $(e).getAttribute("alt")}async getTagName(e){return await $(e).getTagName()}async getValue(e){return await $(e).getValue()}async getElementID(e){return await $(e).getAttribute("id")}async getElementDimension(e){if(!e)return null;try{const t=await e.getLocation(),a=await e.getSize();return!t||!a?null:[t.x,t.y,a.height,a.width]}catch(t){return console.error("Error getting element dimensions:",t),null}}async isElementDisplayed(e){return await $(e).isDisplayed()}async isElementPresent(e){return await $(e).isExisting()}async getElementStrings(e){const t=[];return[{type:"elTxt",value:await this.getText(e)},{type:"altTxt",value:await this.getAltText(e)},{type:"titleTxt",value:await this.getTitle(e)},{type:"placeTxt",value:await this.getPlaceholderText(e)},{type:"valueTxt",value:await this.getValue(e)}].forEach(({value:n})=>{this.checkIfNullOrEmpty(n)&&t.push(n)}),t}async getElementString(e){let t=null;const a=[this.getText,this.getAltText,this.getTitle,this.getPlaceholderText,this.getValue];for(const n of a)if(t=await n(e),t!==null)return t;return t}async captureScreenshot(e){await Je(this.$driver,e)}async getElementsCount(e){return e.length}async switchToIFrame(e,t){await this.$driver.switchFrame(t)}async switchToParentFrame(){await this.$driver.switchToParentFrame()}pause(e){this.$driver.pause(e*1e3)}async onScreenStringHighlight(e,t){await this.$driver.execute((a,n)=>{const s=window.getComputedStyle(a).border;a.style.border=`3px solid ${n}`,setTimeout(()=>{a.style.border=s},40)},e,t)}async checkIfIframeIsPresent(){return new Promise(e=>{this.$driver.$("//iframe").isExisting().then(()=>{e(!0)})})}async checkIfIframeBodyIsEmpty(){return(await this.$driver.executeScript("return document.body.innerHTML;",[])).trim()===""}}const Je=async(i,e)=>{const t=Ke(i),a=await he({host:"localhost",port:t}),{Page:n}=a;await n.enable();const{data:s}=await n.captureScreenshot({format:"png",captureBeyondViewport:!0});v.writeFileSync(e,Buffer.from(s,"base64")),await a.close()},Ke=i=>{const e=i.capabilities?.["goog:chromeOptions"]?.debuggerAddress;return e&&e.split(":")[1]||9229},et=({subject:i,selector:e,options:t={},driver:a})=>{if(!Cypress){a.printOnConsole("Cypress object is inaccessible");return}const n=m=>m.resultType===XPathResult.NUMBER_TYPE,s=m=>m.numberValue,o=m=>m.resultType===XPathResult.STRING_TYPE,u=m=>m.stringValue,h=m=>m.resultType===XPathResult.BOOLEAN_TYPE,p=m=>m.booleanValue,U=m=>Cypress._.isNumber(m)||Cypress._.isString(m)||Cypress._.isBoolean(m),T={name:"xpath",message:e};if(Cypress.dom.isElement(i)&&i.length>1)throw new Error("xpath() can only be called on a single element. Your subject contained "+i.length+" elements.");const L=()=>{let m=[],_,ce=cy.state("withinSubject");Cypress.dom.isElement(i)?_=i[0]:Cypress.dom.isDocument(i)?_=i:ce?_=ce[0]:_=cy.state("window").document;let A=(_.ownerDocument||_).evaluate(e,_);if(n(A)){const I=s(A);return T.consoleProps=()=>({XPath:e,type:"number",result:I}),I}if(o(A)){const I=u(A);return T.consoleProps=()=>({XPath:e,type:"string",result:I}),I}if(h(A)){const I=p(A);return T.consoleProps=()=>({XPath:e,type:"boolean",result:I}),I}try{let I=A.iterateNext();for(;I;)m.push(I),I=A.iterateNext();return T.consoleProps=()=>({XPath:e,result:m.length===1?m[0]:m}),m}catch(I){return console.error("Document tree modified during iteration",I),null}},le=()=>Cypress.Promise.try(L).then(m=>(U(m)||(m=Cypress.$(m),m.selector=e),cy.verifyUpcomingAssertions(m,t,{onRetry:le})));return le().then(m=>(t.log!==!1&&Cypress.log(T),m)).catch(m=>console.log(m))};class tt extends H{constructor(e){super(e)}async getElement(e){return typeof e!="string"?this.$driver.wrap(e):e.startsWith("//")?await this.xpath(e).first():await this.$driver.get(e).first()}async getElements(e){return typeof e!="string"?this.$driver.wrap(e):e.startsWith("//")?await this.xpath(e):await this.$driver.get(e)}async getText(e){return typeof e=="string"?await this.$driver.get(e).invoke("text"):await this.$driver.wrap(e).invoke("text")}async getTitle(e){return typeof e=="string"?await this.$driver.get(e).title():this.$driver.wrap().title()}async getPlaceholderText(e){return typeof e=="string"?this.$driver.get(e).filter("input").invoke("attr","placeholder").then(t=>t):this.$driver.$$(e).attr("placeholder")}async getAltText(e){return this.$driver.get(e).invoke("attr","alt")}async getWidth(e){return typeof e=="string"?this.$driver.get(e).invoke("width"):this.$driver.$$(e).width()}async getHeight(e){return typeof e=="string"?this.$driver.get(e).invoke("height"):this.$driver.$$(e).height()}async getTagName(e){return typeof e=="string"?this.$driver.get(e).invoke("prop","tagName").then(t=>t.toLowerCase()):this.$driver.$$(e).tagName}async getValue(e){return typeof e=="string"?this.$driver.get(e).invoke("val"):this.$driver.wrap(e).invoke("val")}async getLocation(e){if(typeof e=="string")return this.$driver.get(e).invoke("offset").then(t=>({x:t.left,y:t.top}));{const t=this.$driver.$$(e).offset();return{x:t.left,y:t.top}}}async isElementDisplayed(e){return typeof e=="string"?this.$driver.get(e).then(t=>t.is(":visible")):this.$driver.$$(e).is(":visible")}async captureScreenshot(e){this.$driver.screenshot(e)}async getElementsCount(e){return new Promise(t=>typeof e=="string"?this.$driver.get(e).its("length").then(a=>t(a)):this.$driver.wrap(e,{timeout:8e3}).its("length").then(a=>t(a)))}async getElementStrings(e){const t=[];try{[{type:"elTxt",value:await this.getText(e)},{type:"altTxt",value:await this.getAltText(e)},{type:"placetxt",value:await this.getPlaceholderText(e)}].forEach(({value:n})=>{this.checkIfNullOrEmpty(n)&&t.push(n)})}catch(a){f.error("Error getting text of element:",a)}return t}printOnConsole(e){this.$driver.log(e)}xpath(e,t,a={}){return et({subject:e,selector:t,options:a,driver:this.$driver})}}class at extends H{constructor(e){super(e)}async getElement(e){return await this.driver.findElement(e)}async getElements(e){return await this.driver.findElements(e)}async getText(e){return await e.getText()}async getTitle(){return await this.driver.getTitle()}async getAttribute(e,t){return await e.getAttribute(t)}async getTagName(e){return await e.getTagName()}async getElementDimension(e){const t=await e.getRect();if(![null,"",void 0].includes(t))return[t.x,t.y,t.height,t.width]}async isElementDisplayed(e){return await e.isDisplayed()}async getElementStrings(e){const t=[];return[{type:"elTxt",value:await this.getText(e)},{type:"altTxt",value:await this.getAttribute(e,"alt")},{type:"titleTxt",value:await this.getAttribute(e,"title")},{type:"placeTxt",value:await this.getAttribute(e,"placeholder")},{type:"valueTxt",value:await this.getAttribute(e,"value")}].forEach(({value:n})=>{this.checkIfNullOrEmpty(n)&&t.push(n)}),t}async getElementsCount(e){return e.length}}const rt=(i,e)=>{switch(i){case z.NIGHT_WATCH:return new He(e);case z.WEB_DRIVER_IO:return new Xe(e);case z.CYPRESS:return new tt(e);case z.SELENIUMJS:return new at(e);default:throw new Error("Unsupported framework")}},it=(i,e)=>i in e,nt=(i,e,t=[])=>i.every(a=>(it(a,e)||t.push(a),!0)),fe=(i,e=", ")=>i.join(e),D=(i=!0)=>i?"(?:\\s|\\t|(?:&nbsp;))":/(?:\s|\t|(?:&nbsp;))/g;class P{#e={};#t;constructor(e){this.#t=e,this.#r(),this.buildConfig(),this.#a()}#r(){this.addToConfig("supportedLocales",c.getOptions()?.supportedLocales,[]),this.addToConfig("defaultLocale",c.getDefaultLocale()),this.addToConfig("defaultLanguage",c.getDefaultLocale()?.split(/[-_ ]/g)[0]),this.addToConfig("language",c.getLocale()?.split(/[-_ ]/g)[0]),this.addToConfig("locale",c.getLocale()),this.addToConfig("qaLocale",c.getQALocale())}buildConfig(){throw new Error(`{{${this.#t}}} buildConfig should be implemented by child class`)}#a(){Q.load(X.entireSupplemental()),Q.load(X.entireMainFor(this.#i(this.#e.defaultLocale),this.#i(this.#e.locale)))}#i(e){if(this.isQaLocale())return"en";e=e.replace(/[-_ ]/g,"-");const t=X.availableLocales;let a;if(t.find(n=>n===e))a=e;else{const n=e.split("-")[0];t.find(s=>s===n)?a=n:a=e}return a}validate(e){throw new Error(`{{${this.#t}}} validate should be implemented by child class`)}isInternationalized(e){throw new Error(`{{${this.#t}}} isInternationalized should be implemented by child class`)}setConfig(e){this.#e=e}addToConfig(e,t,a){this.#e[e]=t??a}getConfig(){return this.#e}isSupportedLocale(){return this.#e.supportedLocales.includes(this.currentLocale())}isQaLocale(){return this.currentLocale()===this.#e?.qaLocale}isDefaultLocale(){return this.currentLocale()===this.defaultLocale()}defaultLocale(){return this.#e?.defaultLocale}defaultLanguage(){return this.#e?.defaultLanguage}currentLocale(){return this.#e?.locale}currentLanguage(){return this.#e.language}getGlobalize(e){return Q(this.#i(e))}}class st extends P{constructor(){super("currency")}validate(e){return this.#s(e)||this.isInternationalized(e)}isInternationalized(e){return this.#e(this.currentLocale(),e)}buildConfig(){}#e(e,t){const a=this.#i(e),n=this.#n(e,a);if(!this.#t(a,n,t))return!1;const o=this.#r(a,n,t);return!isNaN(this.getGlobalize(e).numberParser()(o))}#t(e,t,a){return new RegExp(`^(?:-)?(?:${e}|\\${t})(?:${D()})?(?:-)?[0-9,. ]+$`,"gi").test(a)||new RegExp(`^(?:[- ]?)[0-9,. ]+(?:${D()})?(?:${e}|\\${t})$`,"gi").test(a)}#r(e,t,a){return a.replace(new RegExp(`^(?:-)(?:${D()})?`,"gi"),"").replace(new RegExp(`^(?:${D()})?(?:${e}|\\${t})`,"gi"),"").replace(new RegExp(`^(?:-)(?:${D()})?`,"gi"),"").replace(new RegExp(`(?:${D()})?(?:${e}|\\${t})$`,"gi"),"").trim()}#a(e){return(this.getGlobalize(e).cldr.supplemental(["likelySubtags",e])||e).split(/[-_ ]/).pop()}#i(e){const t=this.#a(e),n=this.getGlobalize(e).cldr.supplemental("currencyData").region[t];if(n){const s=n.find(o=>{const u=Object.values(o)[0];return!u._tender&&(!u._to||new Date(u._to)>=new Date)});return s?Object.keys(s)[0]:"USD"}return"USD"}#n(e,t){return this.getGlobalize(e).cldr.main(`numbers/currencies/${t}`)?.symbol||"$"}#s(e){return this.#e(this.defaultLocale(),e)}}const ot=i=>{let[e="en",t="us"]=i.split(/[-_ ]/g);switch(t=String(t).toLowerCase(),e){case"en":return t==="gb"?b.en.GB:b.en;case"de":return b.de;case"es":return b.es;case"fr":return b.fr;case"pt":return b.pt;case"ja":return b.ja;case"zh":return["hans","cn","sg","hans-cn"].includes(t)?b.zh.hans:["hant","tw","hk","mo","hant-tw"].includes(t)?b.zh.hant:b.zh;case"ru":return b.ru;case"nl":return b.nl;case"uk":return b.uk;default:return b.en}},ne=(i,e)=>(e=String(e),ot(i).parse(String(e).trim()).forEach(a=>{e=e.replace(a.text,"")}),e.replace(/[^\p{L}\p{N}]+/gu,"").trim().length===0),pe=i=>{try{return i=i.replace("_","-"),Intl.DateTimeFormat.supportedLocalesOf(i)[0]}catch{return Logger.warn(`${i} is unsupported by Intl`),!1}},se=(i,e,t)=>(i=pe(i),!!(i!==!1&&E.DateTime.fromFormat(t,e,{locale:pe(i)}).isValid));class lt extends P{constructor(){super("date")}validate(e){return this.#t(e)||this.isInternationalized(e)}isInternationalized(e){return this.#e(this.isQaLocale()?this.defaultLocale():this.currentLocale(),e)}buildConfig(){}#e(e,t){return this.#r(e,t)||this.#a(e,t)||this.#i(e,t)}#t(e){return this.#e(this.defaultLocale(),e)}#r(e,t){const a=["short","medium","long","full"];for(let n of a)if(this.getGlobalize(e).dateParser({date:n})(t))return!0;return!1}#a(e,t){const a=[E.DateTime.DATE_SHORT,E.DateTime.DATE_MED,E.DateTime.DATE_FULL,E.DateTime.DATE_HUGE,E.DateTime.DATE_MED_WITH_WEEKDAY,"D","DD","DDD","DDDD"];for(let n of a)if(se(e,n,t))return!0;return!1}#i(e,t){return ne(this.isQaLocale()?this.defaultLocale():e,t)}}class ct extends P{constructor(){super("dateTime")}validate(e){return this.#t(e)||this.isInternationalized(e)}isInternationalized(e){return this.#e(this.isQaLocale()?this.defaultLocale():this.currentLocale(),e)}buildConfig(){}#e(e,t){return this.#r(e,t)||this.#a(e,t)||this.#i(e,t)}#t(e){return this.#e(this.defaultLocale(),e)}#r(e,t){const a=["short","medium","long","full"];for(let n of a)if(this.getGlobalize(e).dateParser({datetime:n})(t))return!0;return!1}#a(e,t){const a=[E.DateTime.DATETIME_SHORT,E.DateTime.DATETIME_SHORT_WITH_SECONDS,E.DateTime.DATETIME_MED,E.DateTime.DATETIME_MED_WITH_SECONDS,E.DateTime.DATETIME_MED_WITH_WEEKDAY,E.DateTime.DATETIME_FULL,E.DateTime.DATETIME_FULL_WITH_SECONDS,E.DateTime.DATETIME_HUGE,E.DateTime.DATETIME_HUGE_WITH_SECONDS,"f","F","ff","FF"];for(let n of a)if(se(e,n,t))return!0;return!1}#i(e,t){return ne(this.isQaLocale()?this.defaultLocale():e,t)}}class dt extends P{constructor(){super("number")}validate(e){return this.#t(e)||this.isInternationalized(e)}isInternationalized(e){return this.#e(this.currentLocale(),e)}buildConfig(){}#e(e,t){const a=this.getGlobalize(e).numberParser();return!isNaN(a(t))}#t(e){return this.#e(this.defaultLocale(),e)}}class ut extends P{constructor(){super("percentage")}validate(e){return this.#a(e)||this.isInternationalized(e)}isInternationalized(e){return this.#e(this.currentLocale(),e)}buildConfig(){}#e(e,t){if(!this.#r(e,t))return!1;const n=this.#t(t);return!isNaN(this.getGlobalize(e).numberParser()(n))}#t(e=""){return e.replace(new RegExp(`(^(?:${D()})*|(?:${D()})*$)`,"g"),"").replace(/^-/,"").replace(/٪|%/g,"").trim()}#r(e,t){const a="[0-9,. ]+";let n;return["fa-IR","fa-ir"].includes(e)||e.startsWith("ar")?n=new RegExp(`(?:-)?(?:${D()})?(?:٪|%)(?:${D()})?${a}`,"g"):n=new RegExp(`(?:-)?(?:${D()})?${a}(?:${D()})?(?:٪|%)`,"g"),n.test(t)}#a(e){return this.#e(this.defaultLocale(),e)}}class mt extends P{constructor(){super("string")}buildConfig(){const e=c.getOptions();this.addToConfig("mockChars",e?.qaMock),this.addToConfig("resource",c.getResourceBundle(),{}),this.addToConfig("garbledChars",c.getGarbledChars()?.filter(t=>String(t).trim()).filter(Boolean),[])}isInternationalized(e){const t=e.trim().replace(/\s*:\s*$/,""),a=this.getConfig()?.resource?.[this.defaultLocale()];return a?.includes(e)||a?.includes(t)}validate(e){return typeof e=="string"}isDntText(e){return this.getConfig()?.resource?.dnt?.includes(e)}isAutoIgnoredText(e){return this.isDefaultLocale()||this.isUserInputText(e)||this.isEmailText(e)||this.isUrlText(e)}isIgnoredText(e){return this.getConfig()?.resource?.ignore?.includes(e)}isUserInputText(e){return e.startsWith(Se)}isEmailText(e){return ue.EMAIL.test(e)}isUrlText(e){return ue.URL.test(e)}isFullQaLanguageText(e){const t=this.getConfig();return(e.slice(0,2)===t?.mockChars?.prefix||e.slice(0,2)===t?.mockChars?.prefix.toUpperCase())&&e.slice(-2)===t?.mockChars.suffix}isPartialQaLanguageText(e){const t=this.getConfig();return e.slice(0,2)===t?.mockChars.prefix||e.slice(0,2)===t?.mockChars.prefix.toUpperCase()||e.slice(-2)===t?.mockChars.suffix}hasEncodingIssue(e){return this.getConfig()?.garbledChars?.length>0&&this.getConfig().garbledChars.some(t=>e.includes(t))}isPartiallyLocalizedText(e){return this.#e(e)===this.currentLanguage()}#e(e){const t=Object.keys(Ie.detectTextLangEx(e)?.scores||{}).filter(Boolean)||[],a=this.currentLanguage();return t.length?t.includes(a)?a:t[0]:this.defaultLanguage()}isLocalized(e){const t=e.trim().replace(/\s*:\s*$/,""),a=this.getConfig()?.resource?.[this.currentLocale()];return a?.includes(e)||a?.includes(t)}}class pt extends P{constructor(){super("time")}validate(e){return this.#t(e)||this.isInternationalized(e)}isInternationalized(e){return this.#e(this.isQaLocale()?this.defaultLocale():this.currentLocale(),e)}buildConfig(){}#e(e,t){return this.#r(e,t)||this.#a(e,t)||this.#i(e,t)}#t(e){return this.#e(this.defaultLocale(),e)}#r(e,t){const a=["short","medium","long","full"];for(let n of a)if(this.getGlobalize(e).dateParser({time:n})(t))return!0;return!1}#a(e,t){const a=[E.DateTime.TIME_SIMPLE,E.DateTime.TIME_WITH_SECONDS,E.DateTime.TIME_WITH_SHORT_OFFSET,E.DateTime.TIME_WITH_LONG_OFFSET,E.DateTime.TIME_24_SIMPLE,E.DateTime.TIME_24_WITH_LONG_OFFSET,E.DateTime.TIME_24_WITH_SECONDS,E.DateTime.TIME_24_WITH_SHORT_OFFSET,"t","T","tt","TT"];for(let n of a)if(se(e,n,t))return!0;return!1}#i(e,t){return ne(this.isQaLocale()?this.defaultLocale():e,t)}}class y{static#e={};static#t;static#r;static#a;static#i;static#n;static#s;static#o;static load(){y.#t=new mt,y.#r=new dt,y.#a=new lt,y.#i=new pt,y.#n=new ct,y.#s=new st,y.#o=new ut}static getIssueType(e){const t=c.getLocale();if(t){let a=r.UNTRANSLATED;return y.#e[t]||(y.#e[t]={}),y.#e[t][e]?y.#e[t][e]:(this.#t.isAutoIgnoredText(e)?a=r.AUTO_IGNORE:this.#t.isDntText(e)?a=r.DNT:this.#t.isIgnoredText(e)?a=r.IGNORE:this.#t.hasEncodingIssue(e)?a=r.ENCODING_ISSUE:this.#s.validate(e)?a=this.#s.isInternationalized(e)?r.CURRENCY_LOCALIZED:r.CURRENCY_NOT_LOCALIZED:this.#o.validate(e)?a=this.#o.isInternationalized(e)?r.PERCENTAGE_LOCALIZED:r.PERCENTAGE_NOT_LOCALIZED:this.#r.validate(e)?a=this.#r.isInternationalized(e)?r.NUMBER_LOCALIZED:r.NUMBER_NOT_LOCALIZED:this.#a.validate(e)?a=this.#a.isInternationalized(e)?r.DATE_LOCALIZED:r.DATE_NOT_LOCALIZED:this.#i.validate(e)?a=this.#i.isInternationalized(e)?r.TIME_LOCALIZED:r.TIME_NOT_LOCALIZED:this.#n.validate(e)?a=this.#n.isInternationalized(e)?r.DATE_TIME_LOCALIZED:r.DATE_TIME_NOT_LOCALIZED:this.#t.validate(e)?this.#t.isQaLocale()?this.#t.isFullQaLanguageText(e)?a=r.STRING_LOCALIZED:this.#t.isPartialQaLanguageText(e)?a=r.STRING_PARTIALLY_LOCALIZED:a=r.STRING_NOT_LOCALIZED:!this.#t.isDefaultLocale()&&this.#t.isSupportedLocale()&&(this.#t.isLocalized(e)?a=r.STRING_LOCALIZED:this.#t.isPartiallyLocalizedText(e)?a=r.STRING_PARTIALLY_LOCALIZED:this.#t.isInternationalized(e)?a=r.UNTRANSLATED:a=r.STRING_NOT_LOCALIZED):this.#t.isDefaultLocale()&&(a=r.AUTO_IGNORE),y.#e[t][e]=a,a)}return r.UNTRANSLATED}}class Y{static load(){const e={};if(c.getOptions()?.l10nResourcePath){const t=g(process.cwd(),c.getOptions()?.l10nResourcePath);if(x(t))Y.#e(t,e);else if(te(t))for(const a of ae(t)){const n=g(t,a);Y.#e(n,e)}else{console.error(`${t} invalid resource path`);return}c.setResourceBundle(e)}}static#e(e,t){const a=c.getLocale(),n=c.getDefaultLocale(),s=M(e),o=xe(e);if(De.includes(o)){if(!s){console.error(`${e} is empty or invalid`);return}if(e.toLowerCase().includes("dnt"))t.dnt=s.split(/\r?\n/);else if(e.toLowerCase().includes("ignore"))t.ignore=s.split(/\r?\n/);else if(e.includes(a)){const u=s.split(/\r?\n/);t[a]=u.map(gt)}else e.includes(n)&&(t[n]=s.split(/\r?\n/))}}}function gt(i){const e=/<\/?[^>]+>/gi;return i.replace(e,"")}const ht=()=>{c.getDriver()&&!c.isLoaded()&&c.getLocale()&&(c.build(),Y.load(),y.load(),l.setup(),S.init(),c.setIsLoaded(!0))},ve=()=>{let e=process.cwd(),t=0;for(;t<10;){const a=g(e,"package.json");if(x(a)){const n=M(a),s=JSON.parse(n),o={...s?.dependencies||{},...s?.devDependencies||{},...s?.peerDependencies||{}};if(s.name!=="@zeesoft/i18n-verify"&&JSON.stringify(o).includes('"@zeesoft/i18n-verify"'))break}e=Oe(e),t++}return e},we=(i=ve())=>M(g(i,"package.json")),Et=()=>we()?.match(/"name": "([^"]+)",/)?.[1]||"",ft=()=>g(process.cwd(),C),vt=(i="")=>`{
3599
- "appName": "${Et()}",
3600
- "type": "${i}", // set automation framework type ${fe(Object.values(z))}
4020
+ })();`;
4021
+ const getJsData = (metaData) => `${global()}
4022
+ ${data(metaData)}
4023
+ ${menuBar()}
4024
+ ${overview()}
4025
+ ${insight()}
4026
+ ${localeGrid()}
4027
+ ${log()}`;
4028
+ class HtmlReport extends BaseReport {
4029
+ constructor() {
4030
+ super(SUPPORTED_REPORT_TYPES.HTML);
4031
+ }
4032
+ buildContent() {
4033
+ const metaInfo = this.getMetaInfo(), script = getJsData(metaInfo), style = getCssData(), body = getBodyData(), dataFilePaths = [], logDataFilePath = joinPaths(Reports.getReportPath(), "logs", "log"), captureAll = Config.isSanityRun() || Config.isContextRun(), expectedLocaleDirs = [
4034
+ Config.getQALocale(),
4035
+ ...Config.getOptions()?.supportedLocales || []
4036
+ ].filter(Boolean).map((v) => toFileNameFormat(v)), localeDirs = getDirContents(Reports.getReportPath()).filter(
4037
+ (v) => expectedLocaleDirs.includes(v)
4038
+ ), includeDefaultLocaleDir = localeDirs.length === 1 && localeDirs[0] === toFileNameFormat(Config.getDefaultLocale());
4039
+ let logData = "";
4040
+ localeDirs.forEach(
4041
+ (file) => (captureAll || file !== metaInfo.defaultLocale || file === metaInfo.defaultLocale && includeDefaultLocaleDir) && fileExists(joinPaths(Reports.getReportPath(), file, CACHE_FILE_NAME)) && dataFilePaths.push(joinPaths(file, CACHE_FILE_NAME).replace(/\\/g, "/"))
4042
+ );
4043
+ if (fileExists(logDataFilePath)) {
4044
+ const paths = [
4045
+ metaInfo.appName,
4046
+ ...Config.getL10nReportsPath().split(/[\\/]+/g),
4047
+ Config.getMode()
4048
+ ];
4049
+ paths.push(Reports.getReportTimeStamp());
4050
+ logData = getFileContent(logDataFilePath).replace(
4051
+ new RegExp(Reports.getReportPath().replace(/\\/g, "\\\\"), "g"),
4052
+ joinPaths(...paths)
4053
+ ).replace(/\\/g, "\\\\").replace(/`/g, "\\`");
4054
+ }
4055
+ return renderHtml({
4056
+ appName: metaInfo.appName,
4057
+ reportTime: metaInfo.reportTime,
4058
+ body,
4059
+ script,
4060
+ style,
4061
+ dataFilePaths,
4062
+ logData
4063
+ });
4064
+ }
4065
+ write(path2, name, data2) {
4066
+ saveToFile(joinPaths(path2, `${name}.html`), data2, "utf-8");
4067
+ }
4068
+ }
4069
+ class TableReport extends BaseReport {
4070
+ /**
4071
+ * @type {Table}
4072
+ */
4073
+ #printer;
4074
+ /**
4075
+ * @type {Boolean}
4076
+ */
4077
+ #hasData = false;
4078
+ static #column1 = "STATUS";
4079
+ static #column2 = "COUNTS";
4080
+ constructor() {
4081
+ super(SUPPORTED_REPORT_TYPES.ASCII_TABLE);
4082
+ this.#preparePrinter();
4083
+ }
4084
+ #preparePrinter() {
4085
+ this.#printer = new Table({
4086
+ style: {
4087
+ headerTop: {
4088
+ left: "\x1B[94m╔\x1B[0m",
4089
+ mid: "\x1B[94m╦\x1B[0m",
4090
+ right: "\x1B[94m╗\x1B[0m",
4091
+ other: "\x1B[94m═"
4092
+ },
4093
+ headerBottom: {
4094
+ left: "\x1B[94m╟\x1B[0m",
4095
+ mid: "\x1B[94m╬\x1B[0m",
4096
+ right: "\x1B[94m╢\x1B[0m",
4097
+ other: "\x1B[94m═"
4098
+ },
4099
+ tableBottom: {
4100
+ left: "\x1B[94m╚\x1B[0m",
4101
+ mid: "\x1B[94m╩\x1B[0m",
4102
+ right: "\x1B[94m╝\x1B[0m",
4103
+ other: "\x1B[94m═\x1B[0m"
4104
+ },
4105
+ vertical: "\x1B[94m║\x1B[0m"
4106
+ },
4107
+ columns: [
4108
+ { name: TableReport.#column1, alignment: "left" },
4109
+ { name: TableReport.#column2, alignment: "center" }
4110
+ ]
4111
+ });
4112
+ }
4113
+ /**
4114
+ * @override
4115
+ */
4116
+ buildContent() {
4117
+ if (REPORT_COUNTS[I18N_STATUS.REVIEWED] > 0) {
4118
+ this.#hasData = true;
4119
+ for (const key in REPORT_COUNTS) {
4120
+ if (key !== I18N_STATUS.REVIEWED) {
4121
+ if (REPORT_COUNTS.hasOwnProperty(key)) {
4122
+ this.#printer.addRows([
4123
+ { STATUS: key, COUNTS: `${REPORT_COUNTS[key]}` }
4124
+ ]);
4125
+ }
4126
+ } else {
4127
+ this.#printer.addRows([
4128
+ {
4129
+ STATUS: "\x1B[94m" + "═".repeat(28) + "\x1B[0m",
4130
+ COUNTS: "\x1B[94m" + "═".repeat(8) + "\x1B[0m"
4131
+ }
4132
+ ]);
4133
+ this.#printer.addRows([
4134
+ { STATUS: "OVERALL_REVIEWED", COUNTS: `${REPORT_COUNTS[key]}` }
4135
+ ]);
4136
+ }
4137
+ }
4138
+ }
4139
+ }
4140
+ /**
4141
+ * @override
4142
+ */
4143
+ export() {
4144
+ this.#hasData ? this.#printer.printTable() : Logger$1.info("There are no visbile elements with UI strings");
4145
+ }
4146
+ }
4147
+ class ReportFactory {
4148
+ static #build(type) {
4149
+ switch (type) {
4150
+ case SUPPORTED_REPORT_TYPES.HTML:
4151
+ return new HtmlReport();
4152
+ case SUPPORTED_REPORT_TYPES.ASCII_TABLE:
4153
+ return new TableReport();
4154
+ default:
4155
+ throw new Error("unsupported report type requested");
4156
+ }
4157
+ }
4158
+ static export(type, path2, name) {
4159
+ const builder = ReportFactory.#build(type);
4160
+ const reportData = new ReportData({
4161
+ appName: Config.getAppName(),
4162
+ reportTime: (/* @__PURE__ */ new Date()).toLocaleString(),
4163
+ isContext: Config.isContextRun(),
4164
+ isSanity: Config.isSanityRun(),
4165
+ defaultLocale: Config.getDefaultLocale(),
4166
+ reportFolderTimestamp: Reports.getReportTimeStamp()
4167
+ });
4168
+ builder.generate(reportData);
4169
+ builder.export(path2, name);
4170
+ }
4171
+ }
4172
+ class Cache {
4173
+ /** @type {String} */
4174
+ static #cachePath;
4175
+ static #cacheDirPath;
4176
+ static init() {
4177
+ Cache.#cacheDirPath = joinPaths(
4178
+ Reports.getReportPath(),
4179
+ toFileNameFormat(Config.getLocale())
4180
+ );
4181
+ Cache.#cachePath = joinPaths(Cache.#cacheDirPath, CACHE_FILE_NAME);
4182
+ this.#ensureFileExists();
4183
+ }
4184
+ static exists() {
4185
+ return fileExists(Cache.#cachePath);
4186
+ }
4187
+ static save(data2) {
4188
+ this.#ensureFileExists();
4189
+ const source = `!window.rawData && (window.rawData={'${Config.getLocale()}':{}});window.rawData['${Config.getLocale()}']=${JSON.stringify(
4190
+ data2
4191
+ )};`;
4192
+ saveToFile(Cache.#cachePath, source);
4193
+ }
4194
+ static getData() {
4195
+ if (!this.exists()) {
4196
+ return {};
4197
+ } else {
4198
+ try {
4199
+ return JSON.parse(
4200
+ getFileContent(Cache.#cachePath).replace(
4201
+ new RegExp(
4202
+ `(\\!window.rawData && \\(window\\.rawData=\\{'${Config.getLocale()}':\\{\\}\\}\\);window\\.rawData\\['${Config.getLocale()}'\\]=)|(;$)`,
4203
+ "g"
4204
+ ),
4205
+ ""
4206
+ )
4207
+ );
4208
+ } catch (ex) {
4209
+ return {};
4210
+ }
4211
+ }
4212
+ }
4213
+ static #ensureFileExists() {
4214
+ ensureDirectoryExists(Cache.#cacheDirPath);
4215
+ }
4216
+ static getCacheDirPath() {
4217
+ return Cache.#cacheDirPath;
4218
+ }
4219
+ }
4220
+ class StatData {
4221
+ /**
4222
+ * @type {Number}
4223
+ */
4224
+ #localizedStrings;
4225
+ /**
4226
+ * @type {Number}
4227
+ */
4228
+ #notLocalizedStrings;
4229
+ /**
4230
+ * @type {Number}
4231
+ */
4232
+ #untranslatedStrings;
4233
+ /**
4234
+ * @type {Number}
4235
+ */
4236
+ #partialStrings;
4237
+ /**
4238
+ * @type {Number}
4239
+ */
4240
+ #localizedDateTime;
4241
+ /**
4242
+ * @type {Number}
4243
+ */
4244
+ #localizedDate;
4245
+ /**
4246
+ * @type {Number}
4247
+ */
4248
+ #localizedTime;
4249
+ /**
4250
+ * @type {Number}
4251
+ */
4252
+ #notLocalizedDateTime;
4253
+ /**
4254
+ * @type {Number}
4255
+ */
4256
+ #notLocalizedDate;
4257
+ /**
4258
+ * @type {Number}
4259
+ */
4260
+ #notLocalizedTime;
4261
+ /**
4262
+ * @type {Number}
4263
+ */
4264
+ #localizedNumber;
4265
+ /**
4266
+ * @type {Number}
4267
+ */
4268
+ #notLocalizedNumber;
4269
+ /**
4270
+ * @type {Number}
4271
+ */
4272
+ #localizedCurrency;
4273
+ /**
4274
+ * @type {Number}
4275
+ */
4276
+ #notLocalizedCurrency;
4277
+ /**
4278
+ * @type {Number}
4279
+ */
4280
+ #localizedPercentage;
4281
+ /**
4282
+ * @type {Number}
4283
+ */
4284
+ #notLocalizedPercentage;
4285
+ /**
4286
+ * @type {Number}
4287
+ */
4288
+ #ignored;
4289
+ /**
4290
+ * @type {Number}
4291
+ */
4292
+ #dnt;
4293
+ /**
4294
+ * @type {Number}
4295
+ */
4296
+ #autoIgnored;
4297
+ /**
4298
+ * @type {Number}
4299
+ */
4300
+ #userInput;
4301
+ /**
4302
+ * @type {Number}
4303
+ */
4304
+ #encoding;
4305
+ /**
4306
+ * @type {Number}
4307
+ */
4308
+ #truncation;
4309
+ /**
4310
+ * @type {Number}
4311
+ */
4312
+ #overlapping;
4313
+ /**
4314
+ * @type {Number}
4315
+ */
4316
+ #reviewed;
4317
+ /**
4318
+ * @type {Number}
4319
+ */
4320
+ #context;
4321
+ constructor(data2 = {}) {
4322
+ this.#localizedStrings = data2?.localizedStrings || 0;
4323
+ this.#notLocalizedStrings = data2?.notLocalizedStrings || 0;
4324
+ this.#untranslatedStrings = data2?.untranslatedStrings || 0;
4325
+ this.#partialStrings = data2?.partialStrings || 0;
4326
+ this.#localizedDateTime = data2?.localizedDateTime || 0;
4327
+ this.#localizedDate = data2?.localizedDate || 0;
4328
+ this.#localizedTime = data2?.localizedTime || 0;
4329
+ this.#notLocalizedDateTime = data2?.notLocalizedDateTime || 0;
4330
+ this.#notLocalizedDate = data2?.notLocalizedDate || 0;
4331
+ this.#notLocalizedTime = data2?.notLocalizedTime || 0;
4332
+ this.#localizedNumber = data2?.localizedNumber || 0;
4333
+ this.#notLocalizedNumber = data2?.notLocalizedNumber || 0;
4334
+ this.#localizedCurrency = data2?.localizedCurrency || 0;
4335
+ this.#notLocalizedCurrency = data2?.notLocalizedCurrency || 0;
4336
+ this.#localizedPercentage = data2?.localizedPercentage || 0;
4337
+ this.#notLocalizedPercentage = data2?.notLocalizedPercentage || 0;
4338
+ this.#ignored = data2?.ignored || 0;
4339
+ this.#dnt = data2?.dnt || 0;
4340
+ this.#autoIgnored = data2?.autoIgnored || 0;
4341
+ this.#userInput = data2?.userInput || 0;
4342
+ this.#encoding = data2?.encoding || 0;
4343
+ this.#truncation = data2?.truncation || 0;
4344
+ this.#overlapping = data2?.overlapping || 0;
4345
+ this.#reviewed = data2?.reviewed || 0;
4346
+ this.#context = data2?.context || 0;
4347
+ }
4348
+ getLocalizedStrings() {
4349
+ return this.#localizedStrings;
4350
+ }
4351
+ setLocalizedStrings(translatedStrings) {
4352
+ this.#localizedStrings = translatedStrings;
4353
+ }
4354
+ getUntranslatedStrings() {
4355
+ return this.#untranslatedStrings;
4356
+ }
4357
+ setUntranslatedStrings(untranslatedStrings) {
4358
+ this.#untranslatedStrings = untranslatedStrings;
4359
+ }
4360
+ getNotLocalizedStrings() {
4361
+ return this.#notLocalizedStrings;
4362
+ }
4363
+ setNotLocalizedStrings(notLocalizedStrings) {
4364
+ this.#notLocalizedStrings = notLocalizedStrings;
4365
+ }
4366
+ getPartialStrings() {
4367
+ return this.#partialStrings;
4368
+ }
4369
+ setPartialStrings(partialStrings) {
4370
+ this.#partialStrings = partialStrings;
4371
+ }
4372
+ getLocalizedDateTime() {
4373
+ return this.#localizedDateTime;
4374
+ }
4375
+ setLocalizedDateTime(localizedDateTime) {
4376
+ this.#localizedDateTime = localizedDateTime;
4377
+ }
4378
+ getLocalizedDate() {
4379
+ return this.#localizedDate;
4380
+ }
4381
+ setLocalizedDate(localizedDate) {
4382
+ this.#localizedDate = localizedDate;
4383
+ }
4384
+ getLocalizedTime() {
4385
+ return this.#localizedTime;
4386
+ }
4387
+ setLocalizedTime(localizedTime) {
4388
+ this.#localizedTime = localizedTime;
4389
+ }
4390
+ getNotLocalizedDateTime() {
4391
+ return this.#notLocalizedDateTime;
4392
+ }
4393
+ setNotLocalizedDateTime(notLocalizedDateTime) {
4394
+ this.#notLocalizedDateTime = notLocalizedDateTime;
4395
+ }
4396
+ getNotLocalizedDate() {
4397
+ return this.#notLocalizedDate;
4398
+ }
4399
+ setNotLocalizedDate(notLocalizedDate) {
4400
+ this.#notLocalizedDate = notLocalizedDate;
4401
+ }
4402
+ getNotLocalizedTime() {
4403
+ return this.#notLocalizedTime;
4404
+ }
4405
+ setNotLocalizedTime(notLocalizedTime) {
4406
+ this.#notLocalizedTime = notLocalizedTime;
4407
+ }
4408
+ getLocalizedNumber() {
4409
+ return this.#localizedNumber;
4410
+ }
4411
+ setLocalizedNumber(localizedNumber) {
4412
+ this.#localizedNumber = localizedNumber;
4413
+ }
4414
+ getNotLocalizeNumber() {
4415
+ return this.#notLocalizedNumber;
4416
+ }
4417
+ setNotLocalizeNumber(notLocalizedNumber) {
4418
+ this.#notLocalizedNumber = notLocalizedNumber;
4419
+ }
4420
+ getCurrency() {
4421
+ return this.#localizedCurrency;
4422
+ }
4423
+ setCurrency(currency) {
4424
+ this.#localizedCurrency = currency;
4425
+ }
4426
+ getNotLocalizeCurrency() {
4427
+ return this.#notLocalizedCurrency;
4428
+ }
4429
+ setNotLocalizeCurrency(notLocalizedCurrency) {
4430
+ this.#notLocalizedCurrency = notLocalizedCurrency;
4431
+ }
4432
+ getPercentage() {
4433
+ return this.#localizedPercentage;
4434
+ }
4435
+ setPercentage(percentage) {
4436
+ this.#localizedPercentage = percentage;
4437
+ }
4438
+ getNotLocalizePercentage() {
4439
+ return this.#notLocalizedPercentage;
4440
+ }
4441
+ setNotLocalizePercentage(notLocalizedPercentage) {
4442
+ this.#notLocalizedPercentage = notLocalizedPercentage;
4443
+ }
4444
+ getIgnored() {
4445
+ return this.#ignored;
4446
+ }
4447
+ setIgnored(ignored) {
4448
+ this.#ignored = ignored;
4449
+ }
4450
+ getUserInput() {
4451
+ return this.#userInput;
4452
+ }
4453
+ setUserInput(userInput) {
4454
+ this.#userInput = userInput;
4455
+ }
4456
+ getDnt() {
4457
+ return this.#dnt;
4458
+ }
4459
+ setDnt(dnt) {
4460
+ this.#dnt = dnt;
4461
+ }
4462
+ getAutoIgnored() {
4463
+ return this.#autoIgnored;
4464
+ }
4465
+ setAutoIgnored(autoIgnored) {
4466
+ this.#autoIgnored = autoIgnored;
4467
+ }
4468
+ getEncoding() {
4469
+ return this.#encoding;
4470
+ }
4471
+ setEncoding(encoding) {
4472
+ this.#encoding = encoding;
4473
+ }
4474
+ getTruncation() {
4475
+ return this.#truncation;
4476
+ }
4477
+ setTruncation(truncation) {
4478
+ this.#truncation = truncation;
4479
+ }
4480
+ getOverlapping() {
4481
+ return this.#overlapping;
4482
+ }
4483
+ setOverlapping(overlapping) {
4484
+ this.#overlapping = overlapping;
4485
+ }
4486
+ getReviewed() {
4487
+ return this.#reviewed;
4488
+ }
4489
+ setReviewed(reviewed) {
4490
+ this.#reviewed = reviewed;
4491
+ }
4492
+ getContext() {
4493
+ return this.#context;
4494
+ }
4495
+ setContext(context) {
4496
+ this.#context = context;
4497
+ }
4498
+ incrementByType(type) {
4499
+ switch (type) {
4500
+ case I18N_STATUS.STRING_LOCALIZED:
4501
+ ++this.#localizedStrings;
4502
+ break;
4503
+ case I18N_STATUS.STRING_NOT_LOCALIZED:
4504
+ ++this.#notLocalizedStrings;
4505
+ break;
4506
+ case I18N_STATUS.UNTRANSLATED:
4507
+ ++this.#untranslatedStrings;
4508
+ break;
4509
+ case I18N_STATUS.STRING_PARTIALLY_LOCALIZED:
4510
+ ++this.#partialStrings;
4511
+ break;
4512
+ case I18N_STATUS.AUTO_IGNORE:
4513
+ ++this.#autoIgnored;
4514
+ break;
4515
+ case I18N_STATUS.IGNORE:
4516
+ ++this.#ignored;
4517
+ break;
4518
+ case I18N_STATUS.DNT:
4519
+ ++this.#dnt;
4520
+ break;
4521
+ case I18N_STATUS.ENCODING_ISSUE:
4522
+ ++this.#encoding;
4523
+ break;
4524
+ case I18N_STATUS.DATE_LOCALIZED:
4525
+ ++this.#localizedDate;
4526
+ break;
4527
+ case I18N_STATUS.TIME_LOCALIZED:
4528
+ ++this.#localizedTime;
4529
+ break;
4530
+ case I18N_STATUS.DATE_TIME_LOCALIZED:
4531
+ ++this.#localizedDateTime;
4532
+ break;
4533
+ case I18N_STATUS.DATE_NOT_LOCALIZED:
4534
+ ++this.#notLocalizedDate;
4535
+ break;
4536
+ case I18N_STATUS.TIME_NOT_LOCALIZED:
4537
+ ++this.#notLocalizedTime;
4538
+ break;
4539
+ case I18N_STATUS.DATE_TIME_NOT_LOCALIZED:
4540
+ ++this.#notLocalizedDateTime;
4541
+ break;
4542
+ case I18N_STATUS.NUMBER_LOCALIZED:
4543
+ ++this.#localizedNumber;
4544
+ break;
4545
+ case I18N_STATUS.NUMBER_NOT_LOCALIZED:
4546
+ ++this.#notLocalizedNumber;
4547
+ break;
4548
+ case I18N_STATUS.CURRENCY_LOCALIZED:
4549
+ ++this.#localizedCurrency;
4550
+ break;
4551
+ case I18N_STATUS.CURRENCY_NOT_LOCALIZED:
4552
+ ++this.#notLocalizedCurrency;
4553
+ break;
4554
+ case I18N_STATUS.PERCENTAGE_LOCALIZED:
4555
+ ++this.#localizedPercentage;
4556
+ break;
4557
+ case I18N_STATUS.PERCENTAGE_NOT_LOCALIZED:
4558
+ ++this.#notLocalizedPercentage;
4559
+ break;
4560
+ case I18N_STATUS.TRUNCATION_ISSUE:
4561
+ ++this.#truncation;
4562
+ break;
4563
+ case I18N_STATUS.OVERLAPPING_ISSUE:
4564
+ ++this.#overlapping;
4565
+ break;
4566
+ case I18N_STATUS.REVIEWED:
4567
+ ++this.#reviewed;
4568
+ break;
4569
+ case I18N_STATUS.USER_INPUT:
4570
+ ++this.#userInput;
4571
+ break;
4572
+ case "context":
4573
+ ++this.#context;
4574
+ break;
4575
+ }
4576
+ }
4577
+ toJSON() {
4578
+ return {
4579
+ localizedStrings: this.#localizedStrings,
4580
+ notLocalizedStrings: this.#notLocalizedStrings,
4581
+ untranslatedStrings: this.#untranslatedStrings,
4582
+ partialStrings: this.#partialStrings,
4583
+ localizedDateTime: this.#localizedDateTime,
4584
+ localizedDate: this.#localizedDate,
4585
+ localizedTime: this.#localizedTime,
4586
+ notLocalizedDateTime: this.#notLocalizedDateTime,
4587
+ notLocalizedDate: this.#notLocalizedDate,
4588
+ notLocalizedTime: this.#notLocalizedTime,
4589
+ localizedNumber: this.#localizedNumber,
4590
+ notLocalizedNumber: this.#notLocalizedNumber,
4591
+ localizedCurrency: this.#localizedCurrency,
4592
+ notLocalizedCurrency: this.#notLocalizedCurrency,
4593
+ localizedPercentage: this.#localizedPercentage,
4594
+ notLocalizedPercentage: this.#notLocalizedPercentage,
4595
+ ignored: this.#ignored,
4596
+ dnt: this.#dnt,
4597
+ autoIgnored: this.#autoIgnored,
4598
+ userInput: this.#userInput,
4599
+ encoding: this.#encoding,
4600
+ truncation: this.#truncation,
4601
+ overlapping: this.#overlapping,
4602
+ reviewed: this.#reviewed,
4603
+ context: this.#context
4604
+ };
4605
+ }
4606
+ }
4607
+ class MetaData {
4608
+ /**
4609
+ * @type {StatData}
4610
+ */
4611
+ #stats;
4612
+ constructor(data2 = {}) {
4613
+ this.#stats = new StatData(data2.stats);
4614
+ }
4615
+ getStats() {
4616
+ return this.#stats;
4617
+ }
4618
+ setStats(stats) {
4619
+ this.#stats = stats;
4620
+ }
4621
+ toJSON() {
4622
+ return {
4623
+ stats: this.#stats
4624
+ };
4625
+ }
4626
+ }
4627
+ class StringInfo {
4628
+ /**
4629
+ * @type {String}
4630
+ */
4631
+ #type;
4632
+ /**
4633
+ * @type {String}
4634
+ */
4635
+ #imagePath;
4636
+ /**
4637
+ * @type {String}
4638
+ */
4639
+ #description;
4640
+ constructor(data2) {
4641
+ this.#type = data2?.type || "";
4642
+ this.#imagePath = data2?.imagePath || "";
4643
+ this.#description = data2?.description || "";
4644
+ }
4645
+ getType() {
4646
+ return this.#type;
4647
+ }
4648
+ setType(type) {
4649
+ this.#type = type;
4650
+ }
4651
+ getImagePath() {
4652
+ return this.#imagePath;
4653
+ }
4654
+ setImagePath(imagePath) {
4655
+ this.#imagePath = imagePath;
4656
+ }
4657
+ getDescription() {
4658
+ return this.#description;
4659
+ }
4660
+ setDescription(description) {
4661
+ this.#description = description;
4662
+ }
4663
+ toJSON() {
4664
+ return {
4665
+ type: this.#type,
4666
+ description: this.#description,
4667
+ imagePath: this.#imagePath
4668
+ };
4669
+ }
4670
+ }
4671
+ class StringData {
4672
+ /**
4673
+ * @type {{[key: string]: StringInfo[]}}
4674
+ */
4675
+ #data = {};
4676
+ constructor(data2) {
4677
+ if (data2) {
4678
+ for (const string in data2) {
4679
+ data2[string].forEach((info) => {
4680
+ if (!this.#data[string]) {
4681
+ this.#data[string] = [];
4682
+ }
4683
+ this.#data[string].push(new StringInfo(info));
4684
+ });
4685
+ }
4686
+ }
4687
+ }
4688
+ getStringData(string) {
4689
+ return this.#data[string] || [];
4690
+ }
4691
+ setStringData(string, info) {
4692
+ !this.#data[string] && (this.#data[string] = []);
4693
+ this.#data[string].push(new StringInfo(info));
4694
+ return true;
4695
+ }
4696
+ checkAndAdd(string, info) {
4697
+ !this.#data[string] && (this.#data[string] = []);
4698
+ const canAdd = this.getStringData(string).some(
4699
+ (data2) => data2.getDescription() !== info.description || data2.getImagePath() !== info.imagePath || data2.getType() !== data2.type
4700
+ );
4701
+ if (canAdd) {
4702
+ this.setStringData(string, info);
4703
+ }
4704
+ return canAdd;
4705
+ }
4706
+ hasStringData(string) {
4707
+ return string in this.#data;
4708
+ }
4709
+ /**
4710
+ *
4711
+ * @param {String} string
4712
+ * @param {Object[] | Object} info
4713
+ * @returns {StringData}
4714
+ */
4715
+ static createNew(string, info) {
4716
+ info = Array.isArray(info) ? info : [info];
4717
+ return new StringData({ data: { [string]: info } });
4718
+ }
4719
+ toJSON() {
4720
+ return this.#data;
4721
+ }
4722
+ }
4723
+ class CacheData {
4724
+ /**
4725
+ * @type {MetaData}
4726
+ */
4727
+ #metaData;
4728
+ /**
4729
+ * @type {StringData}
4730
+ */
4731
+ #stringsData;
4732
+ constructor(data2 = {}) {
4733
+ this.#metaData = new MetaData(data2.metaData);
4734
+ this.#stringsData = new StringData(data2.stringsData);
4735
+ }
4736
+ getMetaData() {
4737
+ return this.#metaData;
4738
+ }
4739
+ setMetaData(metaData) {
4740
+ this.#metaData = metaData;
4741
+ }
4742
+ getStringEntry(string) {
4743
+ return this.#stringsData.getStringData(string);
4744
+ }
4745
+ static addString(string, type, description, imagePath) {
4746
+ const cache = CacheData.getInstance();
4747
+ const added = cache.#addStringEntry(
4748
+ string,
4749
+ type,
4750
+ description,
4751
+ imagePath.replace(/\\/g, "/")
4752
+ );
4753
+ added && cache.save();
4754
+ return added;
4755
+ }
4756
+ #addStringEntry(string, type, description, imagePath) {
4757
+ let dataAdded = false;
4758
+ const info = {
4759
+ type,
4760
+ description,
4761
+ imagePath
4762
+ };
4763
+ if (!this.#stringsData.hasStringData(string)) {
4764
+ dataAdded = this.#stringsData.setStringData(string, info);
4765
+ } else {
4766
+ dataAdded = this.#stringsData.checkAndAdd(string, info);
4767
+ }
4768
+ if (dataAdded) {
4769
+ this.#metaData.getStats().incrementByType(type);
4770
+ }
4771
+ return dataAdded;
4772
+ }
4773
+ static incrementCountByType(type) {
4774
+ const cache = CacheData.getInstance();
4775
+ cache.#metaData.getStats().incrementByType(type);
4776
+ cache.save();
4777
+ }
4778
+ toJSON() {
4779
+ return {
4780
+ metaData: this.#metaData,
4781
+ stringsData: this.#stringsData
4782
+ };
4783
+ }
4784
+ save() {
4785
+ Cache.save(this);
4786
+ }
4787
+ remove() {
4788
+ Cache.delete();
4789
+ }
4790
+ static getInstance() {
4791
+ return new CacheData(Cache.getData());
4792
+ }
4793
+ }
4794
+ class Reports {
4795
+ static #baseReportPath;
4796
+ static #reportTimeStamp;
4797
+ static setup() {
4798
+ if (!Reports.#reportTimeStamp) {
4799
+ Reports.#reportTimeStamp = Reports.#dateTime();
4800
+ }
4801
+ const rootFolder = path.resolve();
4802
+ Reports.#baseReportPath = joinPaths(
4803
+ rootFolder,
4804
+ Config.getL10nReportsPath(),
4805
+ Config.getMode(),
4806
+ Reports.#reportTimeStamp
4807
+ );
4808
+ }
4809
+ static getReportTimeStamp() {
4810
+ return Reports.#reportTimeStamp;
4811
+ }
4812
+ static getReportPath() {
4813
+ return Reports.#baseReportPath;
4814
+ }
4815
+ static reviewedReports(str = null, imgName = null) {
4816
+ return Reports.#generateFullReportPath(I18N_STATUS.REVIEWED, str, imgName);
4817
+ }
4818
+ static getContextPath() {
4819
+ return this.#generateContextReportPath();
4820
+ }
4821
+ static [I18N_STATUS.STRING_LOCALIZED](str, imgName) {
4822
+ return Reports.#generateFullReportPath(
4823
+ I18N_STATUS.STRING_LOCALIZED,
4824
+ str,
4825
+ imgName
4826
+ );
4827
+ }
4828
+ static [I18N_STATUS.STRING_NOT_LOCALIZED](str, imgName) {
4829
+ return Reports.#generateFullReportPath(
4830
+ I18N_STATUS.STRING_NOT_LOCALIZED,
4831
+ str,
4832
+ imgName
4833
+ );
4834
+ }
4835
+ static [I18N_STATUS.STRING_PARTIALLY_LOCALIZED](str, imgName) {
4836
+ return Reports.#generateFullReportPath(
4837
+ I18N_STATUS.STRING_PARTIALLY_LOCALIZED,
4838
+ str,
4839
+ imgName
4840
+ );
4841
+ }
4842
+ static [I18N_STATUS.DNT](str, imgName) {
4843
+ return Reports.#generateFullReportPath(I18N_STATUS.DNT, str, imgName);
4844
+ }
4845
+ static [I18N_STATUS.IGNORE](str, imgName) {
4846
+ return Reports.#generateFullReportPath(I18N_STATUS.IGNORE, str, imgName);
4847
+ }
4848
+ static [I18N_STATUS.AUTO_IGNORE](str, imgName) {
4849
+ return Reports.#generateFullReportPath(
4850
+ I18N_STATUS.AUTO_IGNORE,
4851
+ str,
4852
+ imgName
4853
+ );
4854
+ }
4855
+ static [I18N_STATUS.UNTRANSLATED](str, imgName) {
4856
+ return Reports.#generateFullReportPath(
4857
+ I18N_STATUS.UNTRANSLATED,
4858
+ str,
4859
+ imgName
4860
+ );
4861
+ }
4862
+ static [I18N_STATUS.ENCODING_ISSUE](str, imgName) {
4863
+ return Reports.#generateFullReportPath(
4864
+ I18N_STATUS.ENCODING_ISSUE,
4865
+ str,
4866
+ imgName
4867
+ );
4868
+ }
4869
+ static [I18N_STATUS.DATE_TIME_LOCALIZED](str, imgName) {
4870
+ return Reports.#generateFullReportPath(
4871
+ I18N_STATUS.DATE_TIME_LOCALIZED,
4872
+ str,
4873
+ imgName
4874
+ );
4875
+ }
4876
+ static [I18N_STATUS.DATE_TIME_NOT_LOCALIZED](str, imgName) {
4877
+ return Reports.#generateFullReportPath(
4878
+ I18N_STATUS.DATE_TIME_NOT_LOCALIZED,
4879
+ str,
4880
+ imgName
4881
+ );
4882
+ }
4883
+ static [I18N_STATUS.DATE_LOCALIZED](str, imgName) {
4884
+ return Reports.#generateFullReportPath(
4885
+ I18N_STATUS.DATE_LOCALIZED,
4886
+ str,
4887
+ imgName
4888
+ );
4889
+ }
4890
+ static [I18N_STATUS.DATE_NOT_LOCALIZED](str, imgName) {
4891
+ return Reports.#generateFullReportPath(
4892
+ I18N_STATUS.DATE_NOT_LOCALIZED,
4893
+ str,
4894
+ imgName
4895
+ );
4896
+ }
4897
+ static [I18N_STATUS.TIME_LOCALIZED](str, imgName) {
4898
+ return Reports.#generateFullReportPath(
4899
+ I18N_STATUS.TIME_LOCALIZED,
4900
+ str,
4901
+ imgName
4902
+ );
4903
+ }
4904
+ static [I18N_STATUS.TIME_NOT_LOCALIZED](str, imgName) {
4905
+ return Reports.#generateFullReportPath(
4906
+ I18N_STATUS.TIME_NOT_LOCALIZED,
4907
+ str,
4908
+ imgName
4909
+ );
4910
+ }
4911
+ static [I18N_STATUS.CURRENCY_LOCALIZED](str, imgName) {
4912
+ return Reports.#generateFullReportPath(
4913
+ I18N_STATUS.CURRENCY_LOCALIZED,
4914
+ str,
4915
+ imgName
4916
+ );
4917
+ }
4918
+ static [I18N_STATUS.CURRENCY_NOT_LOCALIZED](str, imgName) {
4919
+ return Reports.#generateFullReportPath(
4920
+ I18N_STATUS.CURRENCY_NOT_LOCALIZED,
4921
+ str,
4922
+ imgName
4923
+ );
4924
+ }
4925
+ static [I18N_STATUS.PERCENTAGE_LOCALIZED](str, imgName) {
4926
+ return Reports.#generateFullReportPath(
4927
+ I18N_STATUS.PERCENTAGE_LOCALIZED,
4928
+ str,
4929
+ imgName
4930
+ );
4931
+ }
4932
+ static [I18N_STATUS.PERCENTAGE_NOT_LOCALIZED](str, imgName) {
4933
+ return Reports.#generateFullReportPath(
4934
+ I18N_STATUS.PERCENTAGE_NOT_LOCALIZED,
4935
+ str,
4936
+ imgName
4937
+ );
4938
+ }
4939
+ static [I18N_STATUS.NUMBER_LOCALIZED](str, imgName) {
4940
+ return Reports.#generateFullReportPath(
4941
+ I18N_STATUS.NUMBER_LOCALIZED,
4942
+ str,
4943
+ imgName
4944
+ );
4945
+ }
4946
+ static [I18N_STATUS.NUMBER_NOT_LOCALIZED](str, imgName) {
4947
+ return Reports.#generateFullReportPath(
4948
+ I18N_STATUS.NUMBER_NOT_LOCALIZED,
4949
+ str,
4950
+ imgName
4951
+ );
4952
+ }
4953
+ static incrementCount(type, str, imgPath, desc) {
4954
+ if (REPORT_COUNTS.hasOwnProperty(type)) {
4955
+ REPORT_COUNTS[type]++;
4956
+ CacheData.addString(
4957
+ str,
4958
+ type,
4959
+ desc,
4960
+ imgPath.replace(Reports.#baseReportPath, "")
4961
+ );
4962
+ }
4963
+ }
4964
+ static #dateTime() {
4965
+ const now = /* @__PURE__ */ new Date();
4966
+ const year = now.getFullYear();
4967
+ const month = String(now.getMonth() + 1).padStart(2, "0");
4968
+ const day = String(now.getDate()).padStart(2, "0");
4969
+ const hours = String(now.getHours()).padStart(2, "0");
4970
+ const minutes = String(now.getMinutes()).padStart(2, "0");
4971
+ const timeStamp = `${year}-${month}-${day}-${hours}-${minutes}`;
4972
+ return timeStamp;
4973
+ }
4974
+ static #generateFullReportPath = (type, str, imgName) => {
4975
+ const _screenshotPath = joinPaths(
4976
+ Reports.#baseReportPath,
4977
+ toFileNameFormat(Config.getLocale()),
4978
+ "screenshots",
4979
+ String(type).toLowerCase()
4980
+ );
4981
+ ensureDirectoryExists(_screenshotPath, DEBUG_MODE);
4982
+ if (str !== null && str !== void 0) {
4983
+ const _stringsPath = joinPaths(
4984
+ Reports.#baseReportPath,
4985
+ toFileNameFormat(Config.getLocale()),
4986
+ "strings"
4987
+ );
4988
+ ensureDirectoryExists(_stringsPath, DEBUG_MODE);
4989
+ let content = "";
4990
+ const filePath = joinPaths(_stringsPath, type + ".txt");
4991
+ if (pathExists(filePath)) {
4992
+ const existingContent = getFileContent(filePath);
4993
+ if (existingContent.includes(imgName)) {
4994
+ content += str;
4995
+ } else {
4996
+ content += `
4997
+ |<<<<<<<<<<<<<------${imgName}------>>>>>>>>>>>>>|
4998
+ `;
4999
+ content += str;
5000
+ }
5001
+ } else {
5002
+ content += `
5003
+ |<<<<<<<<<<<<<------${imgName}------>>>>>>>>>>>>>|
5004
+ `;
5005
+ content += str;
5006
+ }
5007
+ addContentToFile(filePath, content);
5008
+ }
5009
+ return _screenshotPath;
5010
+ };
5011
+ static #generateContextReportPath = () => {
5012
+ const contextPath = joinPaths(
5013
+ Reports.#baseReportPath,
5014
+ toFileNameFormat(Config.getLocale()),
5015
+ "contexts"
5016
+ );
5017
+ ensureDirectoryExists(contextPath, DEBUG_MODE);
5018
+ return contextPath;
5019
+ };
5020
+ static #generateReport(type) {
5021
+ ReportFactory.export(type, Reports.#baseReportPath);
5022
+ }
5023
+ static generateHtml() {
5024
+ Reports.#generateReport(SUPPORTED_REPORT_TYPES.HTML);
5025
+ }
5026
+ static generateAsciiTable() {
5027
+ Reports.#generateReport(SUPPORTED_REPORT_TYPES.ASCII_TABLE);
5028
+ }
5029
+ }
5030
+ let Logger$1 = class Logger2 {
5031
+ static #isLogAppending = false;
5032
+ static #appenderInterval;
5033
+ static #appenderQueue = [];
5034
+ static info(message) {
5035
+ Logger2.#print("info", message);
5036
+ }
5037
+ static warn(message) {
5038
+ Logger2.#print("warn", message);
5039
+ }
5040
+ static error(message, err) {
5041
+ Logger2.#print("errr", message, err);
5042
+ }
5043
+ static debug(message) {
5044
+ Logger2.#print("dbug", message);
5045
+ }
5046
+ static #print(type, message, additionalObj = "") {
5047
+ const colors = {
5048
+ INFO: "\x1B[37m",
5049
+ WARN: "\x1B[33m",
5050
+ ERRR: "\x1B[31m",
5051
+ DBUG: "\x1B[34m"
5052
+ };
5053
+ type = type.toUpperCase();
5054
+ let color = colors[type] || colors.DEFAULT;
5055
+ additionalObj = additionalObj ? ` reason: ${additionalObj.toString()}` : "";
5056
+ let logMessage = `[${(/* @__PURE__ */ new Date()).toLocaleString()}] [${color}${type}\x1B[0m] [${Config.getLocale()}] - ${message}${additionalObj}`;
5057
+ switch (type) {
5058
+ case "INFO":
5059
+ console.info(logMessage);
5060
+ break;
5061
+ case "WARN":
5062
+ console.warn(logMessage);
5063
+ break;
5064
+ case "ERRR":
5065
+ console.error(logMessage);
5066
+ break;
5067
+ case "DBUG":
5068
+ console.debug(logMessage);
5069
+ break;
5070
+ default:
5071
+ console.log(logMessage);
5072
+ }
5073
+ logMessage = logMessage.replace(/\x1b\[\d+m/g, "");
5074
+ Logger2.#customLog(`${logMessage}
5075
+ `);
5076
+ }
5077
+ static #customLog = (message) => {
5078
+ if (Logger2.#isLogAppending) {
5079
+ Logger2.#appenderQueue.push(message);
5080
+ Logger2.#appenderInterval = setInterval(() => {
5081
+ if (!Logger2.#isLogAppending) {
5082
+ clearInterval(Logger2.#appenderInterval);
5083
+ message = Logger2.#appenderQueue.join("\n");
5084
+ Logger2.#appenderQueue = [];
5085
+ message && Logger2.#customLog(message);
5086
+ }
5087
+ }, 10);
5088
+ } else {
5089
+ Logger2.#isLogAppending = true;
5090
+ const LOGS_DIR = joinPaths(Reports.getReportPath(), "logs");
5091
+ const logFilePath = joinPaths(LOGS_DIR, "log");
5092
+ ensureDirectoryExists(LOGS_DIR, DEBUG_MODE);
5093
+ fs.appendFileSync(logFilePath, message);
5094
+ Logger2.#isLogAppending = false;
5095
+ }
5096
+ };
5097
+ };
5098
+ class NightWatchDriver extends BaseDriver {
5099
+ constructor(driver) {
5100
+ super(driver);
5101
+ }
5102
+ async getElement(locator, suppressNotFoundErrors = false) {
5103
+ return await this.$driver.element.find({
5104
+ selector: locator,
5105
+ locateStrategy: locator.startsWith("/") ? "xpath" : "css selector",
5106
+ suppressNotFoundErrors
5107
+ });
5108
+ }
5109
+ async getElements(locator, suppressNotFoundErrors = false) {
5110
+ return await this.$driver.element.findAll({
5111
+ selector: locator,
5112
+ locateStrategy: locator.startsWith("/") ? "xpath" : "css selector",
5113
+ suppressNotFoundErrors
5114
+ });
5115
+ }
5116
+ async getText(element) {
5117
+ return await element.getText();
5118
+ }
5119
+ async getTitle(element) {
5120
+ return await element.getAttribute("title");
5121
+ }
5122
+ async getPlaceholderText(element) {
5123
+ return await element.getAttribute("placeholder");
5124
+ }
5125
+ async getAltText(element) {
5126
+ return await element.getAttribute("alt");
5127
+ }
5128
+ async getTagName(element) {
5129
+ return await element.getTagName();
5130
+ }
5131
+ async getValue(element) {
5132
+ return await element.getAttribute("value");
5133
+ }
5134
+ async getElementID(element) {
5135
+ return await element.getAttribute("id");
5136
+ }
5137
+ async getElementDimension(element) {
5138
+ const eleSize = await element.getRect();
5139
+ if (![null, "", void 0].includes(eleSize)) {
5140
+ return [eleSize.x, eleSize.y, eleSize.height, eleSize.width];
5141
+ }
5142
+ }
5143
+ async isElementDisplayed(element) {
5144
+ return await this.$driver.isVisible(element);
5145
+ }
5146
+ async isElementPresent(element) {
5147
+ return await this.$driver.isPresent(element);
5148
+ }
5149
+ async getElementStrings(element) {
5150
+ const elementStrings = [];
5151
+ if (this.isElementDisplayed(element)) {
5152
+ const textFields = [
5153
+ { type: "eleTxt", value: await this.getText(element) },
5154
+ { type: "altTxt", value: await this.getAltText(element) },
5155
+ { type: "titleTxt", value: await this.getTitle(element) },
5156
+ { type: "placeTxt", value: await this.getPlaceholderText(element) },
5157
+ { type: "valueTxt", value: await this.getValue(element) }
5158
+ ];
5159
+ textFields.forEach(({ value }) => {
5160
+ if (this.checkIfNullOrEmpty(value)) {
5161
+ elementStrings.push(value);
5162
+ }
5163
+ });
5164
+ }
5165
+ return elementStrings;
5166
+ }
5167
+ async getElementString(element) {
5168
+ let eleStr = null;
5169
+ const textFunctions = [
5170
+ this.getText,
5171
+ this.getAltText,
5172
+ this.getTitle,
5173
+ this.getPlaceholderText,
5174
+ this.getValue
5175
+ ];
5176
+ for (const func of textFunctions) {
5177
+ eleStr = await func(element);
5178
+ if (eleStr !== null) return eleStr;
5179
+ }
5180
+ return eleStr;
5181
+ }
5182
+ async captureScreenshot(file) {
5183
+ await captureFullPage$1(this.$driver, file);
5184
+ }
5185
+ async getElementsCount(elements) {
5186
+ return elements.length;
5187
+ }
5188
+ async switchToIFrame(frameID, frameValue) {
5189
+ return new Promise((res) => {
5190
+ this.$driver.frame(frameID, function() {
5191
+ res(true);
5192
+ });
5193
+ });
5194
+ }
5195
+ async switchToParentFrame() {
5196
+ return new Promise(
5197
+ (res) => this.$driver.frame(null, function() {
5198
+ res(true);
5199
+ })
5200
+ );
5201
+ }
5202
+ pause(time) {
5203
+ this.$driver.pause(time * 1e3);
5204
+ }
5205
+ async onScreenStringHighlight(el, color) {
5206
+ await this.$driver.execute(
5207
+ (el2, color2) => {
5208
+ const oldBorder = window.getComputedStyle(el2).border;
5209
+ el2.style.border = `3px solid ${color2}`;
5210
+ setTimeout(() => {
5211
+ el2.style.border = oldBorder;
5212
+ }, 40);
5213
+ },
5214
+ [el, color]
5215
+ );
5216
+ }
5217
+ async checkIfIframeIsPresent() {
5218
+ return new Promise((res) => {
5219
+ this.$driver.isPresent(
5220
+ {
5221
+ selector: "//iframe",
5222
+ locateStrategy: "xpath",
5223
+ suppressNotFoundErrors: true
5224
+ },
5225
+ (result) => {
5226
+ res(result.value);
5227
+ }
5228
+ );
5229
+ });
5230
+ }
5231
+ async checkIfIframeBodyIsEmpty() {
5232
+ const bodyContent = await this.$driver.executeScript(function() {
5233
+ return document.body.innerHTML;
5234
+ });
5235
+ return bodyContent.trim() === "";
5236
+ }
5237
+ }
5238
+ const captureFullPage$1 = async (driver, filePath) => {
5239
+ const client = await CDP({
5240
+ host: "localhost",
5241
+ port: getRemoteDebuggerPort$1(driver)
5242
+ });
5243
+ const { Page } = client;
5244
+ await Page.enable();
5245
+ const { data: data2 } = await Page.captureScreenshot({
5246
+ format: "png",
5247
+ captureBeyondViewport: true
5248
+ });
5249
+ const screenshotBuffer = Buffer.from(data2, "base64");
5250
+ writeFileSync(filePath, screenshotBuffer);
5251
+ Logger$1.debug(`Screenshot saved as: ${filePath}`);
5252
+ await client.close();
5253
+ };
5254
+ const getRemoteDebuggerPort$1 = (driver) => {
5255
+ const debuggerAddress = driver?.capabilities?.["goog:chromeOptions"]?.debuggerAddress;
5256
+ if (debuggerAddress) {
5257
+ return debuggerAddress.split(":")?.[1] || 9229;
5258
+ }
5259
+ return 9229;
5260
+ };
5261
+ class WebDriverIoDriver extends BaseDriver {
5262
+ constructor(driver) {
5263
+ super(driver);
5264
+ }
5265
+ async getElement(locator) {
5266
+ return await this.$driver.$(locator);
5267
+ }
5268
+ async getElements(locator) {
5269
+ return await this.$driver.$$(locator);
5270
+ }
5271
+ async getText(element) {
5272
+ return await $(element).getText();
5273
+ }
5274
+ async getTitle(element) {
5275
+ return await $(element).getAttribute("title");
5276
+ }
5277
+ async getPlaceholderText(element) {
5278
+ return await $(element).getAttribute("placeholder");
5279
+ }
5280
+ async getAltText(element) {
5281
+ return await $(element).getAttribute("alt");
5282
+ }
5283
+ async getTagName(element) {
5284
+ return await $(element).getTagName();
5285
+ }
5286
+ async getValue(element) {
5287
+ return await $(element).getValue();
5288
+ }
5289
+ async getElementID(element) {
5290
+ return await $(element).getAttribute("id");
5291
+ }
5292
+ async getElementDimension(element) {
5293
+ if (!element) return null;
5294
+ try {
5295
+ const location = await element.getLocation();
5296
+ const size = await element.getSize();
5297
+ if (!location || !size) return null;
5298
+ return [location.x, location.y, size.height, size.width];
5299
+ } catch (error) {
5300
+ console.error("Error getting element dimensions:", error);
5301
+ return null;
5302
+ }
5303
+ }
5304
+ async isElementDisplayed(element) {
5305
+ return await $(element).isDisplayed();
5306
+ }
5307
+ async isElementPresent(element) {
5308
+ return await $(element).isExisting();
5309
+ }
5310
+ async getElementStrings(element) {
5311
+ const elementStrings = [];
5312
+ const textFields = [
5313
+ { type: "elTxt", value: await this.getText(element) },
5314
+ { type: "altTxt", value: await this.getAltText(element) },
5315
+ { type: "titleTxt", value: await this.getTitle(element) },
5316
+ { type: "placeTxt", value: await this.getPlaceholderText(element) },
5317
+ { type: "valueTxt", value: await this.getValue(element) }
5318
+ ];
5319
+ textFields.forEach(({ value }) => {
5320
+ if (this.checkIfNullOrEmpty(value)) {
5321
+ elementStrings.push(value);
5322
+ }
5323
+ });
5324
+ return elementStrings;
5325
+ }
5326
+ async getElementString(element) {
5327
+ let eleStr = null;
5328
+ const textFunctions = [
5329
+ this.getText,
5330
+ this.getAltText,
5331
+ this.getTitle,
5332
+ this.getPlaceholderText,
5333
+ this.getValue
5334
+ ];
5335
+ for (const func of textFunctions) {
5336
+ eleStr = await func(element);
5337
+ if (eleStr !== null) return eleStr;
5338
+ }
5339
+ return eleStr;
5340
+ }
5341
+ async captureScreenshot(file) {
5342
+ await captureFullPage(this.$driver, file);
5343
+ }
5344
+ async getElementsCount(elements) {
5345
+ return elements.length;
5346
+ }
5347
+ async switchToIFrame(frameID, frameValue) {
5348
+ await this.$driver.switchFrame(frameValue);
5349
+ }
5350
+ async switchToParentFrame() {
5351
+ await this.$driver.switchToParentFrame();
5352
+ }
5353
+ pause(time) {
5354
+ this.$driver.pause(time * 1e3);
5355
+ }
5356
+ async onScreenStringHighlight(el, color) {
5357
+ await this.$driver.execute(
5358
+ (el2, color2) => {
5359
+ const oldBorder = window.getComputedStyle(el2).border;
5360
+ el2.style.border = `3px solid ${color2}`;
5361
+ setTimeout(() => {
5362
+ el2.style.border = oldBorder;
5363
+ }, 40);
5364
+ },
5365
+ el,
5366
+ color
5367
+ );
5368
+ }
5369
+ async checkIfIframeIsPresent() {
5370
+ return new Promise((res) => {
5371
+ this.$driver.$("//iframe").isExisting().then(() => {
5372
+ res(true);
5373
+ });
5374
+ });
5375
+ }
5376
+ async checkIfIframeBodyIsEmpty() {
5377
+ const bodyContent = await this.$driver.executeScript(
5378
+ "return document.body.innerHTML;",
5379
+ []
5380
+ );
5381
+ return bodyContent.trim() === "";
5382
+ }
5383
+ }
5384
+ const captureFullPage = async (driver, filePath) => {
5385
+ const port = getRemoteDebuggerPort(driver);
5386
+ const client = await CDP({ host: "localhost", port });
5387
+ const { Page } = client;
5388
+ await Page.enable();
5389
+ const { data: data2 } = await Page.captureScreenshot({
5390
+ format: "png",
5391
+ captureBeyondViewport: true
5392
+ });
5393
+ fs.writeFileSync(filePath, Buffer.from(data2, "base64"));
5394
+ await client.close();
5395
+ };
5396
+ const getRemoteDebuggerPort = (driver) => {
5397
+ const debuggerAddress = driver.capabilities?.["goog:chromeOptions"]?.debuggerAddress;
5398
+ return debuggerAddress ? debuggerAddress.split(":")[1] || 9229 : 9229;
5399
+ };
5400
+ const xpath = ({ subject, selector, options = {}, driver }) => {
5401
+ if (!Cypress) {
5402
+ driver.printOnConsole("Cypress object is inaccessible");
5403
+ return;
5404
+ }
5405
+ const isNumber = (xpathResult) => xpathResult.resultType === XPathResult.NUMBER_TYPE;
5406
+ const numberResult = (xpathResult) => xpathResult.numberValue;
5407
+ const isString = (xpathResult) => xpathResult.resultType === XPathResult.STRING_TYPE;
5408
+ const stringResult = (xpathResult) => xpathResult.stringValue;
5409
+ const isBoolean = (xpathResult) => xpathResult.resultType === XPathResult.BOOLEAN_TYPE;
5410
+ const booleanResult = (xpathResult) => xpathResult.booleanValue;
5411
+ const isPrimitive = (x) => Cypress._.isNumber(x) || Cypress._.isString(x) || Cypress._.isBoolean(x);
5412
+ const log2 = {
5413
+ name: "xpath",
5414
+ message: selector
5415
+ };
5416
+ if (Cypress.dom.isElement(subject) && subject.length > 1) {
5417
+ throw new Error(
5418
+ "xpath() can only be called on a single element. Your subject contained " + subject.length + " elements."
5419
+ );
5420
+ }
5421
+ const getValue = () => {
5422
+ let nodes = [];
5423
+ let contextNode;
5424
+ let withinSubject = cy.state("withinSubject");
5425
+ if (Cypress.dom.isElement(subject)) {
5426
+ contextNode = subject[0];
5427
+ } else if (Cypress.dom.isDocument(subject)) {
5428
+ contextNode = subject;
5429
+ } else if (withinSubject) {
5430
+ contextNode = withinSubject[0];
5431
+ } else {
5432
+ contextNode = cy.state("window").document;
5433
+ }
5434
+ let iterator = (contextNode.ownerDocument || contextNode).evaluate(
5435
+ selector,
5436
+ contextNode
5437
+ );
5438
+ if (isNumber(iterator)) {
5439
+ const result = numberResult(iterator);
5440
+ log2.consoleProps = () => {
5441
+ return {
5442
+ XPath: selector,
5443
+ type: "number",
5444
+ result
5445
+ };
5446
+ };
5447
+ return result;
5448
+ }
5449
+ if (isString(iterator)) {
5450
+ const result = stringResult(iterator);
5451
+ log2.consoleProps = () => {
5452
+ return {
5453
+ XPath: selector,
5454
+ type: "string",
5455
+ result
5456
+ };
5457
+ };
5458
+ return result;
5459
+ }
5460
+ if (isBoolean(iterator)) {
5461
+ const result = booleanResult(iterator);
5462
+ log2.consoleProps = () => {
5463
+ return {
5464
+ XPath: selector,
5465
+ type: "boolean",
5466
+ result
5467
+ };
5468
+ };
5469
+ return result;
5470
+ }
5471
+ try {
5472
+ let node = iterator.iterateNext();
5473
+ while (node) {
5474
+ nodes.push(node);
5475
+ node = iterator.iterateNext();
5476
+ }
5477
+ log2.consoleProps = () => {
5478
+ return {
5479
+ XPath: selector,
5480
+ result: nodes.length === 1 ? nodes[0] : nodes
5481
+ };
5482
+ };
5483
+ return nodes;
5484
+ } catch (e) {
5485
+ console.error("Document tree modified during iteration", e);
5486
+ return null;
5487
+ }
5488
+ };
5489
+ const resolveValue = () => {
5490
+ return Cypress.Promise.try(getValue).then((value) => {
5491
+ if (!isPrimitive(value)) {
5492
+ value = Cypress.$(value);
5493
+ value.selector = selector;
5494
+ }
5495
+ return cy.verifyUpcomingAssertions(value, options, {
5496
+ onRetry: resolveValue
5497
+ });
5498
+ });
5499
+ };
5500
+ return resolveValue().then((value) => {
5501
+ if (options.log !== false) {
5502
+ Cypress.log(log2);
5503
+ }
5504
+ return value;
5505
+ }).catch((ex) => console.log(ex));
5506
+ };
5507
+ class CypressDriver extends BaseDriver {
5508
+ /**
5509
+ *
5510
+ * @param {this.$driver} driver
5511
+ */
5512
+ constructor(driver) {
5513
+ super(driver);
5514
+ }
5515
+ async getElement(el) {
5516
+ if (typeof el !== "string") {
5517
+ return this.$driver.wrap(el);
5518
+ } else if (el.startsWith("//")) {
5519
+ return await this.xpath(el).first();
5520
+ } else {
5521
+ return await this.$driver.get(el).first();
5522
+ }
5523
+ }
5524
+ async getElements(el) {
5525
+ if (typeof el !== "string") {
5526
+ return this.$driver.wrap(el);
5527
+ } else if (el.startsWith("//")) {
5528
+ return await this.xpath(el);
5529
+ } else {
5530
+ return await this.$driver.get(el);
5531
+ }
5532
+ }
5533
+ async getText(el) {
5534
+ return typeof el === "string" ? await this.$driver.get(el).invoke("text") : await this.$driver.wrap(el).invoke("text");
5535
+ }
5536
+ async getTitle(el) {
5537
+ return typeof el === "string" ? await this.$driver.get(el).title() : this.$driver.wrap().title();
5538
+ }
5539
+ async getPlaceholderText(el) {
5540
+ if (typeof el === "string") {
5541
+ return this.$driver.get(el).filter("input").invoke("attr", "placeholder").then((placeholder) => {
5542
+ return placeholder;
5543
+ });
5544
+ } else {
5545
+ return this.$driver.$$(el).attr("placeholder");
5546
+ }
5547
+ }
5548
+ async getAltText(locator) {
5549
+ return this.$driver.get(locator).invoke("attr", "alt");
5550
+ }
5551
+ async getWidth(el) {
5552
+ if (typeof el === "string") {
5553
+ return this.$driver.get(el).invoke("width");
5554
+ } else {
5555
+ return this.$driver.$$(el).width();
5556
+ }
5557
+ }
5558
+ async getHeight(el) {
5559
+ if (typeof el === "string") {
5560
+ return this.$driver.get(el).invoke("height");
5561
+ } else {
5562
+ return this.$driver.$$(el).height();
5563
+ }
5564
+ }
5565
+ async getTagName(el) {
5566
+ if (typeof el === "string") {
5567
+ return this.$driver.get(el).invoke("prop", "tagName").then((tagName) => tagName.toLowerCase());
5568
+ } else {
5569
+ return this.$driver.$$(el).tagName;
5570
+ }
5571
+ }
5572
+ async getValue(el) {
5573
+ if (typeof el === "string") {
5574
+ return this.$driver.get(el).invoke("val");
5575
+ } else {
5576
+ return this.$driver.wrap(el).invoke("val");
5577
+ }
5578
+ }
5579
+ async getLocation(el) {
5580
+ if (typeof el === "string") {
5581
+ return this.$driver.get(el).invoke("offset").then((offset) => {
5582
+ return { x: offset.left, y: offset.top };
5583
+ });
5584
+ } else {
5585
+ const offset = this.$driver.$$(el).offset();
5586
+ return { x: offset.left, y: offset.top };
5587
+ }
5588
+ }
5589
+ async isElementDisplayed(el) {
5590
+ if (typeof el === "string") {
5591
+ return this.$driver.get(el).then(($element) => {
5592
+ return $element.is(":visible");
5593
+ });
5594
+ } else {
5595
+ return this.$driver.$$(el).is(":visible");
5596
+ }
5597
+ }
5598
+ async captureScreenshot(file) {
5599
+ this.$driver.screenshot(file);
5600
+ }
5601
+ async getElementsCount(el) {
5602
+ return new Promise((res) => {
5603
+ if (typeof el === "string") {
5604
+ return this.$driver.get(el).its("length").then((l) => res(l));
5605
+ } else {
5606
+ return this.$driver.wrap(el, { timeout: 8e3 }).its("length").then((l) => res(l));
5607
+ }
5608
+ });
5609
+ }
5610
+ async getElementStrings(el) {
5611
+ const elementStrings = [];
5612
+ try {
5613
+ const textFields = [
5614
+ { type: "elTxt", value: await this.getText(el) },
5615
+ { type: "altTxt", value: await this.getAltText(el) },
5616
+ // { type: 'titleTxt', value: await this.getTitle(el) },
5617
+ { type: "placetxt", value: await this.getPlaceholderText(el) }
5618
+ ];
5619
+ textFields.forEach(({ value }) => {
5620
+ if (this.checkIfNullOrEmpty(value)) {
5621
+ elementStrings.push(value);
5622
+ }
5623
+ });
5624
+ } catch (textError) {
5625
+ Logger$1.error("Error getting text of element:", textError);
5626
+ }
5627
+ return elementStrings;
5628
+ }
5629
+ printOnConsole(str) {
5630
+ this.$driver.log(str);
5631
+ }
5632
+ xpath(subject, selector, options = {}) {
5633
+ return xpath({ subject, selector, options, driver: this.$driver });
5634
+ }
5635
+ }
5636
+ class SeleniumDriver extends BaseDriver {
5637
+ constructor(driver) {
5638
+ super(driver);
5639
+ }
5640
+ async getElement(locator) {
5641
+ return await this.driver.findElement(locator);
5642
+ }
5643
+ async getElements(locator) {
5644
+ return await this.driver.findElements(locator);
5645
+ }
5646
+ async getText(element) {
5647
+ return await element.getText();
5648
+ }
5649
+ async getTitle() {
5650
+ return await this.driver.getTitle();
5651
+ }
5652
+ // async getTitle(element) {
5653
+ // return await element.getAttribute('title');
5654
+ // }
5655
+ // async getPlaceholderText(element, placeholder) {
5656
+ // return await element.getAttribute(placeholder);
5657
+ // }
5658
+ // async getAltText(element, alt) {
5659
+ // return await element.getAttribute(alt);
5660
+ // }
5661
+ async getAttribute(element, attributeName) {
5662
+ return await element.getAttribute(attributeName);
5663
+ }
5664
+ async getTagName(element) {
5665
+ return await element.getTagName();
5666
+ }
5667
+ // async getValue(element, value) {
5668
+ // return await element.getAttribute(value);
5669
+ // }
5670
+ async getElementDimension(element) {
5671
+ const eleSize = await element.getRect();
5672
+ if (![null, "", void 0].includes(eleSize)) {
5673
+ return [eleSize.x, eleSize.y, eleSize.height, eleSize.width];
5674
+ }
5675
+ }
5676
+ async isElementDisplayed(element) {
5677
+ return await element.isDisplayed();
5678
+ }
5679
+ async getElementStrings(element) {
5680
+ const elementStrings = [];
5681
+ const textFields = [
5682
+ { type: "elTxt", value: await this.getText(element) },
5683
+ { type: "altTxt", value: await this.getAttribute(element, "alt") },
5684
+ { type: "titleTxt", value: await this.getAttribute(element, "title") },
5685
+ {
5686
+ type: "placeTxt",
5687
+ value: await this.getAttribute(element, "placeholder")
5688
+ },
5689
+ { type: "valueTxt", value: await this.getAttribute(element, "value") }
5690
+ ];
5691
+ textFields.forEach(({ value }) => {
5692
+ if (this.checkIfNullOrEmpty(value)) {
5693
+ elementStrings.push(value);
5694
+ }
5695
+ });
5696
+ return elementStrings;
5697
+ }
5698
+ async getElementsCount(elements) {
5699
+ return elements.length;
5700
+ }
5701
+ }
5702
+ const build$1 = (type, driver) => {
5703
+ switch (type) {
5704
+ case SYSTEM_TYPES.NIGHT_WATCH:
5705
+ return new NightWatchDriver(driver);
5706
+ case SYSTEM_TYPES.WEB_DRIVER_IO:
5707
+ return new WebDriverIoDriver(driver);
5708
+ case SYSTEM_TYPES.CYPRESS:
5709
+ return new CypressDriver(driver);
5710
+ case SYSTEM_TYPES.SELENIUMJS:
5711
+ return new SeleniumDriver(driver);
5712
+ default:
5713
+ throw new Error("Unsupported framework");
5714
+ }
5715
+ };
5716
+ const propertExists = (key, obj) => key in obj;
5717
+ const allPropertyExists = (keys, obj, missingKeys = []) => keys.every((key) => {
5718
+ if (!propertExists(key, obj)) {
5719
+ missingKeys.push(key);
5720
+ return true;
5721
+ }
5722
+ return true;
5723
+ });
5724
+ const arr2Txt = (array, demiliter = ", ") => array.join(demiliter);
5725
+ const getSpacePattern = (asStr = true) => asStr ? "(?:\\s|\\t|(?:&nbsp;))" : /(?:\s|\t|(?:&nbsp;))/g;
5726
+ class BaseValidator {
5727
+ #config = {};
5728
+ #type;
5729
+ constructor(type) {
5730
+ this.#type = type;
5731
+ this.#addBaseConfig();
5732
+ this.buildConfig();
5733
+ this.#buildParser();
5734
+ }
5735
+ #addBaseConfig() {
5736
+ this.addToConfig(
5737
+ "supportedLocales",
5738
+ Config.getOptions()?.supportedLocales,
5739
+ []
5740
+ );
5741
+ this.addToConfig("defaultLocale", Config.getDefaultLocale());
5742
+ this.addToConfig(
5743
+ "defaultLanguage",
5744
+ Config.getDefaultLocale()?.split(/[-_ ]/g)[0]
5745
+ );
5746
+ this.addToConfig("language", Config.getLocale()?.split(/[-_ ]/g)[0]);
5747
+ this.addToConfig("locale", Config.getLocale());
5748
+ this.addToConfig("qaLocale", Config.getQALocale());
5749
+ }
5750
+ buildConfig() {
5751
+ throw new Error(
5752
+ `{{${this.#type}}} buildConfig should be implemented by child class`
5753
+ );
5754
+ }
5755
+ #buildParser() {
5756
+ Globalize.load(CldrData.entireSupplemental());
5757
+ Globalize.load(
5758
+ CldrData.entireMainFor(
5759
+ this.#getCompatibleLocale(this.#config.defaultLocale),
5760
+ this.#getCompatibleLocale(this.#config.locale)
5761
+ )
5762
+ );
5763
+ }
5764
+ #getCompatibleLocale(locale) {
5765
+ if (this.isQaLocale()) {
5766
+ return "en";
5767
+ }
5768
+ locale = locale.replace(/[-_ ]/g, "-");
5769
+ const locales = CldrData.availableLocales;
5770
+ let suitableLocale;
5771
+ if (locales.find((l) => l === locale)) {
5772
+ suitableLocale = locale;
5773
+ } else {
5774
+ const temp = locale.split("-")[0];
5775
+ if (locales.find((l) => l === temp)) {
5776
+ suitableLocale = temp;
5777
+ } else {
5778
+ suitableLocale = locale;
5779
+ }
5780
+ }
5781
+ return suitableLocale;
5782
+ }
5783
+ /**
5784
+ * to check if the given text is a valid issue type
5785
+ * @param {String} string
5786
+ * @returns {Boolean}
5787
+ */
5788
+ validate(string) {
5789
+ throw new Error(
5790
+ `{{${this.#type}}} validate should be implemented by child class`
5791
+ );
5792
+ }
5793
+ /**
5794
+ * check whether the given value is a valid type of the supplied locale
5795
+ *
5796
+ * @param {String} string
5797
+ * @returns {Boolean}
5798
+ */
5799
+ isInternationalized(string) {
5800
+ throw new Error(
5801
+ `{{${this.#type}}} isInternationalized should be implemented by child class`
5802
+ );
5803
+ }
5804
+ setConfig(data2) {
5805
+ this.#config = data2;
5806
+ }
5807
+ addToConfig(prop, value, defaultValue) {
5808
+ this.#config[prop] = value ?? defaultValue;
5809
+ }
5810
+ getConfig() {
5811
+ return this.#config;
5812
+ }
5813
+ isSupportedLocale() {
5814
+ return this.#config.supportedLocales.includes(this.currentLocale());
5815
+ }
5816
+ isQaLocale() {
5817
+ return this.currentLocale() === this.#config?.qaLocale;
5818
+ }
5819
+ isDefaultLocale() {
5820
+ return this.currentLocale() === this.defaultLocale();
5821
+ }
5822
+ defaultLocale() {
5823
+ return this.#config?.defaultLocale;
5824
+ }
5825
+ defaultLanguage() {
5826
+ return this.#config?.defaultLanguage;
5827
+ }
5828
+ currentLocale() {
5829
+ return this.#config?.locale;
5830
+ }
5831
+ currentLanguage() {
5832
+ return this.#config.language;
5833
+ }
5834
+ /**
5835
+ *
5836
+ * @param {String} locale
5837
+ * @returns {Globalize}
5838
+ */
5839
+ getGlobalize(locale) {
5840
+ return Globalize(this.#getCompatibleLocale(locale));
5841
+ }
5842
+ }
5843
+ class CurrencyValidator extends BaseValidator {
5844
+ constructor() {
5845
+ super("currency");
5846
+ }
5847
+ /**
5848
+ *
5849
+ * @override
5850
+ */
5851
+ validate(string) {
5852
+ return this.#isDefaultCurrency(string) || this.isInternationalized(string);
5853
+ }
5854
+ /**
5855
+ *
5856
+ * @override
5857
+ */
5858
+ isInternationalized(string) {
5859
+ return this.#isValidCurrency(this.currentLocale(), string);
5860
+ }
5861
+ /**
5862
+ *
5863
+ * @override
5864
+ */
5865
+ buildConfig() {
5866
+ }
5867
+ /**
5868
+ * check whether the given value is a valid percentage of the supplied locale
5869
+ *
5870
+ * @param {String} locale
5871
+ * @param {String} string
5872
+ * @returns {Boolean}
5873
+ */
5874
+ #isValidCurrency(locale, string) {
5875
+ const currencyCode = this.#getCurrencyCode(locale);
5876
+ const currencySymbol = this.#getCurrencySymbol(locale, currencyCode);
5877
+ const hasCurrencySymbolOrCode = this.#hasCurrencyCodeOrSymbol(
5878
+ currencyCode,
5879
+ currencySymbol,
5880
+ string
5881
+ );
5882
+ if (!hasCurrencySymbolOrCode) {
5883
+ return false;
5884
+ }
5885
+ const clearNumber = this.#clearNumber(currencyCode, currencySymbol, string);
5886
+ return !isNaN(this.getGlobalize(locale).numberParser()(clearNumber));
5887
+ }
5888
+ #hasCurrencyCodeOrSymbol(code, symbol, string) {
5889
+ return new RegExp(
5890
+ `^(?:-)?(?:${code}|\\${symbol})(?:${getSpacePattern()})?(?:-)?[0-9,. ]+$`,
5891
+ "gi"
5892
+ ).test(string) || new RegExp(
5893
+ `^(?:[- ]?)[0-9,. ]+(?:${getSpacePattern()})?(?:${code}|\\${symbol})$`,
5894
+ "gi"
5895
+ ).test(string);
5896
+ }
5897
+ #clearNumber(code, symbol, string) {
5898
+ return string.replace(new RegExp(`^(?:-)(?:${getSpacePattern()})?`, "gi"), "").replace(
5899
+ new RegExp(`^(?:${getSpacePattern()})?(?:${code}|\\${symbol})`, "gi"),
5900
+ ""
5901
+ ).replace(new RegExp(`^(?:-)(?:${getSpacePattern()})?`, "gi"), "").replace(
5902
+ new RegExp(`(?:${getSpacePattern()})?(?:${code}|\\${symbol})$`, "gi"),
5903
+ ""
5904
+ ).trim();
5905
+ }
5906
+ #getTerritory(locale) {
5907
+ const maxLocale = this.getGlobalize(locale).cldr.supplemental(["likelySubtags", locale]) || locale;
5908
+ return maxLocale.split(/[-_ ]/).pop();
5909
+ }
5910
+ #getCurrencyCode(locale) {
5911
+ const territory = this.#getTerritory(locale);
5912
+ const currencyData = this.getGlobalize(locale).cldr.supplemental("currencyData");
5913
+ const currencies = currencyData.region[territory];
5914
+ if (currencies) {
5915
+ const currency = currencies.find((currency2) => {
5916
+ const values = Object.values(currency2)[0];
5917
+ return !values._tender && (!values._to || new Date(values._to) >= /* @__PURE__ */ new Date());
5918
+ });
5919
+ return currency ? Object.keys(currency)[0] : "USD";
5920
+ }
5921
+ return "USD";
5922
+ }
5923
+ #getCurrencySymbol(locale, currencyCode) {
5924
+ const currencyData = this.getGlobalize(locale).cldr.main(
5925
+ `numbers/currencies/${currencyCode}`
5926
+ );
5927
+ return currencyData?.symbol || "$";
5928
+ }
5929
+ /**
5930
+ * check whether the given value is a valid currency of default locale
5931
+ *
5932
+ * @param {String} string
5933
+ * @returns {Boolean}
5934
+ */
5935
+ #isDefaultCurrency(string) {
5936
+ return this.#isValidCurrency(this.defaultLocale(), string);
5937
+ }
5938
+ }
5939
+ const getParser = (locale) => {
5940
+ let [lang = "en", country = "us"] = locale.split(/[-_ ]/g);
5941
+ country = String(country).toLowerCase();
5942
+ switch (lang) {
5943
+ case "en":
5944
+ return country === "gb" ? en.GB : en;
5945
+ case "de":
5946
+ return de;
5947
+ case "es":
5948
+ return es;
5949
+ case "fr":
5950
+ return fr;
5951
+ case "pt":
5952
+ return pt;
5953
+ case "ja":
5954
+ return ja;
5955
+ case "zh":
5956
+ if (["hans", "cn", "sg", "hans-cn"].includes(country)) {
5957
+ return zh.hans;
5958
+ } else if (["hant", "tw", "hk", "mo", "hant-tw"].includes(country)) {
5959
+ return zh.hant;
5960
+ }
5961
+ return zh;
5962
+ case "ru":
5963
+ return ru;
5964
+ case "nl":
5965
+ return nl;
5966
+ case "uk":
5967
+ return uk;
5968
+ default:
5969
+ return en;
5970
+ }
5971
+ };
5972
+ const isValid$1 = (locale, string) => {
5973
+ string = String(string);
5974
+ const parsedResults = getParser(locale).parse(String(string).trim());
5975
+ parsedResults.forEach((r) => {
5976
+ string = string.replace(r.text, "");
5977
+ });
5978
+ return string.replace(/[^\p{L}\p{N}]+/gu, "").trim().length === 0;
5979
+ };
5980
+ const toLuxonLocale = (locale) => {
5981
+ try {
5982
+ locale = locale.replace("_", "-");
5983
+ return Intl.DateTimeFormat.supportedLocalesOf(locale)[0];
5984
+ } catch (ex) {
5985
+ Logger.warn(`${locale} is unsupported by Intl`);
5986
+ return false;
5987
+ }
5988
+ };
5989
+ const isValid = (locale, format, value) => {
5990
+ locale = toLuxonLocale(locale);
5991
+ if (locale !== false) {
5992
+ const parsed = DateTime.fromFormat(value, format, {
5993
+ locale: toLuxonLocale(locale)
5994
+ });
5995
+ if (parsed.isValid) {
5996
+ return true;
5997
+ }
5998
+ }
5999
+ return false;
6000
+ };
6001
+ class DateValidator extends BaseValidator {
6002
+ constructor() {
6003
+ super("date");
6004
+ }
6005
+ /**
6006
+ *
6007
+ * @override
6008
+ */
6009
+ validate(string) {
6010
+ return this.#isDefaultDate(string) || this.isInternationalized(string);
6011
+ }
6012
+ /**
6013
+ *
6014
+ * @override
6015
+ */
6016
+ isInternationalized(string) {
6017
+ return this.#isValidDate(
6018
+ this.isQaLocale() ? this.defaultLocale() : this.currentLocale(),
6019
+ string
6020
+ );
6021
+ }
6022
+ /**
6023
+ *
6024
+ * @override
6025
+ */
6026
+ buildConfig() {
6027
+ }
6028
+ #isValidDate(locale, string) {
6029
+ return this.#verifyUsingGlobalize(locale, string) || this.#verifyUsingLuxon(locale, string) || this.#verifyUsingChrono(locale, string);
6030
+ }
6031
+ #isDefaultDate(string) {
6032
+ return this.#isValidDate(this.defaultLocale(), string);
6033
+ }
6034
+ #verifyUsingGlobalize(locale, string) {
6035
+ const formats = ["short", "medium", "long", "full"];
6036
+ for (let format of formats) {
6037
+ const dateParser = this.getGlobalize(locale).dateParser({ date: format });
6038
+ if (dateParser(string)) {
6039
+ return true;
6040
+ }
6041
+ }
6042
+ return false;
6043
+ }
6044
+ #verifyUsingLuxon(locale, string) {
6045
+ const formats = [
6046
+ DateTime.DATE_SHORT,
6047
+ DateTime.DATE_MED,
6048
+ DateTime.DATE_FULL,
6049
+ DateTime.DATE_HUGE,
6050
+ DateTime.DATE_MED_WITH_WEEKDAY,
6051
+ "D",
6052
+ "DD",
6053
+ "DDD",
6054
+ "DDDD"
6055
+ ];
6056
+ for (let format of formats) {
6057
+ const result = isValid(locale, format, string);
6058
+ if (result) {
6059
+ return true;
6060
+ }
6061
+ }
6062
+ return false;
6063
+ }
6064
+ #verifyUsingChrono(locale, string) {
6065
+ return isValid$1(
6066
+ this.isQaLocale() ? this.defaultLocale() : locale,
6067
+ string
6068
+ );
6069
+ }
6070
+ }
6071
+ class DateTimeValidator extends BaseValidator {
6072
+ constructor() {
6073
+ super("dateTime");
6074
+ }
6075
+ /**
6076
+ *
6077
+ * @override
6078
+ */
6079
+ validate(string) {
6080
+ return this.#isDefaultDateTime(string) || this.isInternationalized(string);
6081
+ }
6082
+ /**
6083
+ *
6084
+ * @override
6085
+ */
6086
+ isInternationalized(string) {
6087
+ return this.#isValidDateTime(
6088
+ this.isQaLocale() ? this.defaultLocale() : this.currentLocale(),
6089
+ string
6090
+ );
6091
+ }
6092
+ /**
6093
+ *
6094
+ * @override
6095
+ */
6096
+ buildConfig() {
6097
+ }
6098
+ #isValidDateTime(locale, string) {
6099
+ return this.#verifyUsingGlobalize(locale, string) || this.#verifyUsingLuxon(locale, string) || this.#verifyUsingChrono(locale, string);
6100
+ }
6101
+ #isDefaultDateTime(string) {
6102
+ return this.#isValidDateTime(this.defaultLocale(), string);
6103
+ }
6104
+ #verifyUsingGlobalize(locale, string) {
6105
+ const formats = ["short", "medium", "long", "full"];
6106
+ for (let format of formats) {
6107
+ const timeParser = this.getGlobalize(locale).dateParser({
6108
+ datetime: format
6109
+ });
6110
+ if (timeParser(string)) {
6111
+ return true;
6112
+ }
6113
+ }
6114
+ return false;
6115
+ }
6116
+ #verifyUsingLuxon(locale, string) {
6117
+ const formats = [
6118
+ DateTime.DATETIME_SHORT,
6119
+ DateTime.DATETIME_SHORT_WITH_SECONDS,
6120
+ DateTime.DATETIME_MED,
6121
+ DateTime.DATETIME_MED_WITH_SECONDS,
6122
+ DateTime.DATETIME_MED_WITH_WEEKDAY,
6123
+ DateTime.DATETIME_FULL,
6124
+ DateTime.DATETIME_FULL_WITH_SECONDS,
6125
+ DateTime.DATETIME_HUGE,
6126
+ DateTime.DATETIME_HUGE_WITH_SECONDS,
6127
+ "f",
6128
+ "F",
6129
+ "ff",
6130
+ "FF"
6131
+ ];
6132
+ for (let format of formats) {
6133
+ const result = isValid(locale, format, string);
6134
+ if (result) {
6135
+ return true;
6136
+ }
6137
+ }
6138
+ return false;
6139
+ }
6140
+ #verifyUsingChrono(locale, string) {
6141
+ return isValid$1(
6142
+ this.isQaLocale() ? this.defaultLocale() : locale,
6143
+ string
6144
+ );
6145
+ }
6146
+ }
6147
+ class NumberValidator extends BaseValidator {
6148
+ constructor() {
6149
+ super("number");
6150
+ }
6151
+ /**
6152
+ *
6153
+ * @override
6154
+ */
6155
+ validate(string) {
6156
+ return this.#isDefaultNumber(string) || this.isInternationalized(string);
6157
+ }
6158
+ /**
6159
+ *
6160
+ * @override
6161
+ */
6162
+ isInternationalized(string) {
6163
+ return this.#isValidNumber(this.currentLocale(), string);
6164
+ }
6165
+ /**
6166
+ *
6167
+ * @override
6168
+ */
6169
+ buildConfig() {
6170
+ }
6171
+ /**
6172
+ * check whether the given value is a valid number of the supplied locale
6173
+ *
6174
+ * @param {String} locale
6175
+ * @param {String} string
6176
+ * @returns {Boolean}
6177
+ */
6178
+ #isValidNumber(locale, string) {
6179
+ const parser = this.getGlobalize(locale).numberParser();
6180
+ return !isNaN(parser(string));
6181
+ }
6182
+ /**
6183
+ * check whether the given value is a valid number of default locale
6184
+ *
6185
+ * @param {String} string
6186
+ * @returns {Boolean}
6187
+ */
6188
+ #isDefaultNumber(string) {
6189
+ return this.#isValidNumber(this.defaultLocale(), string);
6190
+ }
6191
+ }
6192
+ class PercentageValidator extends BaseValidator {
6193
+ constructor() {
6194
+ super("percentage");
6195
+ }
6196
+ /**
6197
+ *
6198
+ * @override
6199
+ */
6200
+ validate(string) {
6201
+ return this.#isDefaultPercentage(string) || this.isInternationalized(string);
6202
+ }
6203
+ /**
6204
+ *
6205
+ * @override
6206
+ */
6207
+ isInternationalized(string) {
6208
+ return this.#isValidPercentage(this.currentLocale(), string);
6209
+ }
6210
+ /**
6211
+ *
6212
+ * @override
6213
+ */
6214
+ buildConfig() {
6215
+ }
6216
+ /**
6217
+ * check whether the given value is a valid percentage of the supplied locale
6218
+ *
6219
+ * @param {String} locale
6220
+ * @param {String} string
6221
+ * @returns {Boolean}
6222
+ */
6223
+ #isValidPercentage(locale, string) {
6224
+ const hasPercentageSymbol = this.#hasPercentage(locale, string);
6225
+ if (!hasPercentageSymbol) {
6226
+ return false;
6227
+ }
6228
+ const clearNumber = this.#getClearNumber(string);
6229
+ return !isNaN(this.getGlobalize(locale).numberParser()(clearNumber));
6230
+ }
6231
+ #getClearNumber(string = "") {
6232
+ return string.replace(
6233
+ new RegExp(
6234
+ `(^(?:${getSpacePattern()})*|(?:${getSpacePattern()})*$)`,
6235
+ "g"
6236
+ ),
6237
+ ""
6238
+ ).replace(/^-/, "").replace(/٪|%/g, "").trim();
6239
+ }
6240
+ #hasPercentage(locale, string) {
6241
+ const baseNumber = "[0-9,. ]+";
6242
+ let pattern;
6243
+ if (["fa-IR", "fa-ir"].includes(locale) || locale.startsWith("ar")) {
6244
+ pattern = new RegExp(
6245
+ `(?:-)?(?:${getSpacePattern()})?(?:٪|%)(?:${getSpacePattern()})?${baseNumber}`,
6246
+ "g"
6247
+ );
6248
+ } else {
6249
+ pattern = new RegExp(
6250
+ `(?:-)?(?:${getSpacePattern()})?${baseNumber}(?:${getSpacePattern()})?(?:٪|%)`,
6251
+ "g"
6252
+ );
6253
+ }
6254
+ return pattern.test(string);
6255
+ }
6256
+ /**
6257
+ * check whether the given value is a valid percentage of default locale
6258
+ *
6259
+ * @param {String} string
6260
+ * @returns {Boolean}
6261
+ */
6262
+ #isDefaultPercentage(string) {
6263
+ return this.#isValidPercentage(this.defaultLocale(), string);
6264
+ }
6265
+ }
6266
+ class StringValidator extends BaseValidator {
6267
+ constructor() {
6268
+ super("string");
6269
+ }
6270
+ /**
6271
+ *
6272
+ * @override
6273
+ */
6274
+ buildConfig() {
6275
+ const options = Config.getOptions();
6276
+ this.addToConfig("mockChars", options?.qaMock);
6277
+ this.addToConfig("resource", Config.getResourceBundle(), {});
6278
+ this.addToConfig(
6279
+ "garbledChars",
6280
+ Config.getGarbledChars()?.filter((v) => String(v).trim()).filter(Boolean),
6281
+ []
6282
+ );
6283
+ }
6284
+ /**
6285
+ *
6286
+ * @override
6287
+ */
6288
+ isInternationalized(string) {
6289
+ const cleanedString = string.trim().replace(/\s*:\s*$/, "");
6290
+ const resources = this.getConfig()?.resource?.[this.defaultLocale()];
6291
+ return resources?.includes(string) || resources?.includes(cleanedString);
6292
+ }
6293
+ /**
6294
+ *
6295
+ * @override
6296
+ */
6297
+ validate(string) {
6298
+ return typeof string === "string";
6299
+ }
6300
+ /**
6301
+ * to check if the string is a DNT string
6302
+ *
6303
+ * @param {String} string
6304
+ * @returns {Boolean}
6305
+ */
6306
+ isDntText(string) {
6307
+ return this.getConfig()?.resource?.dnt?.includes(string);
6308
+ }
6309
+ /**
6310
+ * to check if the string can be treated as an auto ingored string
6311
+ *
6312
+ * @param {String} string
6313
+ * @returns {Boolean}
6314
+ */
6315
+ isAutoIgnoredText(string) {
6316
+ return this.isDefaultLocale() || this.isUserInputText(string) || this.isEmailText(string) || this.isUrlText(string);
6317
+ }
6318
+ /**
6319
+ * to check if the string is an Ignored string
6320
+ *
6321
+ * @param {String} string
6322
+ * @returns {Boolean}
6323
+ */
6324
+ isIgnoredText(string) {
6325
+ return this.getConfig()?.resource?.ignore?.includes(string);
6326
+ }
6327
+ /**
6328
+ * to check if the string is a user input
6329
+ *
6330
+ * @param {String} string
6331
+ * @returns {Boolean}
6332
+ */
6333
+ isUserInputText(string) {
6334
+ return string.startsWith(USER_INPUT_PRE_FIX);
6335
+ }
6336
+ /**
6337
+ * to check if the string is a email string
6338
+ *
6339
+ * @param {String} string
6340
+ * @returns {Boolean}
6341
+ */
6342
+ isEmailText(string) {
6343
+ return PATTERNS.EMAIL.test(string);
6344
+ }
6345
+ /**
6346
+ * to check if the string is a Url string
6347
+ *
6348
+ * @param {String} string
6349
+ * @returns {Boolean}
6350
+ */
6351
+ isUrlText(string) {
6352
+ return PATTERNS.URL.test(string);
6353
+ }
6354
+ /**
6355
+ * to check if the string is fully localized in QA
6356
+ *
6357
+ * @param {String} string
6358
+ * @returns {Boolean}
6359
+ */
6360
+ isFullQaLanguageText(string) {
6361
+ const config = this.getConfig();
6362
+ return (string.slice(0, 2) === config?.mockChars?.prefix || string.slice(0, 2) === config?.mockChars?.prefix.toUpperCase()) && string.slice(-2) === config?.mockChars.suffix;
6363
+ }
6364
+ /**
6365
+ * to check if the string is a DNT string
6366
+ *
6367
+ * @param {String} string
6368
+ * @returns {Boolean}
6369
+ */
6370
+ isPartialQaLanguageText(string) {
6371
+ const config = this.getConfig();
6372
+ return string.slice(0, 2) === config?.mockChars.prefix || string.slice(0, 2) === config?.mockChars.prefix.toUpperCase() || string.slice(-2) === config?.mockChars.suffix;
6373
+ }
6374
+ /**
6375
+ * to check if the string has encoding issues
6376
+ *
6377
+ * @param {String} string
6378
+ * @returns {Boolean}
6379
+ */
6380
+ hasEncodingIssue(string) {
6381
+ return this.getConfig()?.garbledChars?.length > 0 && this.getConfig().garbledChars.some((char) => string.includes(char));
6382
+ }
6383
+ /**
6384
+ * to check if the string is a partially localized
6385
+ *
6386
+ * @param {String} string
6387
+ * @returns {Promise<Boolean>}
6388
+ */
6389
+ isPartiallyLocalizedText(string) {
6390
+ return this.#detectLanguageCode(string) === this.currentLanguage();
6391
+ }
6392
+ /**
6393
+ * detects given string language code
6394
+ * @param {String} string
6395
+ */
6396
+ #detectLanguageCode(string) {
6397
+ const matches = Object.keys(detectTextLangEx(string)?.scores || {}).filter(Boolean) || [];
6398
+ const currLang = this.currentLanguage();
6399
+ if (matches.length) {
6400
+ return matches.includes(currLang) ? currLang : matches[0];
6401
+ }
6402
+ return this.defaultLanguage();
6403
+ }
6404
+ /**
6405
+ * to check if the string is a fully localized
6406
+ *
6407
+ * @param {String} string
6408
+ * @returns {Boolean}
6409
+ */
6410
+ isLocalized(string) {
6411
+ const cleanedString = string.trim().replace(/\s*:\s*$/, "");
6412
+ const resources = this.getConfig()?.resource?.[this.currentLocale()];
6413
+ return resources?.includes(string) || resources?.includes(cleanedString);
6414
+ }
6415
+ }
6416
+ class TimeValidator extends BaseValidator {
6417
+ constructor() {
6418
+ super("time");
6419
+ }
6420
+ /**
6421
+ *
6422
+ * @override
6423
+ */
6424
+ validate(string) {
6425
+ return this.#isDefaultTime(string) || this.isInternationalized(string);
6426
+ }
6427
+ /**
6428
+ *
6429
+ * @override
6430
+ */
6431
+ isInternationalized(string) {
6432
+ return this.#isValidTime(
6433
+ this.isQaLocale() ? this.defaultLocale() : this.currentLocale(),
6434
+ string
6435
+ );
6436
+ }
6437
+ /**
6438
+ *
6439
+ * @override
6440
+ */
6441
+ buildConfig() {
6442
+ }
6443
+ #isValidTime(locale, string) {
6444
+ return this.#verifyUsingGlobalize(locale, string) || this.#verifyUsingLuxon(locale, string) || this.#verifyUsingChrono(locale, string);
6445
+ }
6446
+ #isDefaultTime(string) {
6447
+ return this.#isValidTime(this.defaultLocale(), string);
6448
+ }
6449
+ #verifyUsingGlobalize(locale, string) {
6450
+ const formats = ["short", "medium", "long", "full"];
6451
+ for (let format of formats) {
6452
+ const timeParser = this.getGlobalize(locale).dateParser({ time: format });
6453
+ if (timeParser(string)) {
6454
+ return true;
6455
+ }
6456
+ }
6457
+ return false;
6458
+ }
6459
+ #verifyUsingLuxon(locale, string) {
6460
+ const formats = [
6461
+ DateTime.TIME_SIMPLE,
6462
+ DateTime.TIME_WITH_SECONDS,
6463
+ DateTime.TIME_WITH_SHORT_OFFSET,
6464
+ DateTime.TIME_WITH_LONG_OFFSET,
6465
+ DateTime.TIME_24_SIMPLE,
6466
+ DateTime.TIME_24_WITH_LONG_OFFSET,
6467
+ DateTime.TIME_24_WITH_SECONDS,
6468
+ DateTime.TIME_24_WITH_SHORT_OFFSET,
6469
+ "t",
6470
+ "T",
6471
+ "tt",
6472
+ "TT"
6473
+ ];
6474
+ for (let format of formats) {
6475
+ const result = isValid(locale, format, string);
6476
+ if (result) {
6477
+ return true;
6478
+ }
6479
+ }
6480
+ return false;
6481
+ }
6482
+ #verifyUsingChrono(locale, string) {
6483
+ return isValid$1(
6484
+ this.isQaLocale() ? this.defaultLocale() : locale,
6485
+ string
6486
+ );
6487
+ }
6488
+ }
6489
+ class Validator {
6490
+ static #issuesMap = {};
6491
+ /**
6492
+ * Collection of methods to validate and determine string issues
6493
+ * @type {StringValidator}
6494
+ */
6495
+ static #string;
6496
+ /**
6497
+ * Collection of methods to validate and determine number issues
6498
+ * @type {NumberValidator}
6499
+ */
6500
+ static #number;
6501
+ /**
6502
+ * Collection of methods to validate and determine date issues
6503
+ * @type {DateValidator}
6504
+ */
6505
+ static #date;
6506
+ /**
6507
+ * Collection of methods to validate and determine date issues
6508
+ * @type {TimeValidator}
6509
+ */
6510
+ static #time;
6511
+ /**
6512
+ * Collection of methods to validate and determine dateTime issues
6513
+ * @type {DateTimeValidator}
6514
+ */
6515
+ static #dateTime;
6516
+ /**
6517
+ * Collection of methods to validate and determine currency issues
6518
+ * @type {CurrencyValidator}
6519
+ */
6520
+ static #currency;
6521
+ /**
6522
+ * Collection of methods to validate and determine percentage issues
6523
+ * @type {PercentageValidator}
6524
+ */
6525
+ static #percentage;
6526
+ static load() {
6527
+ Validator.#string = new StringValidator();
6528
+ Validator.#number = new NumberValidator();
6529
+ Validator.#date = new DateValidator();
6530
+ Validator.#time = new TimeValidator();
6531
+ Validator.#dateTime = new DateTimeValidator();
6532
+ Validator.#currency = new CurrencyValidator();
6533
+ Validator.#percentage = new PercentageValidator();
6534
+ }
6535
+ /**
6536
+ *
6537
+ * @param {String} string
6538
+ * @returns {String} issue type
6539
+ */
6540
+ static getIssueType(string) {
6541
+ const locale = Config.getLocale();
6542
+ if (locale) {
6543
+ let type = I18N_STATUS.UNTRANSLATED;
6544
+ if (!Validator.#issuesMap[locale]) {
6545
+ Validator.#issuesMap[locale] = {};
6546
+ }
6547
+ if (Validator.#issuesMap[locale][string]) {
6548
+ return Validator.#issuesMap[locale][string];
6549
+ }
6550
+ if (this.#string.isAutoIgnoredText(string)) {
6551
+ type = I18N_STATUS.AUTO_IGNORE;
6552
+ } else if (this.#string.isDntText(string)) {
6553
+ type = I18N_STATUS.DNT;
6554
+ } else if (this.#string.isIgnoredText(string)) {
6555
+ type = I18N_STATUS.IGNORE;
6556
+ } else if (this.#string.hasEncodingIssue(string)) {
6557
+ type = I18N_STATUS.ENCODING_ISSUE;
6558
+ } else if (this.#currency.validate(string)) {
6559
+ type = this.#currency.isInternationalized(string) ? I18N_STATUS.CURRENCY_LOCALIZED : I18N_STATUS.CURRENCY_NOT_LOCALIZED;
6560
+ } else if (this.#percentage.validate(string)) {
6561
+ type = this.#percentage.isInternationalized(string) ? I18N_STATUS.PERCENTAGE_LOCALIZED : I18N_STATUS.PERCENTAGE_NOT_LOCALIZED;
6562
+ } else if (this.#number.validate(string)) {
6563
+ type = this.#number.isInternationalized(string) ? I18N_STATUS.NUMBER_LOCALIZED : I18N_STATUS.NUMBER_NOT_LOCALIZED;
6564
+ } else if (this.#date.validate(string)) {
6565
+ type = this.#date.isInternationalized(string) ? I18N_STATUS.DATE_LOCALIZED : I18N_STATUS.DATE_NOT_LOCALIZED;
6566
+ } else if (this.#time.validate(string)) {
6567
+ type = this.#time.isInternationalized(string) ? I18N_STATUS.TIME_LOCALIZED : I18N_STATUS.TIME_NOT_LOCALIZED;
6568
+ } else if (this.#dateTime.validate(string)) {
6569
+ type = this.#dateTime.isInternationalized(string) ? I18N_STATUS.DATE_TIME_LOCALIZED : I18N_STATUS.DATE_TIME_NOT_LOCALIZED;
6570
+ } else if (this.#string.validate(string)) {
6571
+ if (this.#string.isQaLocale()) {
6572
+ if (this.#string.isFullQaLanguageText(string)) {
6573
+ type = I18N_STATUS.STRING_LOCALIZED;
6574
+ } else if (this.#string.isPartialQaLanguageText(string)) {
6575
+ type = I18N_STATUS.STRING_PARTIALLY_LOCALIZED;
6576
+ } else {
6577
+ type = I18N_STATUS.STRING_NOT_LOCALIZED;
6578
+ }
6579
+ } else if (!this.#string.isDefaultLocale() && this.#string.isSupportedLocale()) {
6580
+ if (this.#string.isLocalized(string)) {
6581
+ type = I18N_STATUS.STRING_LOCALIZED;
6582
+ } else if (this.#string.isPartiallyLocalizedText(string)) {
6583
+ type = I18N_STATUS.STRING_PARTIALLY_LOCALIZED;
6584
+ } else if (!this.#string.isInternationalized(string)) {
6585
+ type = I18N_STATUS.STRING_NOT_LOCALIZED;
6586
+ } else {
6587
+ type = I18N_STATUS.UNTRANSLATED;
6588
+ }
6589
+ }
6590
+ } else if (this.#string.isDefaultLocale()) {
6591
+ type = I18N_STATUS.AUTO_IGNORE;
6592
+ }
6593
+ Validator.#issuesMap[locale][string] = type;
6594
+ return type;
6595
+ }
6596
+ return I18N_STATUS.UNTRANSLATED;
6597
+ }
6598
+ }
6599
+ class Resource {
6600
+ static load() {
6601
+ const bundle = {};
6602
+ if (Config.getOptions()?.l10nResourcePath) {
6603
+ const resourcePath = joinPaths(
6604
+ process.cwd(),
6605
+ Config.getOptions()?.l10nResourcePath
6606
+ );
6607
+ if (fileExists(resourcePath)) {
6608
+ Resource.#processFile(resourcePath, bundle);
6609
+ } else if (dirExists(resourcePath)) {
6610
+ for (const file of getDirContents(resourcePath)) {
6611
+ const filePath = joinPaths(resourcePath, file);
6612
+ Resource.#processFile(filePath, bundle);
6613
+ }
6614
+ } else {
6615
+ console.error(`${resourcePath} invalid resource path`);
6616
+ return;
6617
+ }
6618
+ Config.setResourceBundle(bundle);
6619
+ }
6620
+ }
6621
+ static #processFile(filePath, bundle) {
6622
+ const locale = Config.getLocale(), defaultLocale = Config.getDefaultLocale(), fileContent = getFileContent(filePath), ext = getFileExtenstion(filePath);
6623
+ if (RES_FILE_EXTENSIONS.includes(ext)) {
6624
+ if (!fileContent) {
6625
+ console.error(`${filePath} is empty or invalid`);
6626
+ return;
6627
+ }
6628
+ if (filePath.toLowerCase().includes("dnt")) {
6629
+ bundle["dnt"] = fileContent.split(/\r?\n/);
6630
+ } else if (filePath.toLowerCase().includes("ignore")) {
6631
+ bundle["ignore"] = fileContent.split(/\r?\n/);
6632
+ } else if (filePath.includes(locale)) {
6633
+ const lines = fileContent.split(/\r?\n/);
6634
+ bundle[locale] = lines.map(removeHtmlTags);
6635
+ } else if (filePath.includes(defaultLocale)) {
6636
+ bundle[defaultLocale] = fileContent.split(/\r?\n/);
6637
+ }
6638
+ }
6639
+ }
6640
+ }
6641
+ function removeHtmlTags(str) {
6642
+ const htmlTagPattern = /<\/?[^>]+>/gi;
6643
+ return str.replace(htmlTagPattern, "");
6644
+ }
6645
+ const loadDependencies = () => {
6646
+ if (Config.getDriver() && !Config.isLoaded() && Config.getLocale()) {
6647
+ Config.build();
6648
+ Resource.load();
6649
+ Validator.load();
6650
+ Reports.setup();
6651
+ Cache.init();
6652
+ Config.setIsLoaded(true);
6653
+ }
6654
+ };
6655
+ const getRootProjectMainDir = () => {
6656
+ const maxDepth = 10;
6657
+ let currentDir = process.cwd(), currDepth = 0;
6658
+ while (currDepth < maxDepth) {
6659
+ const packageJsonPath = joinPaths(currentDir, "package.json");
6660
+ if (fileExists(packageJsonPath)) {
6661
+ const src = getFileContent(packageJsonPath);
6662
+ const json = JSON.parse(src);
6663
+ const deps = {
6664
+ ...json?.dependencies || {},
6665
+ ...json?.devDependencies || {},
6666
+ ...json?.peerDependencies || {}
6667
+ };
6668
+ if (json.name !== "@zeesoft/i18n-verify" && JSON.stringify(deps).includes('"@zeesoft/i18n-verify"')) {
6669
+ break;
6670
+ }
6671
+ }
6672
+ currentDir = getDirPath(currentDir);
6673
+ currDepth++;
6674
+ }
6675
+ return currentDir;
6676
+ };
6677
+ const getRootProjectPackageJson = (rootProjectPath = getRootProjectMainDir()) => getFileContent(joinPaths(rootProjectPath, "package.json"));
6678
+ const getRootProjectName = () => getRootProjectPackageJson()?.match(/"name": "([^"]+)",/)?.[1] || "";
6679
+ const getConfigFilePath = () => joinPaths(process.cwd(), CONFIG_FILE_NAME);
6680
+ const getConfigTemplate = (type = "") => `{
6681
+ "appName": "${getRootProjectName()}",
6682
+ "type": "${type}", // set automation framework type ${arr2Txt(
6683
+ Object.values(SYSTEM_TYPES)
6684
+ )}
3601
6685
  "qaLocale": "", // set the qa locale used in your project
3602
6686
  "l10nResourcePath": "./l10nResources", // set the dir path of l10n resources
3603
6687
  "l10nReportsPath": "./l10nReports/", // set the dir path of l10n reports
@@ -3607,6 +6691,752 @@
3607
6691
  "prefix": "à_",
3608
6692
  "suffix": "_海"
3609
6693
  },
3610
- "mode": "${N.I18N}", // should be one of the following: ${Object.values(N).join(", ")}
6694
+ "mode": "${RUN_MODE.I18N}", // should be one of the following: ${Object.values(RUN_MODE).join(", ")}
3611
6695
  "garbledChars": [""]
3612
- }`,wt=()=>{const i=ft();if(!x(i))throw new Error(`${C} file is missing. Please add the file in your project root dir`);let e=M(i);if(!e)throw new Error(`invalid ${C} file. Please add valid file in your project root dir`);e=e.replace(/\/\/.+$/gm,"");try{e=JSON.parse(e)}catch{throw new Error(`invalid ${C} file. Please add valid file in your project root dir`)}return e},Lt=i=>{if(typeof i!="object"||Object.keys(i).length<1)throw new Error(`empty ${C} file`);const e=[];if(!nt(["l10nResourcePath","l10nReportsPath","supportedLocales","defaultLocale","type","mode"],i,e))throw new Error(`following properties are missing in ${C} file: ${fe(e)}`);if(!Object.values(z).includes(i?.type||""))throw new Error(`${C} has invalid system type`);if(!Object.values(N).includes(i?.mode||""))throw new Error(`${C} has invalid mode option`)},yt=(i,e="")=>{i&&!x(i)&&q(i,vt(e))};class c{static#e;static#t;static#r;static#a;static#i;static#n;static#s;static#o;static#l;static#c;static#d;static init(){try{const e=wt();Lt(e),this.#r=e?.type,this.#a=e?.mode,this.#n=e?.qaLocale,this.#c=e?.appName,this.#s=e,this.#l=0,this.getGarbledChars()}catch(e){throw f.error(e.message),e}}static build(){this.#e=rt(this.#r,this.#e),this.resetCounter()}static getGarbledChars(){return[...this.#s.garbledChars||[],...Te]}static getL10nReportsPath(){return this.#s.l10nReportsPath}static setDriver(e){this.#e=e}static setType(e){this.#r=e}static setLocale(e){this.#i=e}static setOptions(e){this.#s=e}static getExecutor(){if(c.#t)return c.#t;if(!c.#e)throw new Error("Unable to initialize process executor, driver is missing");return this.#t=new Le(this.#e),this.#t}static getDriver(){return this.#e}static getLocale(){return this.#i}static getDefaultLocale(){return this.#s.defaultLocale}static getType(){return this.#r}static getOptions(){return this.#s}static setQALocale(e){this.#n=e}static getQALocale(){return this.#n}static setResourceBundle(e){this.#o=e}static getResourceBundle(e){return this.#o?.[e]||this.#o||[]}static incrementCounter(){this.#l++}static resetCounter(){this.#l=0}static getSSCount(e=!1){return e?++this.#l:this.#l}static getMode(){return this.#a}static isSanityRun(){return this.#a===N.SANITY}static isI18nVerificationRun(){return this.#a===N.I18N}static isContextRun(){return this.#a===N.CONTEXT}static getAppName(){return this.#c}static isLoaded(){return this.#d}static setIsLoaded(e){this.#d=e}}class oe{#e;#t;#r;#a;#i=[];#n;#s;#o;#l;#c;constructor(e,t,a,n,s){this.#e=e,this.#t=t,this.#r=a,this.#c=n,this.#a=s}async run(){try{await this.#p(),this.shouldCollectStrings()?await this.#d():await this.#m()}catch(e){f.error("unable to run the process",e)}finally{await this.#g()}}async process(e,t,a,n){throw new Error("should be implemeneted by the child class")}shouldCollectStrings(){return!0}async preProcess(){}async postProcess(){}async captureScreen(e){try{return await this.#e.captureScreenshot(e),f.debug("reviewed image has been saved"),!0}catch{return f.error("unable to capture screenshot"),!1}}getBaseImageName(){return this.#s}getDescription(){return this.#a}getVerificationArea(){return this.#t}getVerificationAreaEl(){return this.#o}getVerificationAreaOffsets(){return this.#l}getDriver(){return this.#e}async getElementOffsets(e){const t=await this.#e.getElementDimension(e);return{x:t[0],y:t[1],height:t[2],width:t[3]}}async#d(){this.#i.length?(await this.#w(),await this.#L()):f.debug("No locators provided")}async#m(){await this.process(this.#a)}async#p(){this.#h(),this.#E(),await this.#v(),await this.#f(),await this.preProcess()}async#g(){await this.postProcess()}#h(){const e=this.#t||"";if(this.#r?.length>0)for(const t of this.#r)this.#i.push(e+t);this.#c&&(this.#n=e!==""?e+K:K,this.#i.push(this.#n.toString()))}#E(){this.#s=`${c.getSSCount(!0).toString().padStart(3,"0")}_${this.#a.replace(/[^\w\s]/gi,"").replace(/\s+/g,"")}.png`}async#f(){const e=g(l.reviewedReports(),this.#s);await this.captureScreen(e)}async#v(){if(this.#o=await this.#e.getElement(this.#t),this.#o)this.#l=await this.getElementOffsets(this.#o);else throw new Error("invalid verification area selector is supplied")}async#w(){let e=!1;for(const t of this.#i){const a=await this.#e.getElements(t,!0);if(a?.length){!e&&(e=!0);for(const n of a)await this.#u(n,!0)}}e||f.debug("No UI elements found from the provided locators")}async#L(){if(await this.#e.checkIfIframeIsPresent()){const e=await this.#e.getElements("//iframe");f.debug(`Total ${e.length} iframes are located on the ${this.#a}`);for(let t=0;t<e.length;t++){const a=e[t],n=await this.getElementOffsets(a);f.debug(`Switching to iFrame: ${t}`),await this.#e.switchToIFrame(t,a),this.#e.pause(1);const s=await this.#e.getElement("//body");await this.#e.isElementPresent(s);let o=!1;if(!await this.#e.checkIfIframeBodyIsEmpty()){const u=await this.#e.getElements(K,!0);if(u?.length)for(const h of u){const p=await this.#u(h,!0,n,t);!o&&p&&(o=!0)}}!o&&f.debug("No valid UI elements found in the iFrame"),await this.#e.switchToParentFrame()}}}async#u(e,t=!1,a,n){if(await this.#y(e)){const s=t?await this.#e.getElementStrings(e):[await this.#e.getElementString(e)];if(s?.length){for(const o of s)try{await this.process(o,e,a,n)}catch(u){f.error(`unable to process the ${n?`iframe-[${n}] `:""}string "${o}"`,u)}return!0}else return!1}else return!1}async#y(e){return e&&await this.#e.isElementDisplayed(e)}}class It extends oe{#e={screenshot:"",category:"",fileName:"",bookmark:!0,pageTitle:"",strings:{}};#t=0;#r="";constructor(...e){super(...e)}async preProcess(){this.#a(),this.#i(),this.#n(),this.#s(),this.#o()}async process(e,t,a){l.incrementCount(r.REVIEWED,e,this.getBaseImageName(),this.getDescription()),f.debug(`context creation for "${e}"`),await this.#d(e,t,a)}async postProcess(){this.#l();const e=this.#c();q(g(l.getContextPath(),`${this.#e.fileName}.json`),JSON.stringify(e)),B.incrementCountByType("context")}#a(){this.#t=ae(l.getContextPath()).length+1}#i(){this.#e.category=this.getDescription()}#n(){this.#e.pageTitle=`TC-${c.getAppName()}-${this.getDescription().trim().slice(0,2).toUpperCase()}-${`${this.#t}`.padStart(3,"0")}`}#s(){this.#e.fileName=`${O(c.getAppName())}-${`${this.#t}`.padStart(3,"0")}`}#o(){this.#r=`${O(c.getAppName())}_${`${this.#t}`.padStart(3,"0")}`}#l(){this.#e.screenshot=`data:image/png;base64,${_e(g(l.reviewedReports(),this.getBaseImageName()))}`}#c(){return{[G.BOOKMARK]:this.#e.bookmark,[G.CATEGORY]:this.#e.category,[G.FILE_NAME]:this.#e.fileName,[G.SCREENSHOT]:this.#e.screenshot,[G.STRINGS]:JSON.stringify(this.#e.strings)}}async#d(e,t,a){const n=await this.getElementOffsets(t),s=`${this.#r}_${`${Object.keys(this.#e.strings).length+1}`.padStart(3,"0")}`;if(a&&Object.keys(a||{}).length){const o=a,u=["x","y"];for(const h of u)h in n&&h in o&&(n[h]+=o[h])}this.#e.strings[s]={text:e,coordinates:{...n}}}}class ge{static async drawRectangle(e,t,a){const n=e?.x-2,s=e?.y-2,o=e?.width+2,u=e?.height+2,h=2;try{const p=await J.read(a),U=J.cssColorToHex(t);this.drawRectangleOutline(p,n,s,o,u,U,h);const T=Z.dirname(a),L=await p.getBufferAsync(J.MIME_PNG);v.existsSync(T)||(f.debug("folder not found"),v.mkdirSync(T,{recursive:!0})),v.writeFileSync(a,L)}catch(p){f.error(`Error: ${p}`)}}static async drawRectangleOutline(e,t,a,n,s,o,u){for(let h=t;h<t+n;h++)for(let p=0;p<u;p++)e.setPixelColor(o,h,a+p),e.setPixelColor(o,h,a+s-1-p);for(let h=a;h<a+s;h++)for(let p=0;p<u;p++)e.setPixelColor(o,t+p,h),e.setPixelColor(o,t+n-1-p,h)}}class bt extends oe{constructor(...e){super(...e)}async process(e,t,a){if(typeof e!="string"||!e||Number(e)===0)return;const n=g(l.reviewedReports(e,this.getBaseImageName()),this.getBaseImageName()),s=y.getIssueType(e),o=g(l[s](e,this.getBaseImageName()),this.getBaseImageName());l.incrementCount(r.REVIEWED,e,this.getBaseImageName(),this.getDescription()),v.existsSync(n)||v.copyFileSync(g(l.reviewedReports(),this.getBaseImageName()),n),v.existsSync(n)&&!v.existsSync(o)&&v.copyFileSync(n,o);const u=this.#a(s,e);l.incrementCount(s,e,o,this.getDescription()),await this.#e(t,u,o,a)}async#e(e,t,a,n){await this.#t(e,t),await this.#r(e,t,a,n)}async#t(e,t){await this.getDriver().onScreenStringHighlight(e,t)}async#r(e,t,a,n){let s;const o=await this.getElementOffsets(e),u=d.GRB_BLUE;if(n){s=n;const h=["x","y"];for(const p of h)p in o&&p in s&&(o[p]=s[p]+o[p])}else s=this.getVerificationAreaOffsets();await ge.drawRectangle(s,u,a),await ge.drawRectangle(o,t,a)}#a(e,t){return f.debug(`"${t}" - ${de[e][1]}${be[e]}\x1B[0m`),de[e][0]}}class St extends oe{constructor(...e){super(...e)}shouldCollectStrings(){return!1}async process(e){f.info(`${e} loaded`);const t=g(l.reviewedReports(e,this.getBaseImageName()),this.getBaseImageName());l.incrementCount(r.REVIEWED,e,t,this.getDescription()),v.existsSync(t)||v.copyFileSync(g(l.reviewedReports(),this.getBaseImageName()),t)}}const Dt=(i,e,t,a,n)=>{switch(c.getMode()){case N.I18N:return new bt(i,e,t,a,n);case N.CONTEXT:return new It(i,e,t,a,n);case N.SANITY:return new St(i,e,t,a,n);default:throw new Error("unsupported runner type")}};class Le{#e;constructor(e){this.#e=e}async start({verificationArea:e,staticLocators:t,useSmartSelector:a,description:n}){await Dt(this.#e,e,t,a,n).run()}}exports.CONFIG_FILE_NAME=C;exports.Config=c;exports.Executor=Le;exports.Logger=f;exports.Reports=l;exports.SYSTEM_TYPES=z;exports.checkAndExportConfig=yt;exports.getRootProjectMainDir=ve;exports.getRootProjectPackageJson=we;exports.joinPaths=g;exports.loadDependencies=ht;
6696
+ }`;
6697
+ const readConfigFile = () => {
6698
+ const rcFilePath = getConfigFilePath();
6699
+ if (!fileExists(rcFilePath)) {
6700
+ throw new Error(
6701
+ `${CONFIG_FILE_NAME} file is missing. Please add the file in your project root dir`
6702
+ );
6703
+ }
6704
+ let rcFile = getFileContent(rcFilePath);
6705
+ if (!rcFile) {
6706
+ throw new Error(
6707
+ `invalid ${CONFIG_FILE_NAME} file. Please add valid file in your project root dir`
6708
+ );
6709
+ }
6710
+ rcFile = rcFile.replace(/\/\/.+$/gm, "");
6711
+ try {
6712
+ rcFile = JSON.parse(rcFile);
6713
+ } catch (ex) {
6714
+ throw new Error(
6715
+ `invalid ${CONFIG_FILE_NAME} file. Please add valid file in your project root dir`
6716
+ );
6717
+ }
6718
+ return rcFile;
6719
+ };
6720
+ const validateConfig = (config) => {
6721
+ if (typeof config !== "object" || Object.keys(config).length < 1) {
6722
+ throw new Error(`empty ${CONFIG_FILE_NAME} file`);
6723
+ }
6724
+ const missingKeys = [];
6725
+ if (!allPropertyExists(
6726
+ [
6727
+ "l10nResourcePath",
6728
+ "l10nReportsPath",
6729
+ "supportedLocales",
6730
+ "defaultLocale",
6731
+ "type",
6732
+ "mode"
6733
+ ],
6734
+ config,
6735
+ missingKeys
6736
+ )) {
6737
+ throw new Error(
6738
+ `following properties are missing in ${CONFIG_FILE_NAME} file: ${arr2Txt(
6739
+ missingKeys
6740
+ )}`
6741
+ );
6742
+ }
6743
+ if (!Object.values(SYSTEM_TYPES).includes(config?.type || "")) {
6744
+ throw new Error(`${CONFIG_FILE_NAME} has invalid system type`);
6745
+ }
6746
+ if (!Object.values(RUN_MODE).includes(config?.mode || "")) {
6747
+ throw new Error(`${CONFIG_FILE_NAME} has invalid mode option`);
6748
+ }
6749
+ };
6750
+ const checkAndExportConfig = (filePath, type = "") => {
6751
+ if (filePath && !fileExists(filePath)) {
6752
+ saveToFile(filePath, getConfigTemplate(type));
6753
+ }
6754
+ };
6755
+ class Config {
6756
+ static #driver;
6757
+ static #executor;
6758
+ static #type;
6759
+ static #mode;
6760
+ static #locale;
6761
+ static #qaLocale;
6762
+ static #options;
6763
+ static #resources;
6764
+ static #ssCount;
6765
+ static #appName;
6766
+ static #isLoaded;
6767
+ static init() {
6768
+ try {
6769
+ const config = readConfigFile();
6770
+ validateConfig(config);
6771
+ this.#type = config?.type;
6772
+ this.#mode = config?.mode;
6773
+ this.#qaLocale = config?.qaLocale;
6774
+ this.#appName = config?.appName;
6775
+ this.#options = config;
6776
+ this.#ssCount = 0;
6777
+ this.getGarbledChars();
6778
+ } catch (ex) {
6779
+ Logger$1.error(ex.message);
6780
+ throw ex;
6781
+ }
6782
+ }
6783
+ static build() {
6784
+ this.#driver = build$1(this.#type, this.#driver);
6785
+ this.resetCounter();
6786
+ }
6787
+ static getGarbledChars() {
6788
+ return [...this.#options.garbledChars || [], ...GARBLED_CHARACTERS];
6789
+ }
6790
+ static getL10nReportsPath() {
6791
+ return this.#options.l10nReportsPath;
6792
+ }
6793
+ static setDriver(driver) {
6794
+ this.#driver = driver;
6795
+ }
6796
+ static setType(type) {
6797
+ this.#type = type;
6798
+ }
6799
+ static setLocale(locale) {
6800
+ this.#locale = locale;
6801
+ }
6802
+ static setOptions(options) {
6803
+ this.#options = options;
6804
+ }
6805
+ static getExecutor() {
6806
+ if (Config.#executor) {
6807
+ return Config.#executor;
6808
+ }
6809
+ if (!Config.#driver) {
6810
+ throw new Error(
6811
+ "Unable to initialize process executor, driver is missing"
6812
+ );
6813
+ }
6814
+ this.#executor = new Executor(this.#driver);
6815
+ return this.#executor;
6816
+ }
6817
+ static getDriver() {
6818
+ return this.#driver;
6819
+ }
6820
+ static getLocale() {
6821
+ return this.#locale;
6822
+ }
6823
+ static getDefaultLocale() {
6824
+ return this.#options.defaultLocale;
6825
+ }
6826
+ static getType() {
6827
+ return this.#type;
6828
+ }
6829
+ static getOptions() {
6830
+ return this.#options;
6831
+ }
6832
+ static setQALocale(locale) {
6833
+ this.#qaLocale = locale;
6834
+ }
6835
+ static getQALocale() {
6836
+ return this.#qaLocale;
6837
+ }
6838
+ static setResourceBundle(resources) {
6839
+ this.#resources = resources;
6840
+ }
6841
+ static getResourceBundle(value) {
6842
+ return this.#resources?.[value] || this.#resources || [];
6843
+ }
6844
+ static incrementCounter() {
6845
+ this.#ssCount++;
6846
+ }
6847
+ static resetCounter() {
6848
+ this.#ssCount = 0;
6849
+ }
6850
+ static getSSCount(incrementCount = false) {
6851
+ return incrementCount ? ++this.#ssCount : this.#ssCount;
6852
+ }
6853
+ static getMode() {
6854
+ return this.#mode;
6855
+ }
6856
+ static isSanityRun() {
6857
+ return this.#mode === RUN_MODE.SANITY;
6858
+ }
6859
+ static isI18nVerificationRun() {
6860
+ return this.#mode === RUN_MODE.I18N;
6861
+ }
6862
+ static isContextRun() {
6863
+ return this.#mode === RUN_MODE.CONTEXT;
6864
+ }
6865
+ static getAppName() {
6866
+ return this.#appName;
6867
+ }
6868
+ static isLoaded() {
6869
+ return this.#isLoaded;
6870
+ }
6871
+ static setIsLoaded(value) {
6872
+ this.#isLoaded = value;
6873
+ }
6874
+ }
6875
+ class BaseRunner {
6876
+ /**
6877
+ * @type {import('../../driver/baseDriver.js').default}
6878
+ */
6879
+ #driver;
6880
+ /**
6881
+ * @type {String}
6882
+ */
6883
+ #verificationArea;
6884
+ /**
6885
+ * @type {Array<String>}
6886
+ */
6887
+ #selectors;
6888
+ /**
6889
+ * @type {String}
6890
+ */
6891
+ #description;
6892
+ /**
6893
+ * @type {Array<String>}
6894
+ */
6895
+ #preparedSelectors = [];
6896
+ /**
6897
+ * @type {String}
6898
+ */
6899
+ #preparedSelector;
6900
+ /**
6901
+ * @type {String}
6902
+ */
6903
+ #baseImageName;
6904
+ /**
6905
+ * @type {Element}
6906
+ */
6907
+ #verificationAreaEl;
6908
+ /**
6909
+ * @type {{x:Number, y: Number, height: Number, width: Number}}
6910
+ */
6911
+ #verificationAreaOffsets;
6912
+ /**
6913
+ * @type {Boolean}
6914
+ */
6915
+ #useSmartSelector;
6916
+ constructor(driver, verificationArea, selectors, useSmartSelector, description) {
6917
+ this.#driver = driver;
6918
+ this.#verificationArea = verificationArea;
6919
+ this.#selectors = selectors;
6920
+ this.#useSmartSelector = useSmartSelector;
6921
+ this.#description = description;
6922
+ }
6923
+ async run() {
6924
+ try {
6925
+ await this.#preRun();
6926
+ if (this.shouldCollectStrings()) {
6927
+ await this.#executeStringProcess();
6928
+ } else {
6929
+ await this.#executePageProcess();
6930
+ }
6931
+ } catch (ex) {
6932
+ Logger$1.error("unable to run the process", ex);
6933
+ } finally {
6934
+ await this.#postRun();
6935
+ }
6936
+ }
6937
+ /**---------------------public helper methods----------------------*/
6938
+ // should be implemented by child classes
6939
+ async process(_string, _element, _offsets, _frameId) {
6940
+ throw new Error("should be implemeneted by the child class");
6941
+ }
6942
+ // can be implemented by child classes to avoid collecting strings and looping to each item
6943
+ shouldCollectStrings() {
6944
+ return true;
6945
+ }
6946
+ // can be implemented by child classes to configure dependencies
6947
+ async preProcess() {
6948
+ }
6949
+ // can be implemented by child classes to perform cleanup tasks
6950
+ async postProcess() {
6951
+ }
6952
+ async captureScreen(imagePath) {
6953
+ try {
6954
+ await this.#driver.captureScreenshot(imagePath);
6955
+ Logger$1.debug("reviewed image has been saved");
6956
+ return true;
6957
+ } catch (ex) {
6958
+ Logger$1.error("unable to capture screenshot");
6959
+ return false;
6960
+ }
6961
+ }
6962
+ getBaseImageName() {
6963
+ return this.#baseImageName;
6964
+ }
6965
+ getDescription() {
6966
+ return this.#description;
6967
+ }
6968
+ getVerificationArea() {
6969
+ return this.#verificationArea;
6970
+ }
6971
+ getVerificationAreaEl() {
6972
+ return this.#verificationAreaEl;
6973
+ }
6974
+ getVerificationAreaOffsets() {
6975
+ return this.#verificationAreaOffsets;
6976
+ }
6977
+ getDriver() {
6978
+ return this.#driver;
6979
+ }
6980
+ async getElementOffsets(element) {
6981
+ const offset = await this.#driver.getElementDimension(element);
6982
+ return {
6983
+ x: offset[0],
6984
+ y: offset[1],
6985
+ height: offset[2],
6986
+ width: offset[3]
6987
+ };
6988
+ }
6989
+ /**---------------------private helper methods----------------------*/
6990
+ async #executeStringProcess() {
6991
+ if (this.#preparedSelectors.length) {
6992
+ await this.#processLocatorElements();
6993
+ await this.#processIFrames();
6994
+ } else {
6995
+ Logger$1.debug("No locators provided");
6996
+ }
6997
+ }
6998
+ async #executePageProcess() {
6999
+ await this.process(this.#description);
7000
+ }
7001
+ async #preRun() {
7002
+ this.#prepareXpaths();
7003
+ this.#prepareBaseImage();
7004
+ await this.#prepareVerificationArea();
7005
+ await this.#collectReviewedImage();
7006
+ await this.preProcess();
7007
+ }
7008
+ async #postRun() {
7009
+ await this.postProcess();
7010
+ }
7011
+ #prepareXpaths() {
7012
+ const verificationArea = this.#verificationArea || "";
7013
+ if (this.#selectors?.length > 0) {
7014
+ for (const selector of this.#selectors) {
7015
+ this.#preparedSelectors.push(verificationArea + selector);
7016
+ }
7017
+ }
7018
+ if (this.#useSmartSelector) {
7019
+ this.#preparedSelector = verificationArea !== "" ? verificationArea + SMART_SELECTOR : SMART_SELECTOR;
7020
+ this.#preparedSelectors.push(this.#preparedSelector.toString());
7021
+ }
7022
+ }
7023
+ #prepareBaseImage() {
7024
+ this.#baseImageName = `${Config.getSSCount(true).toString().padStart(3, "0")}_${this.#description.replace(/[^\w\s]/gi, "").replace(/\s+/g, "")}.png`;
7025
+ }
7026
+ async #collectReviewedImage() {
7027
+ const path2 = joinPaths(Reports.reviewedReports(), this.#baseImageName);
7028
+ await this.captureScreen(path2);
7029
+ }
7030
+ async #prepareVerificationArea() {
7031
+ this.#verificationAreaEl = await this.#driver.getElement(
7032
+ this.#verificationArea
7033
+ );
7034
+ if (this.#verificationAreaEl) {
7035
+ this.#verificationAreaOffsets = await this.getElementOffsets(
7036
+ this.#verificationAreaEl
7037
+ );
7038
+ } else {
7039
+ throw new Error("invalid verification area selector is supplied");
7040
+ }
7041
+ }
7042
+ async #processLocatorElements() {
7043
+ let hasElements = false;
7044
+ for (const locator of this.#preparedSelectors) {
7045
+ const elements = await this.#driver.getElements(locator, true);
7046
+ if (elements?.length) {
7047
+ !hasElements && (hasElements = true);
7048
+ for (const el of elements) {
7049
+ await this.#processElement(el, true);
7050
+ }
7051
+ }
7052
+ }
7053
+ if (!hasElements) {
7054
+ Logger$1.debug("No UI elements found from the provided locators");
7055
+ }
7056
+ }
7057
+ async #processIFrames() {
7058
+ if (await this.#driver.checkIfIframeIsPresent()) {
7059
+ const frames = await this.#driver.getElements("//iframe");
7060
+ Logger$1.debug(
7061
+ `Total ${frames.length} iframes are located on the ${this.#description}`
7062
+ );
7063
+ for (let fID = 0; fID < frames.length; fID++) {
7064
+ const frame = frames[fID];
7065
+ const offsets = await this.getElementOffsets(frame);
7066
+ Logger$1.debug(`Switching to iFrame: ${fID}`);
7067
+ await this.#driver.switchToIFrame(fID, frame);
7068
+ this.#driver.pause(1);
7069
+ const iframeBody = await this.#driver.getElement("//body");
7070
+ await this.#driver.isElementPresent(iframeBody);
7071
+ let hasAtLeastOneString = false;
7072
+ if (!await this.#driver.checkIfIframeBodyIsEmpty()) {
7073
+ const iframeElements = await this.#driver.getElements(
7074
+ SMART_SELECTOR,
7075
+ true
7076
+ );
7077
+ if (iframeElements?.length) {
7078
+ for (const el of iframeElements) {
7079
+ const result = await this.#processElement(el, true, offsets, fID);
7080
+ !hasAtLeastOneString && result && (hasAtLeastOneString = true);
7081
+ }
7082
+ }
7083
+ }
7084
+ !hasAtLeastOneString && Logger$1.debug("No valid UI elements found in the iFrame");
7085
+ await this.#driver.switchToParentFrame();
7086
+ }
7087
+ }
7088
+ }
7089
+ async #processElement(element, collectAll = false, offsets, frameId) {
7090
+ if (await this.#isValidElement(element)) {
7091
+ const strings = collectAll ? await this.#driver.getElementStrings(element) : [await this.#driver.getElementString(element)];
7092
+ if (strings?.length) {
7093
+ for (const string of strings) {
7094
+ try {
7095
+ await this.process(string, element, offsets, frameId);
7096
+ } catch (ex) {
7097
+ Logger$1.error(
7098
+ `unable to process the ${frameId ? `iframe-[${frameId}] ` : ""}string "${string}"`,
7099
+ ex
7100
+ );
7101
+ }
7102
+ }
7103
+ return true;
7104
+ } else {
7105
+ return false;
7106
+ }
7107
+ } else {
7108
+ return false;
7109
+ }
7110
+ }
7111
+ async #isValidElement(element) {
7112
+ return element && await this.#driver.isElementDisplayed(element);
7113
+ }
7114
+ }
7115
+ class ContextRunner extends BaseRunner {
7116
+ #data = {
7117
+ screenshot: "",
7118
+ category: "",
7119
+ fileName: "",
7120
+ bookmark: true,
7121
+ pageTitle: "",
7122
+ strings: {}
7123
+ };
7124
+ #contextCount = 0;
7125
+ #stringIdPrefix = "";
7126
+ constructor(...args) {
7127
+ super(...args);
7128
+ }
7129
+ /**
7130
+ * @override
7131
+ */
7132
+ async preProcess() {
7133
+ this.#determineContextsCounts();
7134
+ this.#configureCategory();
7135
+ this.#configurePageTitle();
7136
+ this.#configureFileName();
7137
+ this.#configureStringId();
7138
+ }
7139
+ /**
7140
+ *
7141
+ * @override
7142
+ */
7143
+ async process(string, element, offsets) {
7144
+ Reports.incrementCount(
7145
+ I18N_STATUS.REVIEWED,
7146
+ string,
7147
+ this.getBaseImageName(),
7148
+ this.getDescription()
7149
+ );
7150
+ Logger$1.debug(`context creation for "${string}"`);
7151
+ await this.#addToContext(string, element, offsets);
7152
+ }
7153
+ /**
7154
+ * @override
7155
+ */
7156
+ async postProcess() {
7157
+ this.#prepareImage();
7158
+ const data2 = this.#getJsonData();
7159
+ saveToFile(
7160
+ joinPaths(Reports.getContextPath(), `${this.#data.fileName}.json`),
7161
+ JSON.stringify(data2)
7162
+ );
7163
+ CacheData.incrementCountByType("context");
7164
+ }
7165
+ #determineContextsCounts() {
7166
+ this.#contextCount = getDirContents(Reports.getContextPath()).length + 1;
7167
+ }
7168
+ #configureCategory() {
7169
+ this.#data.category = this.getDescription();
7170
+ }
7171
+ #configurePageTitle() {
7172
+ this.#data.pageTitle = `TC-${Config.getAppName()}-${this.getDescription().trim().slice(0, 2).toUpperCase()}-${`${this.#contextCount}`.padStart(3, "0")}`;
7173
+ }
7174
+ #configureFileName() {
7175
+ this.#data.fileName = `${toFileNameFormat(Config.getAppName())}-${`${this.#contextCount}`.padStart(3, "0")}`;
7176
+ }
7177
+ #configureStringId() {
7178
+ this.#stringIdPrefix = `${toFileNameFormat(Config.getAppName())}_${`${this.#contextCount}`.padStart(3, "0")}`;
7179
+ }
7180
+ #prepareImage() {
7181
+ this.#data.screenshot = `data:image/png;base64,${imageToBase64(
7182
+ joinPaths(Reports.reviewedReports(), this.getBaseImageName())
7183
+ )}`;
7184
+ }
7185
+ #getJsonData() {
7186
+ return {
7187
+ [CONTEXT_FILE_KEYS.BOOKMARK]: this.#data.bookmark,
7188
+ [CONTEXT_FILE_KEYS.CATEGORY]: this.#data.category,
7189
+ [CONTEXT_FILE_KEYS.FILE_NAME]: this.#data.fileName,
7190
+ [CONTEXT_FILE_KEYS.SCREENSHOT]: this.#data.screenshot,
7191
+ [CONTEXT_FILE_KEYS.STRINGS]: JSON.stringify(this.#data.strings)
7192
+ };
7193
+ }
7194
+ async #addToContext(string, element, offsets) {
7195
+ const elRec = await this.getElementOffsets(element), uniqueId = `${this.#stringIdPrefix}_${`${Object.keys(this.#data.strings).length + 1}`.padStart(3, "0")}`;
7196
+ if (offsets && Object.keys(offsets || {}).length) {
7197
+ const areaRec = offsets;
7198
+ const keysToUpdate = ["x", "y"];
7199
+ for (const key of keysToUpdate) {
7200
+ if (key in elRec && key in areaRec) {
7201
+ elRec[key] += areaRec[key];
7202
+ }
7203
+ }
7204
+ }
7205
+ this.#data.strings[uniqueId] = {
7206
+ text: string,
7207
+ coordinates: {
7208
+ ...elRec
7209
+ }
7210
+ };
7211
+ }
7212
+ }
7213
+ class Graphic {
7214
+ /**
7215
+ * Draws a rectangle on an image.
7216
+ * @param {object} eleRec - The element rectangle object.
7217
+ * @param {string} color - The color of the rectangle border.
7218
+ * @param {string} report_img - The path to the image file.
7219
+ */
7220
+ static async drawRectangle(eleRec, color, report_img) {
7221
+ const rectX = eleRec?.x - 2;
7222
+ const rectY = eleRec?.y - 2;
7223
+ const rectWidth = eleRec?.width + 2;
7224
+ const rectHeight = eleRec?.height + 2;
7225
+ const thickness = 2;
7226
+ try {
7227
+ const image = await Jimp.read(report_img);
7228
+ const rectangleColor = Jimp.cssColorToHex(color);
7229
+ this.drawRectangleOutline(
7230
+ image,
7231
+ rectX,
7232
+ rectY,
7233
+ rectWidth,
7234
+ rectHeight,
7235
+ rectangleColor,
7236
+ thickness
7237
+ );
7238
+ const targetDir = path.dirname(report_img);
7239
+ const buffer = await image.getBufferAsync(Jimp.MIME_PNG);
7240
+ if (!fs.existsSync(targetDir)) {
7241
+ Logger$1.debug("folder not found");
7242
+ fs.mkdirSync(targetDir, { recursive: true });
7243
+ }
7244
+ fs.writeFileSync(report_img, buffer);
7245
+ } catch (err) {
7246
+ Logger$1.error(`Error: ${err}`);
7247
+ }
7248
+ }
7249
+ static async drawRectangleOutline(image, x, y, width, height, color, thickness) {
7250
+ for (let i = x; i < x + width; i++) {
7251
+ for (let t = 0; t < thickness; t++) {
7252
+ image.setPixelColor(color, i, y + t);
7253
+ image.setPixelColor(color, i, y + height - 1 - t);
7254
+ }
7255
+ }
7256
+ for (let j = y; j < y + height; j++) {
7257
+ for (let t = 0; t < thickness; t++) {
7258
+ image.setPixelColor(color, x + t, j);
7259
+ image.setPixelColor(color, x + width - 1 - t, j);
7260
+ }
7261
+ }
7262
+ }
7263
+ }
7264
+ class I18nRunner extends BaseRunner {
7265
+ constructor(...args) {
7266
+ super(...args);
7267
+ }
7268
+ /**
7269
+ *
7270
+ * @override
7271
+ */
7272
+ async process(string, element, offsets) {
7273
+ if (typeof string !== "string" || !string || Number(string) === 0) {
7274
+ return;
7275
+ }
7276
+ const src_img = joinPaths(
7277
+ Reports.reviewedReports(string, this.getBaseImageName()),
7278
+ this.getBaseImageName()
7279
+ ), status = Validator.getIssueType(string), dest_img = joinPaths(
7280
+ Reports[status](string, this.getBaseImageName()),
7281
+ this.getBaseImageName()
7282
+ );
7283
+ Reports.incrementCount(
7284
+ I18N_STATUS.REVIEWED,
7285
+ string,
7286
+ this.getBaseImageName(),
7287
+ this.getDescription()
7288
+ );
7289
+ if (!existsSync(src_img)) {
7290
+ copyFileSync(
7291
+ joinPaths(Reports.reviewedReports(), this.getBaseImageName()),
7292
+ src_img
7293
+ );
7294
+ }
7295
+ if (existsSync(src_img) && !existsSync(dest_img)) {
7296
+ copyFileSync(src_img, dest_img);
7297
+ }
7298
+ const color = this.#defineColor(status, string);
7299
+ Reports.incrementCount(status, string, dest_img, this.getDescription());
7300
+ await this.#highlightString(element, color, dest_img, offsets);
7301
+ }
7302
+ /**-----------------private helper methods----------------*/
7303
+ async #highlightString(element, color, image, offsets) {
7304
+ await this.#highlightStringInUI(element, color);
7305
+ await this.#highlightStringInReport(element, color, image, offsets);
7306
+ }
7307
+ async #highlightStringInUI(element, color) {
7308
+ await this.getDriver().onScreenStringHighlight(element, color);
7309
+ }
7310
+ async #highlightStringInReport(element, color, image, offsets) {
7311
+ let areaRec;
7312
+ const elRec = await this.getElementOffsets(element), areaColor = COLOR.GRB_BLUE;
7313
+ if (offsets) {
7314
+ areaRec = offsets;
7315
+ const keysToUpdate = ["x", "y"];
7316
+ for (const key of keysToUpdate) {
7317
+ if (key in elRec && key in areaRec) {
7318
+ elRec[key] = areaRec[key] + elRec[key];
7319
+ }
7320
+ }
7321
+ } else {
7322
+ areaRec = this.getVerificationAreaOffsets();
7323
+ }
7324
+ await Graphic.drawRectangle(areaRec, areaColor, image);
7325
+ await Graphic.drawRectangle(elRec, color, image);
7326
+ }
7327
+ #defineColor(status, string) {
7328
+ Logger$1.debug(
7329
+ `"${string}" - ${STATUS_COLOR[status][1]}${STATUS_INFO[status]}${"\x1B[0m"}`
7330
+ );
7331
+ return STATUS_COLOR[status][0];
7332
+ }
7333
+ }
7334
+ class SanityRunner extends BaseRunner {
7335
+ constructor(...args) {
7336
+ super(...args);
7337
+ }
7338
+ /**
7339
+ * @override
7340
+ */
7341
+ shouldCollectStrings() {
7342
+ return false;
7343
+ }
7344
+ /**
7345
+ *
7346
+ * @override
7347
+ */
7348
+ async process(page) {
7349
+ Logger$1.info(`${page} loaded`);
7350
+ const src_img = joinPaths(
7351
+ Reports.reviewedReports(page, this.getBaseImageName()),
7352
+ this.getBaseImageName()
7353
+ );
7354
+ Reports.incrementCount(
7355
+ I18N_STATUS.REVIEWED,
7356
+ page,
7357
+ src_img,
7358
+ this.getDescription()
7359
+ );
7360
+ if (!existsSync(src_img)) {
7361
+ copyFileSync(
7362
+ joinPaths(Reports.reviewedReports(), this.getBaseImageName()),
7363
+ src_img
7364
+ );
7365
+ }
7366
+ }
7367
+ }
7368
+ const build = (driver, verificationArea, selectors, useSmartSelector, description) => {
7369
+ switch (Config.getMode()) {
7370
+ case RUN_MODE.I18N:
7371
+ return new I18nRunner(
7372
+ driver,
7373
+ verificationArea,
7374
+ selectors,
7375
+ useSmartSelector,
7376
+ description
7377
+ );
7378
+ case RUN_MODE.CONTEXT:
7379
+ return new ContextRunner(
7380
+ driver,
7381
+ verificationArea,
7382
+ selectors,
7383
+ useSmartSelector,
7384
+ description
7385
+ );
7386
+ case RUN_MODE.SANITY:
7387
+ return new SanityRunner(
7388
+ driver,
7389
+ verificationArea,
7390
+ selectors,
7391
+ useSmartSelector,
7392
+ description
7393
+ );
7394
+ default:
7395
+ throw new Error("unsupported runner type");
7396
+ }
7397
+ };
7398
+ class Executor {
7399
+ /**
7400
+ * @type {import('../driver/baseDriver.js').default}
7401
+ */
7402
+ #driver;
7403
+ /**
7404
+ * @param {BaseDriver} driver
7405
+ */
7406
+ constructor(driver) {
7407
+ this.#driver = driver;
7408
+ }
7409
+ /**
7410
+ * @param {string} verificationArea - xpath selector of verification area
7411
+ * @param {string} staticLocators - user parsed xpath selectors to find text of elements under verification area
7412
+ * @param {string} description - identity of verification area ex: page, popup, form etc name
7413
+ */
7414
+ async start({
7415
+ verificationArea,
7416
+ staticLocators,
7417
+ useSmartSelector,
7418
+ description
7419
+ }) {
7420
+ const runner = build(
7421
+ this.#driver,
7422
+ verificationArea,
7423
+ staticLocators,
7424
+ useSmartSelector,
7425
+ description
7426
+ );
7427
+ await runner.run();
7428
+ }
7429
+ }
7430
+ export {
7431
+ Config as C,
7432
+ Executor as E,
7433
+ Logger$1 as L,
7434
+ Reports as R,
7435
+ SYSTEM_TYPES as S,
7436
+ getRootProjectPackageJson as a,
7437
+ CONFIG_FILE_NAME as b,
7438
+ checkAndExportConfig as c,
7439
+ getRootProjectMainDir as g,
7440
+ joinPaths as j,
7441
+ loadDependencies as l
7442
+ };