@zeesoft/i18n-verify 2.1.0 → 2.1.3

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.
@@ -6,7 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _baseDriver = _interopRequireDefault(require("../baseDriver.js"));
8
8
  var _logs = _interopRequireDefault(require("../../utils/logs.js"));
9
+ var _chromeRemoteInterface = _interopRequireDefault(require("chrome-remote-interface"));
10
+ var _fs = _interopRequireDefault(require("fs"));
9
11
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ // Default import to access CDP
13
+
10
14
  class NightWatchDriver extends _baseDriver.default {
11
15
  constructor(driver) {
12
16
  super(driver);
@@ -93,7 +97,7 @@ class NightWatchDriver extends _baseDriver.default {
93
97
  return eleStr;
94
98
  }
95
99
  async captureScreenshot(file) {
96
- await this.$driver.saveScreenshot(file);
100
+ await captureFullPage(this.$driver, file);
97
101
  }
98
102
  async getElementsCount(elements) {
99
103
  return elements.length;
@@ -133,4 +137,24 @@ class NightWatchDriver extends _baseDriver.default {
133
137
  return (await bodyContent.trim()) === '' ? true : false;
134
138
  }
135
139
  }
136
- exports.default = NightWatchDriver;
140
+ exports.default = NightWatchDriver;
141
+ const captureFullPage = async ($driver, filePath) => {
142
+ const client = await (0, _chromeRemoteInterface.default)({
143
+ host: 'localhost',
144
+ port: 9222
145
+ });
146
+ const {
147
+ Page
148
+ } = client;
149
+ await Page.enable();
150
+ const {
151
+ data
152
+ } = await Page.captureScreenshot({
153
+ format: 'png',
154
+ captureBeyondViewport: true
155
+ });
156
+ const screenshotBuffer = Buffer.from(data, 'base64');
157
+ _fs.default.writeFileSync(filePath, screenshotBuffer);
158
+ console.log(`Screenshot saved as: ${filePath}`);
159
+ await client.close();
160
+ };
@@ -83,10 +83,6 @@ class SeleniumDriver extends _baseDriver.default {
83
83
  });
84
84
  return elementStrings;
85
85
  }
86
- async captureScreenshot(file) {
87
- const screenshot = await this.driver.takeScreenshot();
88
- _fs.default.writeFileSync(file, screenshot, 'base64');
89
- }
90
86
  async getElementsCount(elements) {
91
87
  return elements.length;
92
88
  }
