ai-l10n-core 1.4.0
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.
- package/CHANGELOG.md +19 -0
- package/LICENSE +21 -0
- package/NOTICE +27 -0
- package/README.md +487 -0
- package/dist/consoleLogger.d.ts +26 -0
- package/dist/consoleLogger.js +62 -0
- package/dist/constants.d.ts +17 -0
- package/dist/constants.js +22 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/languageUtils.d.ts +27 -0
- package/dist/languageUtils.js +79 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.js +2 -0
- package/dist/test/consoleLogger.test.d.ts +1 -0
- package/dist/test/consoleLogger.test.js +242 -0
- package/dist/test/translationService.test.d.ts +1 -0
- package/dist/test/translationService.test.js +454 -0
- package/dist/translationService.d.ts +94 -0
- package/dist/translationService.js +155 -0
- package/package.json +51 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./logger"), exports);
|
|
18
|
+
__exportStar(require("./consoleLogger"), exports);
|
|
19
|
+
__exportStar(require("./constants"), exports);
|
|
20
|
+
__exportStar(require("./translationService"), exports);
|
|
21
|
+
__exportStar(require("./languageUtils"), exports);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BCP 47 language code regex with optional script and region subtags.
|
|
3
|
+
* Matches patterns like: en, en-US, en_US, zh-Hans, zh-Hans-CN, zh_Hans_CN
|
|
4
|
+
*/
|
|
5
|
+
export declare const LANGUAGE_CODE_REGEX: RegExp;
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes language codes to a consistent BCP 47 format with optional script and region subtags
|
|
8
|
+
* Examples:
|
|
9
|
+
* - "en" -> "en"
|
|
10
|
+
* - "en-us", "en_US" -> "en-US"
|
|
11
|
+
* - "zh_hans", "zh-Hans" -> "zh-Hans"
|
|
12
|
+
* - "zh_HANS_CN", "zh-Hans-CN" -> "zh-Hans-CN"
|
|
13
|
+
* @param code Language code to normalize
|
|
14
|
+
* @returns Normalized language code in the format: language[-Script][-REGION]
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeLanguageCode(code: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Validates whether the given string is a valid BCP 47 language code
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateLanguageCode(code: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Extracts language code from file name, handling custom prefixes and suffixes for different file types
|
|
23
|
+
* ARB files: app_en_US.arb -> en_US, my_app_fr.arb -> fr
|
|
24
|
+
* JSON files: en-US.json -> en-US
|
|
25
|
+
* Shopify theme: en.default.schema.json -> en, es-ES.schema.json -> es-ES
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractLanguageCode(fileName: string): string | null;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LANGUAGE_CODE_REGEX = void 0;
|
|
4
|
+
exports.normalizeLanguageCode = normalizeLanguageCode;
|
|
5
|
+
exports.validateLanguageCode = validateLanguageCode;
|
|
6
|
+
exports.extractLanguageCode = extractLanguageCode;
|
|
7
|
+
/**
|
|
8
|
+
* BCP 47 language code regex with optional script and region subtags.
|
|
9
|
+
* Matches patterns like: en, en-US, en_US, zh-Hans, zh-Hans-CN, zh_Hans_CN
|
|
10
|
+
*/
|
|
11
|
+
exports.LANGUAGE_CODE_REGEX = /^(?<language>[a-z]{2,3})([-|_](?<script>[A-Z][a-z]{3}))?([-|_](?<region>[A-Z]{2,3}|[0-9]{3}))?$/i;
|
|
12
|
+
/**
|
|
13
|
+
* Normalizes language codes to a consistent BCP 47 format with optional script and region subtags
|
|
14
|
+
* Examples:
|
|
15
|
+
* - "en" -> "en"
|
|
16
|
+
* - "en-us", "en_US" -> "en-US"
|
|
17
|
+
* - "zh_hans", "zh-Hans" -> "zh-Hans"
|
|
18
|
+
* - "zh_HANS_CN", "zh-Hans-CN" -> "zh-Hans-CN"
|
|
19
|
+
* @param code Language code to normalize
|
|
20
|
+
* @returns Normalized language code in the format: language[-Script][-REGION]
|
|
21
|
+
*/
|
|
22
|
+
function normalizeLanguageCode(code) {
|
|
23
|
+
const match = code.match(exports.LANGUAGE_CODE_REGEX);
|
|
24
|
+
if (!match?.groups) {
|
|
25
|
+
return code; // Return as-is if it doesn't match the pattern
|
|
26
|
+
}
|
|
27
|
+
const { language, script, region } = match.groups;
|
|
28
|
+
let normalized = language.toLowerCase();
|
|
29
|
+
if (script) {
|
|
30
|
+
// Script codes: first letter uppercase, rest lowercase
|
|
31
|
+
normalized +=
|
|
32
|
+
"-" + script.charAt(0).toUpperCase() + script.slice(1).toLowerCase();
|
|
33
|
+
}
|
|
34
|
+
if (region) {
|
|
35
|
+
// Region codes: all uppercase
|
|
36
|
+
normalized += "-" + region.toUpperCase();
|
|
37
|
+
}
|
|
38
|
+
return normalized;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates whether the given string is a valid BCP 47 language code
|
|
42
|
+
*/
|
|
43
|
+
function validateLanguageCode(code) {
|
|
44
|
+
return !!code && exports.LANGUAGE_CODE_REGEX.test(code);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Extracts language code from file name, handling custom prefixes and suffixes for different file types
|
|
48
|
+
* ARB files: app_en_US.arb -> en_US, my_app_fr.arb -> fr
|
|
49
|
+
* JSON files: en-US.json -> en-US
|
|
50
|
+
* Shopify theme: en.default.schema.json -> en, es-ES.schema.json -> es-ES
|
|
51
|
+
*/
|
|
52
|
+
function extractLanguageCode(fileName) {
|
|
53
|
+
const isArbFile = fileName.endsWith(".arb");
|
|
54
|
+
const nameWithoutExt = fileName.replace(/\.[^.]+$/, ""); // Remove extension
|
|
55
|
+
if (isArbFile) {
|
|
56
|
+
// ARB files use underscores instead of hyphens
|
|
57
|
+
const arbLanguageCodeRegex = /^(?<language>[a-z]{2,3})(_(?<script>[A-Z][a-z]{3}))?(_(?<region>[A-Z]{2,3}|[0-9]{3}))?$/;
|
|
58
|
+
// For ARB files, try to extract language code after potential prefix
|
|
59
|
+
// Pattern: [prefix_]language[_script][_region]
|
|
60
|
+
const parts = nameWithoutExt.split("_");
|
|
61
|
+
// Try combinations from right to left to find valid language code
|
|
62
|
+
// For example, for "my_app_en_US.arb", parts = ["my", "app", "en", "US"]
|
|
63
|
+
// Check "en_US", then "app_en_US", then "my_app_en_US" until we find a match
|
|
64
|
+
for (let i = 0; i < parts.length; i++) {
|
|
65
|
+
const potentialCode = parts.slice(i).join("_");
|
|
66
|
+
if (arbLanguageCodeRegex.test(potentialCode)) {
|
|
67
|
+
return potentialCode;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
// Handle Shopify theme pattern: en.default.schema, es-ES.schema
|
|
73
|
+
// Remove .schema first, then .default before extracting language code
|
|
74
|
+
const cleanedFileName = nameWithoutExt
|
|
75
|
+
.replace(/\.schema$/, "")
|
|
76
|
+
.replace(/\.default$/, "");
|
|
77
|
+
// For JSON files, the entire filename should be the language code
|
|
78
|
+
return exports.LANGUAGE_CODE_REGEX.test(cleanedFileName) ? cleanedFileName : null;
|
|
79
|
+
}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger interface for dependency injection
|
|
3
|
+
*/
|
|
4
|
+
export interface ILogger {
|
|
5
|
+
logInfo(message: string): void;
|
|
6
|
+
logWarning(message: string, error?: unknown): void;
|
|
7
|
+
logError(message: string, error?: unknown): void;
|
|
8
|
+
showAndLogError(message: string, error?: unknown, context?: string, linkBtnText?: string, url?: string): void;
|
|
9
|
+
}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const sinon = __importStar(require("sinon"));
|
|
38
|
+
const consoleLogger_1 = require("../consoleLogger");
|
|
39
|
+
suite("ConsoleLogger Test Suite", () => {
|
|
40
|
+
let logger;
|
|
41
|
+
let consoleErrorStub;
|
|
42
|
+
let consoleLogStub;
|
|
43
|
+
let consoleWarnStub;
|
|
44
|
+
setup(() => {
|
|
45
|
+
logger = new consoleLogger_1.ConsoleLogger();
|
|
46
|
+
consoleErrorStub = sinon.stub(console, "error");
|
|
47
|
+
consoleLogStub = sinon.stub(console, "log");
|
|
48
|
+
consoleWarnStub = sinon.stub(console, "warn");
|
|
49
|
+
});
|
|
50
|
+
teardown(() => {
|
|
51
|
+
sinon.restore();
|
|
52
|
+
});
|
|
53
|
+
suite("showAndLogError", () => {
|
|
54
|
+
test("logs error message with emoji", () => {
|
|
55
|
+
logger.showAndLogError("Test error message");
|
|
56
|
+
assert.ok(consoleErrorStub.calledOnce);
|
|
57
|
+
assert.ok(consoleErrorStub.firstCall.args[0].includes("❌"));
|
|
58
|
+
assert.ok(consoleErrorStub.firstCall.args[0].includes("Test error message"));
|
|
59
|
+
});
|
|
60
|
+
test("logs context when provided", () => {
|
|
61
|
+
logger.showAndLogError("Error", undefined, "Test context");
|
|
62
|
+
assert.ok(consoleErrorStub.calledTwice);
|
|
63
|
+
assert.ok(consoleErrorStub.secondCall.args[0].includes("Context:"));
|
|
64
|
+
assert.ok(consoleErrorStub.secondCall.args[0].includes("Test context"));
|
|
65
|
+
});
|
|
66
|
+
test("logs Error object with message and stack", () => {
|
|
67
|
+
const error = new Error("Test error");
|
|
68
|
+
logger.showAndLogError("Error occurred", error);
|
|
69
|
+
// Should log: main message, error message, and stack
|
|
70
|
+
assert.ok(consoleErrorStub.callCount >= 2);
|
|
71
|
+
const calls = consoleErrorStub.getCalls();
|
|
72
|
+
const errorMessageCall = calls.find((call) => call.args[0].includes("Error: Test error"));
|
|
73
|
+
assert.ok(errorMessageCall, "Should log error message");
|
|
74
|
+
const stackCall = calls.find((call) => typeof call.args[0] === "string" && call.args[0].includes("at "));
|
|
75
|
+
assert.ok(stackCall, "Should log stack trace");
|
|
76
|
+
});
|
|
77
|
+
test("logs non-Error objects as strings", () => {
|
|
78
|
+
const error = { message: "Custom error" };
|
|
79
|
+
logger.showAndLogError("Error occurred", error);
|
|
80
|
+
const calls = consoleErrorStub.getCalls();
|
|
81
|
+
const errorCall = calls.find((call) => call.args[0].includes("[object Object]"));
|
|
82
|
+
assert.ok(errorCall, "Should convert error to string");
|
|
83
|
+
});
|
|
84
|
+
test("logs link when both linkBtnText and url provided", () => {
|
|
85
|
+
logger.showAndLogError("Error", undefined, undefined, "Visit docs", "https://example.com");
|
|
86
|
+
const calls = consoleErrorStub.getCalls();
|
|
87
|
+
const linkCall = calls.find((call) => call.args[0].includes("Visit docs") &&
|
|
88
|
+
call.args[0].includes("https://example.com"));
|
|
89
|
+
assert.ok(linkCall, "Should log link with button text");
|
|
90
|
+
});
|
|
91
|
+
test("does not log link when only linkBtnText provided", () => {
|
|
92
|
+
logger.showAndLogError("Error", undefined, undefined, "Visit docs");
|
|
93
|
+
// Should only log the main error message, not the link
|
|
94
|
+
assert.strictEqual(consoleErrorStub.callCount, 1);
|
|
95
|
+
});
|
|
96
|
+
test("does not log link when only url provided", () => {
|
|
97
|
+
logger.showAndLogError("Error", undefined, undefined, undefined, "https://example.com");
|
|
98
|
+
// Should only log the main error message, not the link
|
|
99
|
+
assert.strictEqual(consoleErrorStub.callCount, 1);
|
|
100
|
+
});
|
|
101
|
+
test("handles all parameters together", () => {
|
|
102
|
+
const error = new Error("Full test error");
|
|
103
|
+
logger.showAndLogError("Complete error", error, "Full context", "Help link", "https://help.com");
|
|
104
|
+
// Should log: message, context, error message, stack, link
|
|
105
|
+
assert.ok(consoleErrorStub.callCount >= 4);
|
|
106
|
+
const allCalls = consoleErrorStub.getCalls().map((call) => call.args[0]);
|
|
107
|
+
const allOutput = allCalls.join(" ");
|
|
108
|
+
assert.ok(allOutput.includes("❌ Complete error"));
|
|
109
|
+
assert.ok(allOutput.includes("Context: Full context"));
|
|
110
|
+
assert.ok(allOutput.includes("Error: Full test error"));
|
|
111
|
+
assert.ok(allOutput.includes("Help link: https://help.com"));
|
|
112
|
+
});
|
|
113
|
+
test("handles Error without stack trace", () => {
|
|
114
|
+
const error = new Error("No stack error");
|
|
115
|
+
delete error.stack;
|
|
116
|
+
logger.showAndLogError("Error", error);
|
|
117
|
+
// Should still log the error message
|
|
118
|
+
const calls = consoleErrorStub.getCalls();
|
|
119
|
+
const errorCall = calls.find((call) => call.args[0].includes("Error: No stack error"));
|
|
120
|
+
assert.ok(errorCall, "Should log error message even without stack");
|
|
121
|
+
});
|
|
122
|
+
test("handles null error", () => {
|
|
123
|
+
logger.showAndLogError("Error", null);
|
|
124
|
+
// Should only log main message, null is falsy so no error details
|
|
125
|
+
assert.strictEqual(consoleErrorStub.callCount, 1);
|
|
126
|
+
});
|
|
127
|
+
test("handles undefined error", () => {
|
|
128
|
+
logger.showAndLogError("Error", undefined);
|
|
129
|
+
// Should only log main message
|
|
130
|
+
assert.strictEqual(consoleErrorStub.callCount, 1);
|
|
131
|
+
});
|
|
132
|
+
test("handles number as error", () => {
|
|
133
|
+
logger.showAndLogError("Error", 404);
|
|
134
|
+
const calls = consoleErrorStub.getCalls();
|
|
135
|
+
const errorCall = calls.find((call) => call.args[0].includes("Error: 404"));
|
|
136
|
+
assert.ok(errorCall, "Should convert number to string");
|
|
137
|
+
});
|
|
138
|
+
test("handles string as error", () => {
|
|
139
|
+
logger.showAndLogError("Error", "String error message");
|
|
140
|
+
const calls = consoleErrorStub.getCalls();
|
|
141
|
+
const errorCall = calls.find((call) => call.args[0].includes("Error: String error message"));
|
|
142
|
+
assert.ok(errorCall, "Should log string error");
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
suite("logInfo", () => {
|
|
146
|
+
test("logs info message", () => {
|
|
147
|
+
logger.logInfo("Information message");
|
|
148
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
149
|
+
assert.strictEqual(consoleLogStub.firstCall.args[0], "Information message");
|
|
150
|
+
});
|
|
151
|
+
test("logs empty string", () => {
|
|
152
|
+
logger.logInfo("");
|
|
153
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
154
|
+
assert.strictEqual(consoleLogStub.firstCall.args[0], "");
|
|
155
|
+
});
|
|
156
|
+
test("logs multiline message", () => {
|
|
157
|
+
const multiline = "Line 1\nLine 2\nLine 3";
|
|
158
|
+
logger.logInfo(multiline);
|
|
159
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
160
|
+
assert.strictEqual(consoleLogStub.firstCall.args[0], multiline);
|
|
161
|
+
});
|
|
162
|
+
test("logs message with special characters", () => {
|
|
163
|
+
const message = "Message with 🎉 emoji and special chars: @#$%";
|
|
164
|
+
logger.logInfo(message);
|
|
165
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
166
|
+
assert.strictEqual(consoleLogStub.firstCall.args[0], message);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
suite("logWarning", () => {
|
|
170
|
+
test("logs warning with emoji", () => {
|
|
171
|
+
logger.logWarning("Warning message");
|
|
172
|
+
assert.ok(consoleWarnStub.calledOnce);
|
|
173
|
+
assert.ok(consoleWarnStub.firstCall.args[0].includes("⚠️ "));
|
|
174
|
+
assert.ok(consoleWarnStub.firstCall.args[0].includes("Warning message"));
|
|
175
|
+
});
|
|
176
|
+
test("logs empty warning", () => {
|
|
177
|
+
logger.logWarning("");
|
|
178
|
+
assert.ok(consoleWarnStub.calledOnce);
|
|
179
|
+
assert.strictEqual(consoleWarnStub.firstCall.args[0], "⚠️ ");
|
|
180
|
+
});
|
|
181
|
+
test("logs multiline warning", () => {
|
|
182
|
+
const multiline = "Warning line 1\nWarning line 2";
|
|
183
|
+
logger.logWarning(multiline);
|
|
184
|
+
assert.ok(consoleWarnStub.calledOnce);
|
|
185
|
+
assert.ok(consoleWarnStub.firstCall.args[0].includes(multiline));
|
|
186
|
+
});
|
|
187
|
+
test("preserves warning message format", () => {
|
|
188
|
+
logger.logWarning("Detailed warning with info");
|
|
189
|
+
const output = consoleWarnStub.firstCall.args[0];
|
|
190
|
+
assert.strictEqual(output, "⚠️ Detailed warning with info");
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
suite("Logger Interface Compliance", () => {
|
|
194
|
+
test("implements all required ILogger methods", () => {
|
|
195
|
+
assert.strictEqual(typeof logger.showAndLogError, "function");
|
|
196
|
+
assert.strictEqual(typeof logger.logInfo, "function");
|
|
197
|
+
assert.strictEqual(typeof logger.logWarning, "function");
|
|
198
|
+
});
|
|
199
|
+
test("showAndLogError returns void", () => {
|
|
200
|
+
const result = logger.showAndLogError("Test");
|
|
201
|
+
assert.strictEqual(result, undefined);
|
|
202
|
+
});
|
|
203
|
+
test("logInfo returns void", () => {
|
|
204
|
+
const result = logger.logInfo("Test");
|
|
205
|
+
assert.strictEqual(result, undefined);
|
|
206
|
+
});
|
|
207
|
+
test("logWarning returns void", () => {
|
|
208
|
+
const result = logger.logWarning("Test");
|
|
209
|
+
assert.strictEqual(result, undefined);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
suite("Edge Cases", () => {
|
|
213
|
+
test("handles very long messages", () => {
|
|
214
|
+
const longMessage = "A".repeat(10000);
|
|
215
|
+
logger.logInfo(longMessage);
|
|
216
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
217
|
+
assert.strictEqual(consoleLogStub.firstCall.args[0].length, 10000);
|
|
218
|
+
});
|
|
219
|
+
test("handles messages with null bytes", () => {
|
|
220
|
+
const messageWithNull = "Message\x00with\x00nulls";
|
|
221
|
+
logger.logInfo(messageWithNull);
|
|
222
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
223
|
+
});
|
|
224
|
+
test("handles Unicode characters", () => {
|
|
225
|
+
const unicode = "Hello 世界 🌍 Привет";
|
|
226
|
+
logger.logInfo(unicode);
|
|
227
|
+
assert.ok(consoleLogStub.calledOnce);
|
|
228
|
+
assert.strictEqual(consoleLogStub.firstCall.args[0], unicode);
|
|
229
|
+
});
|
|
230
|
+
test("does not throw on multiple calls", () => {
|
|
231
|
+
assert.doesNotThrow(() => {
|
|
232
|
+
logger.logInfo("Message 1");
|
|
233
|
+
logger.logWarning("Warning 1");
|
|
234
|
+
logger.showAndLogError("Error 1");
|
|
235
|
+
logger.logInfo("Message 2");
|
|
236
|
+
});
|
|
237
|
+
assert.strictEqual(consoleLogStub.callCount, 2);
|
|
238
|
+
assert.strictEqual(consoleWarnStub.callCount, 1);
|
|
239
|
+
assert.ok(consoleErrorStub.callCount >= 1);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|