diff --git a/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts b/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts index e8efaaa2b..40ca264fc 100644 --- a/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts +++ b/src/Framework/Framework/Resources/Scripts/dotvvm-root.ts @@ -22,7 +22,7 @@ import * as api from './api/api' import * as eventHub from './api/eventHub' import * as viewModuleManager from './viewModules/viewModuleManager' import { notifyModuleLoaded } from './postback/resourceLoader' -import { logError, logWarning, logInfo, logInfoVerbose, level, logPostBackScriptError } from "./utils/logging" +import { logError, logWarning, logInfo, logInfoVerbose, level, logPostBackScriptError, setLogger } from "./utils/logging" import * as metadataHelper from './metadata/metadataHelper' import { StateManager } from "./state-manager" import { DotvvmEvent } from "./events" @@ -119,7 +119,8 @@ const dotvvmExports = { logInfo, logInfoVerbose, logPostBackScriptError, - level + level, + setLogger }, options, translations: translations as any, diff --git a/src/Framework/Framework/Resources/Scripts/tests/validation.test.ts b/src/Framework/Framework/Resources/Scripts/tests/validation.test.ts index 875d7205d..1e11d688d 100644 --- a/src/Framework/Framework/Resources/Scripts/tests/validation.test.ts +++ b/src/Framework/Framework/Resources/Scripts/tests/validation.test.ts @@ -2,6 +2,7 @@ import { globalValidationObject as validation, ValidationErrorDescriptor } from "../validation/validation" import { createComplexObservableSubViewmodel, createComplexObservableViewmodel, ObservableHierarchy, ObservableSubHierarchy } from "./observableHierarchies" import { getErrors } from "../validation/error" +import { setLogger } from "../utils/logging"; describe("DotVVM.Validation - public API", () => { @@ -139,6 +140,36 @@ describe("DotVVM.Validation - public API", () => { } }) + test("addErrors - second level nonexistent property (setLogger capture)", () => { + //Setup + const vm = createComplexObservableViewmodel(); + const logMessages: any[][] = [] + let captureLog = true + setLogger((next, level, area, ...args) => { + if (captureLog && level == "warn") + logMessages.push([ "area", ...args ]) + else + next(level, area, ...args) + }) + + try { + //Act + validation.addErrors( + [ + { errorMessage: "Does not matter", propertyPath: "/Prop1/NonExistent" }, + ], + { root: ko.observable(vm) } + ); + + //Check + expect(logMessages.length).toBe(1); + expect(logMessages[0][1]).toContain("Validation error could not been applied to property specified by propertyPath /Prop1/NonExistent. Property with name NonExistent does not exist on /Prop1."); + } + finally { + captureLog = false + } + }) + test("addErrors - root level nonexistent property", () => { //Setup const vm = createComplexObservableViewmodel(); diff --git a/src/Framework/Framework/Resources/Scripts/utils/logging.ts b/src/Framework/Framework/Resources/Scripts/utils/logging.ts index 2116ea8b8..2413852ff 100644 --- a/src/Framework/Framework/Resources/Scripts/utils/logging.ts +++ b/src/Framework/Framework/Resources/Scripts/utils/logging.ts @@ -4,6 +4,28 @@ type LogLevel = "normal" | "verbose"; export const level = getLogLevel(); +type ConsoleLogLevel = "warn" | "log" | "error" | "trace"; + +let logger = function defaultLogger(level: ConsoleLogLevel, area: DotvvmLoggingArea, ...args: any) { + console[level](area, ...args) +} + +/** + * Instead of calling console.log, console.warn or console.error, DotVVM will call this function instead. + * Please keep in mind that the exact wording of log messages is not DotVVM public API and may change without notice. + * @example + * dotvvm.log.setLogger((next, level, area, ...args) => { + * if (area == "validation" && /^This message should be an error$/.test(args[0])) { + * level = "error" + * } +* previous(level, area, ...args) // call the default logger + * }) + */ +export function setLogger(newLogger: (next: typeof logger, level: ConsoleLogLevel, area: DotvvmLoggingArea, ...args: any) => void) { + const nextLogger = logger; + logger = (...args) => newLogger(nextLogger, ...args); +} + export type DotvvmLoggingArea = ( | "debug" | "configuration" @@ -21,20 +43,20 @@ export type DotvvmLoggingArea = ( export function logInfoVerbose(area: DotvvmLoggingArea, ...args: any[]) { if (compileConstants.debug && level === "verbose") { - console.log(area, ...args); + logger("log", area, ...args); } } export function logInfo(area: DotvvmLoggingArea, ...args: any[]) { - console.log(area, ...args); + logger("log", area, ...args); } export function logWarning(area: DotvvmLoggingArea, ...args: any[]) { - console.warn(area, ...args); + logger("warn", area, ...args); } export function logError(area: DotvvmLoggingArea, ...args: any[]) { - console.error(area, ...args); + logger("error", area, ...args); } export function logPostBackScriptError(err: any) {