@@ -13,9 +13,14 @@ var _cacheData = _interopRequireDefault(require("../utils/objects/cacheData.js")
13
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
14
  class Reports {
15
15
  static #baseReportPath;
16
+ static #reportTimeStamp;
16
17
  static setup() {
18
+ Reports.#reportTimeStamp = Reports.#dateTime();
17
19
  const rootFolder = _path.default.resolve();
18
- Reports.#baseReportPath = (0, _file.joinPaths)(rootFolder, _config.default.getL10nReportsPath(), Reports.#dateTime());
20
+ Reports.#baseReportPath = (0, _file.joinPaths)(rootFolder, _config.default.getL10nReportsPath(), Reports.#reportTimeStamp);
21
+ }
22
+ static getReportTimeStamp() {
23
+ return Reports.#reportTimeStamp;
19
24
  }
20
25
  static getReportPath() {
21
26
  return Reports.#baseReportPath;
@@ -11,7 +11,9 @@ var _config = _interopRequireDefault(require("../lib/config.js"));
11
11
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
12
  const fs = require('fs');
13
13
  class Logger {
14
- static #suppressLogging = false;
14
+ static #isLogAppending = false;
15
+ static #appenderInterval;
16
+ static #appenderQueue = [];
15
17
  static info(message) {
16
18
  Logger.#print('info', message);
17
19
  }
@@ -54,27 +56,24 @@ class Logger {
54
56
  Logger.#customLog(`${logMessage}\n`);
55
57
  }
56
58
  static #customLog = message => {
57
- if (Logger.#suppressLogging) {
58
- return;
59
- }
60
- const LOGS_DIR = (0, _file.joinPaths)(_reports.default.getReportPath(), 'logs');
61
- const logFilePath = (0, _file.joinPaths)(LOGS_DIR, 'log.log');
62
- Logger.#suppressLogging = true;
63
- (0, _file.ensureDirectoryExists)(LOGS_DIR, _constants.DEBUG_MODE);
64
- Logger.#suppressLogging = false;
65
- if (!(0, _file.fileExists)(logFilePath)) {
66
- fs.writeFileSync(logFilePath, '');
67
- }
68
- new Promise((resolve, reject) => {
69
- fs.appendFile(logFilePath, message, err => {
70
- if (err) {
71
- Logger.error('Error writing to log file:', err, true);
72
- reject(err);
73
- } else {
74
- resolve();
59
+ if (Logger.#isLogAppending) {
60
+ Logger.#appenderQueue.push(message);
61
+ Logger.#appenderInterval = setInterval(() => {
62
+ if (!Logger.#isLogAppending) {
63
+ clearInterval(Logger.#appenderInterval);
64
+ message = Logger.#appenderQueue.join('\n');
65
+ Logger.#appenderQueue = [];
66
+ message && Logger.#customLog(message);
75
67
  }
76
- });
77
- });
68
+ }, 10);
69
+ } else {
70
+ Logger.#isLogAppending = true;
71
+ const LOGS_DIR = (0, _file.joinPaths)(_reports.default.getReportPath(), 'logs');
72
+ const logFilePath = (0, _file.joinPaths)(LOGS_DIR, 'log');
73
+ (0, _file.ensureDirectoryExists)(LOGS_DIR, _constants.DEBUG_MODE);
74
+ fs.appendFileSync(logFilePath, message);
75
+ Logger.#isLogAppending = false;
76
+ }
78
77
  };
79
78
  }
80
79
  exports.default = Logger;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _config = _interopRequireDefault(require("../../../lib/config.js"));
7
8
  var _reports = _interopRequireDefault(require("../../../lib/reports.js"));
8
9
  var _constants = require("../../constants.js");
9
10
  var _file = require("../../file.js");
@@ -12,6 +13,7 @@ var _body = _interopRequireDefault(require("./template/body.js"));
12
13
  var _css = _interopRequireDefault(require("./template/css.js"));
13
14
  var _html = _interopRequireDefault(require("./template/html.js"));
14
15
  var _index = _interopRequireDefault(require("./template/javascript/index.js"));
16
+ var _path = require("path");
15
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
18
  class HtmlReport extends _base.default {
17
19
  constructor() {
@@ -22,15 +24,24 @@ class HtmlReport extends _base.default {
22
24
  script = (0, _index.default)(metaInfo),
23
25
  style = (0, _css.default)(),
24
26
  body = (0, _body.default)(),
25
- dataFilePaths = [];
27
+ dataFilePaths = [],
28
+ logDataFilePath = (0, _file.joinPaths)(_reports.default.getReportPath(), 'logs', 'log');
29
+ let logData = '';
26
30
  (0, _file.getDirContents)(_reports.default.getReportPath()).forEach(file => file !== metaInfo.defaultLocale && (0, _file.fileExists)((0, _file.joinPaths)(_reports.default.getReportPath(), file, _constants.CACHE_FILE_NAME)) && dataFilePaths.push((0, _file.joinPaths)(file, _constants.CACHE_FILE_NAME).replace(/\\/g, '/')));
31
+ if ((0, _file.fileExists)(logDataFilePath)) {
32
+ // handle characters escapes and redact file paths and replace productName/timestamp
33
+ const paths = [metaInfo.appName, ..._config.default.getL10nReportsPath().split(/[\\/]+/g)];
34
+ paths.push(_reports.default.getReportTimeStamp());
35
+ logData = (0, _file.getFileContent)(logDataFilePath).replace(new RegExp(_reports.default.getReportPath().replace(/\\/g, '\\\\'), 'g'), (0, _file.joinPaths)(...paths)).replace(/\\/g, '\\\\').replace(/`/g, '\\`');
36
+ }
27
37
  return (0, _html.default)({
28
38
  appName: metaInfo.appName,
29
39
  reportTime: metaInfo.reportTime,
30
40
  body,
31
41
  script,
32
42
  style,
33
- dataFilePaths
43
+ dataFilePaths,
44
+ logData
34
45
  });
35
46
  }
36
47
  write(path, name, data) {
@@ -12,6 +12,9 @@ function getBodyData() {
12
12
  <li class="menu-item" data-page="overview">
13
13
  <a href="#">Overview</a>
14
14
  </li>
15
+ <li class="menu-item" data-page="log">
16
+ <a href="#">View Log</a>
17
+ </li>
15
18
  <li class="menu-item has-submenu" data-page="insights">
16
19
  <a href="#" data-page="insights">Insights</a>
17
20
  <ul class="submenu"></ul>
@@ -85,6 +88,10 @@ function getBodyData() {
85
88
  <div class="graph"></div>
86
89
  </div>
87
90
  </div>
91
+ <div id="log" class="content">
92
+ <span class="title">Runtime log</span>
93
+ <div class="log-content"><pre></pre></div>
94
+ </div>
88
95
  <div id="insights" class="content">
89
96
  <div class="cards">
90
97
  <span class="title">Locale Quality</span>
@@ -447,5 +447,30 @@ function getCssData() {
447
447
  width: 16rem;
448
448
  padding: 10px;
449
449
  }
450
+ }
451
+
452
+ .--hidden {
453
+ display: none;
454
+ visibility: hidden;
455
+ }
456
+
457
+ #log .log-content {
458
+ width: 98%;
459
+ height: 82vh;
460
+ background: white;
461
+ border-radius: 3px;
462
+ overflow: hidden;
463
+ padding: 1em;
464
+ }
465
+
466
+ #log .log-content pre {
467
+ height: 100%;
468
+ white-space: pre-line;
469
+ word-break: break-all;
470
+ padding: 0;
471
+ margin: 0;
472
+ width: 100%;
473
+ overflow: hidden;
474
+ overflow-y: auto;
450
475
  }`;
451
476
  }
@@ -10,7 +10,8 @@ function renderHtml({
10
10
  script,
11
11
  style,
12
12
  body,
13
- dataFilePaths = []
13
+ dataFilePaths = [],
14
+ logData
14
15
  }) {
15
16
  return `<!DOCTYPE html>
16
17
  <html lang="en">
@@ -33,8 +34,9 @@ function renderHtml({
33
34
  />
34
35
  ${dataFilePaths.map(v => `<script
35
36
  src="${v}"
36
- type="text/javascript" async>
37
+ type="text/javascript">
37
38
  </script>`).join('')}
39
+ ${logData ? `<script type="text/javascript" async/>window.logData = \`${logData}\`;</script>` : ''}
38
40
  <script
39
41
  src="https://code.jquery.com/jquery-3.7.1.slim.min.js"
40
42
  integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8="
@@ -8,12 +8,38 @@ var _default = () => `var DataStore;
8
8
  // global functions
9
9
  function openImageViewer(imageSrc) {
10
10
  var imageView = document.getElementById('imageView');
11
- imageView.src = \`\${new URL(document.baseURI).pathname.replace(/\\/[^\\/]+$/g, '')}/\${imageSrc}\`;
11
+ imageView.src = \`\${window.getProductUrl()}/\${imageSrc}\`;
12
12
  document.getElementById('imageViewer').style.display = 'block';
13
13
  }
14
14
 
15
15
  function closeImageViewer() {
16
16
  delete document.getElementById('imageView').src;
17
17
  document.getElementById('imageViewer').style.display = 'none';
18
+ }
19
+
20
+ //to dynamically show/hide header based upon query param: ?standalone=<true|false>
21
+ window.getProductUrl = () => {
22
+ if (window.productUrl) {
23
+ return window.productUrl;
24
+ } else {
25
+ window.productUrl = \`\${window.location.protocol}//\${
26
+ window.location.host
27
+ }\${window.location.pathname.match(/^.+[^\\/report\\.html]/g)?.[0]}\`;
28
+ return window.productUrl;
29
+ }
30
+ };
31
+ const params = new URLSearchParams(location.href.match(/(\\?.*$)/g)?.[0]);
32
+ if (params.size) {
33
+ const disableHeader = params.get('standalone') === 'true';
34
+ if (disableHeader) {
35
+ window.disableHeader = disableHeader;
36
+ const header = document.getElementsByTagName('header')[0],
37
+ main = document.getElementsByTagName('main')[0],
38
+ headerHeight = header.offsetHeight,
39
+ mainHeight = main.offsetHeight;
40
+ header.style.display = 'none';
41
+ main.style.height = \`\${headerHeight + mainHeight}px\`;
42
+ document.getElementById('locale').style.height = '96%';
43
+ }
18
44
  }`;
19
45
  exports.default = _default;
@@ -10,11 +10,13 @@ var _insight = _interopRequireDefault(require("./insight.js"));
10
10
  var _grid = _interopRequireDefault(require("./grid.js"));
11
11
  var _data = _interopRequireDefault(require("./data.js"));
12
12
  var _global = _interopRequireDefault(require("./global.js"));
13
+ var _log = _interopRequireDefault(require("./log.js"));
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  var _default = metaData => `${(0, _global.default)()}
15
16
  ${(0, _data.default)(metaData)}
16
17
  ${(0, _menuBar.default)()}
17
18
  ${(0, _overview.default)()}
18
19
  ${(0, _insight.default)()}
19
- ${(0, _grid.default)()}`;
20
+ ${(0, _grid.default)()}
21
+ ${(0, _log.default)()}`;
20
22
  exports.default = _default;
@@ -23,23 +23,15 @@ var _default = () => `// insights content
23
23
  const tbody = document.createElement('tbody');
24
24
  const name = document.createElement('div');
25
25
  const tableData = {
26
- Reviewed: data.reviewed,
27
26
  'Internationlized Strings':
28
27
  data.localizedStrings +
29
28
  data.untranslatedStrings +
30
29
  data.partialStrings,
31
30
  'Not Internationlized Strings': data.notLocalizedStrings,
32
- 'Untranslated Strings': data.untranslatedStrings,
33
- 'Encoding Issue Strings': data.encoding,
34
- 'DNT Strings': data.dnt,
35
- 'Ignored Strings': data.ignored,
36
- 'Auto Ignored Strings': data.autoIgnored,
37
- 'User Input Strings': data.userInput,
38
31
  'Internationlized Numbers': data.localizedNumber,
39
32
  'Not Internationlized Numbers': data.notLocalizedNumber,
40
33
  'Internationlized Currency': data.localizedCurrency,
41
34
  'Not Internationlized Currency': data.notLocalizedCurrency,
42
- 'Not Internationlized Numbers': data.notLocalizedNumber,
43
35
  'Internationlized Percentage': data.localizedPercentage,
44
36
  'Not Internationlized Percentage': data.notLocalizedPercentage,
45
37
  'Internationlized Date': data.localizedDate,
@@ -47,7 +39,14 @@ var _default = () => `// insights content
47
39
  'Internationlized Time': data.localizedTime,
48
40
  'Not Internationlized Time': data.notLocalizedTime,
49
41
  'Internationlized DateTime': data.localizedDate,
50
- 'Not Internationlized DateTime': data.notLocalizedDateTime
42
+ 'Not Internationlized DateTime': data.notLocalizedDateTime,
43
+ 'Encoding Issue Strings': data.encoding,
44
+ 'DNT Strings': data.dnt,
45
+ 'Ignored Strings': data.ignored,
46
+ 'Untranslated Strings': data.untranslatedStrings,
47
+ 'Auto Ignored Strings': data.autoIgnored,
48
+ 'User Input Strings': data.userInput,
49
+ 'Total Reviewed': data.reviewed
51
50
  };
52
51
  const addRow = (name, value) => {
53
52
  const row = document.createElement('tr');
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _default = () => `// log content
8
+ (() => {
9
+ document.addEventListener('DOMContentLoaded', function () {
10
+ const pre = document.querySelector('#log .log-content pre');
11
+ pre.textContent = 'Loading...';
12
+ document
13
+ .querySelector('li[data-page="log"]')
14
+ ?.addEventListener('click', (e) => {
15
+ pre.textContent = window.logData || 'No log data found!';
16
+ });
17
+ });
18
+ })();`;
19
+ exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeesoft/i18n-verify",
3
- "version": "2.1.0",
3
+ "version": "2.1.3",
4
4
  "description": "Library to perform I18n verification over Nightwatch or WebdriverIO frameworks",
5
5
  "main": "dist/index.js",
6
6
  "exports": {