/// <summary> /// The get interface log level. /// </summary> /// <param name="declaringType"> /// The declaring type. /// </param> /// <param name="logLevel"> /// The log level. /// </param> /// <returns> /// The <see cref="StfLogLevel"/>. /// </returns> private StfLogLevel GetInterfaceLogLevel(Type declaringType, StfLogLevel logLevel) { var retVal = logLevel; if (declaringType == null) { return(retVal); } try { var classLoglevel = declaringType.GetCustomAttribute <StfInterfaceLogLevelAttribute>(); if (classLoglevel != null) { retVal = classLoglevel.LogLevel; } } catch (Exception exception) { stfLogger.LogInternal("Exception caught getting interface loglevel: [{0}]", exception.Message); } return(retVal); }
// ============================================================= // Functions in models/adapters // ============================================================= /// <summary> /// The log function enter. Should be called/inserted when entering a model/adapter function. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="nameOfReturnType"> /// The name of return type. /// </param> /// <param name="functionName"> /// The function name. /// </param> /// <param name="argValues"> /// The <c>arg</c> values. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogFunctionEnter(StfLogLevel loglevel, string nameOfReturnType, string functionName, object[] argValues) { var argsString = CreateStringFromArgsAndArgsValues(argValues); var message = $"> Entering [{functionName}] with values [{argsString}] returning [{nameOfReturnType}]"; callStack.Push(functionName); return(LogOneHtmlMessage(loglevel, message)); }
/// <summary> /// The log function exit. Should be called/inserted when exiting a model/adapter function. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="functionName"> /// The function name. /// </param> /// <param name="returnValue"> /// The return value. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogFunctionExit(StfLogLevel loglevel, string functionName, object returnValue) { var message = $"< Exited [{functionName}] returning [{returnValue}]"; var retVal = LogOneHtmlMessage(loglevel, message); callStack.Pop(); return(retVal); }
// ============================================================= // Properties in models/adapters // ============================================================= /// <summary> /// The log get. /// </summary> /// <param name="loglevel"> /// The loglevel. /// </param> /// <param name="callingProperty"> /// The calling property. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogGetEnter(StfLogLevel loglevel, string callingProperty) { var propName = GetLogFriendlyPropName(callingProperty); var message = $"> Entering Get [{propName}]"; callStack.Push(propName); return(LogOneHtmlMessage(loglevel, message)); }
/// <summary> /// The log set. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="callingProperty"> /// The calling property. /// </param> /// <param name="setValue"> /// The set value. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogSetEnter(StfLogLevel loglevel, string callingProperty, object setValue) { var propName = GetLogFriendlyPropName(callingProperty); var valueString = setValue?.ToString() ?? "null"; var message = $"> Entering Set [{propName}] with value [{valueString}]"; callStack.Push(propName); return(LogOneHtmlMessage(loglevel, message)); }
/// <summary> /// The get property log level. /// </summary> /// <param name="methodBase"> /// The method base. /// </param> /// <param name="logLevel"> /// The log level. /// </param> /// <returns> /// The <see cref="StfLogLevel"/>. /// </returns> private StfLogLevel GetPropertyLogLevel(MethodBase methodBase, StfLogLevel logLevel) { var retVal = logLevel; if (methodBase == null) { return(retVal); } var match = Regex.Match(methodBase.Name, @"^(set_|get_)(?<PropertyName>[^\s].+)"); if (!match.Success) { return(retVal); } var propertyName = match.Groups["PropertyName"].Value; var declaringType = methodBase.DeclaringType; if (declaringType == null) { return(retVal); } PropertyInfo property; try { property = declaringType.GetProperties().FirstOrDefault(p => p.Name.Equals(propertyName)); } catch (Exception exception) { stfLogger.LogInternal( "Caught exception trying to get info for property with name [{0}]. Error message: [{1}]", propertyName, exception.Message); return(retVal); } if (property == null) { return(retVal); } var propertyLogLevel = property.GetCustomAttribute <StfMemberLogLevelAttribute>(); if (propertyLogLevel != null) { retVal = propertyLogLevel.LogLevel; } return(retVal); }
/// <summary> /// The log set exit. /// </summary> /// <param name="loglevel"> /// The loglevel. /// </param> /// <param name="callingProperty"> /// The calling property. /// </param> /// <param name="setValue"> /// The set value. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogSetExit(StfLogLevel loglevel, string callingProperty, object setValue) { var propName = GetLogFriendlyPropName(callingProperty); var valueString = setValue?.ToString() ?? "null"; var message = $"< Exiting Set [{propName}] after setting value [{valueString}]"; var retVal = LogOneHtmlMessage(loglevel, message); callStack.Pop(); return(retVal); }
/// <summary> /// Logging a test step assertion did fail. /// </summary> /// <param name="testStepName"> /// The test step name. /// </param> /// <param name="message"> /// Further information related to the failing test step - if any. /// </param> /// <param name="args"> /// The args. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogFail(string testStepName, string message, params object[] args) { message = message.StfFormatString(args); const StfLogLevel TheLogLevel = StfLogLevel.Fail; var tempNeedsToBeReworkedMessage = $"TestStepName=[{testStepName}], message=[{message}]"; var length = LogOneHtmlMessage(TheLogLevel, tempNeedsToBeReworkedMessage); if (Configuration.ScreenshotOnLogFail) { length = LogScreenshot(TheLogLevel, string.Empty); } return(length); }
/// <summary> /// The log screenshot. /// </summary> /// <param name="stfLogLevel"> /// The log level. /// </param> /// <param name="message"> /// The message. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogScreenshot(StfLogLevel stfLogLevel, string message) { var length = 0; foreach (var screen in Screen.AllScreens) { length += LogOneImage(stfLogLevel, Utilities.DoScreenshot(screen.Bounds), message); if (length < 0) { break; } } return(length); }
/// <summary> /// The status msg. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <returns> /// The <see cref="string"/>. /// </returns> private string GetStatusMsgAndSetLoglevel(out StfLogLevel loglevel) { if (this.ErrorOrFail() > 0) { loglevel = StfLogLevel.Error; return("Test showed errors"); } if (this.NumberOfLoglevelMessages[StfLogLevel.Warning] > 0) { loglevel = StfLogLevel.Warning; return("Test showed warnings"); } loglevel = StfLogLevel.Pass; if (this.NumberOfLoglevelMessages[loglevel] < 1) { this.NumberOfLoglevelMessages[loglevel] = 1; } return("Test showed no errors"); }
/// <summary> /// The log one image. /// </summary> /// <param name="level"> /// The level. /// </param> /// <param name="imageFile"> /// The image file. /// </param> /// <param name="message"> /// The message. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> private int LogOneImage(StfLogLevel level, string imageFile, string message) { if (!AddLoglevelToRunReport[level]) { return(-1); } var messageIdString = GetNextMessageId(); var logLevelString = Enum.GetName(typeof(StfLogLevel), level) ?? "Unknown StfLogLevel"; logLevelString = logLevelString.ToLower(); var html = string.Format("<div onclick=\"sa('{0}')\" id=\"{0}\" class=\"line {1} image\">\n", messageIdString, logLevelString); html += $" <div class=\"el time\">{DateTime.Now:HH:mm:ss}</div>\n"; html += $" <div class=\"el level\">{logLevelString}</div>\n"; html += $" <div class=\"el msg\">{message}</div>\n"; html += $" <p><img onclick=\"showImage(this)\" class=\"embeddedimage\" alt=\"{message}\" src=\"data:image/png;base64, {imageFile}\" /></p>"; html += "</div>\n"; LogFileHandle.Write(html); return(html.Length); }
/// <summary> /// Initializes a new instance of the <see cref="StfInterfaceLogLevelAttribute"/> class. /// </summary> /// <param name="logLevel"> /// The log level. /// </param> public StfInterfaceLogLevelAttribute(StfLogLevel logLevel) { LogLevel = logLevel; }
/// <summary> /// The log one html Message. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="message"> /// The Message. /// </param> /// <param name="args"> /// The args. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> private int LogOneHtmlMessage(StfLogLevel loglevel, string message, params object[] args) { ResetIdleTimer(); string htmlLine; if (!AddLoglevelToRunReport[loglevel]) { return(-1); } if (messageId == 0) { if (!InitLogfile()) { Console.WriteLine(@"Coulnd't initialise the logfile"); } } if (!LogFileHandle.Initialized) { return(-2); } var messageIdString = GetNextMessageId(); var logLevelString = Enum.GetName(typeof(StfLogLevel), loglevel) ?? "Unknown StfLogLevel"; var convertedToFoldableMessage = false; logLevelString = logLevelString.ToLower(); CheckForPerformanceAlert(); message = message.StfFormatString(args); if (Configuration.MapNewlinesToBr) { var count = message.Count(f => f == '\n'); if (count > 1) { var firstLineIndexOf = message.IndexOf(Environment.NewLine, StringComparison.Ordinal); if (firstLineIndexOf > 0) { var firstLineOfMessage = message.Substring(0, firstLineIndexOf); var firstLoggedLine = $"{Environment.NewLine}{firstLineOfMessage}"; message = GetMultilineMessage(messageIdString, firstLoggedLine, message); convertedToFoldableMessage = true; } } } if (ShouldMessageBeConvertedToClickable(message) && !convertedToFoldableMessage) { // todo: Implement :-) } switch (loglevel) { case StfLogLevel.Header: htmlLine = $"<div class=\"line logheader\">{message}</div>\n"; break; case StfLogLevel.SubHeader: htmlLine = $"<div class=\"line logsubheader\">{message}</div>\n"; break; default: htmlLine = string.Format( "<div onclick=\"sa('{0}')\" id=\"{0}\" class=\"line {1} \">\n", messageIdString, logLevelString); htmlLine += $" <div class=\"el time\">{timeOfLastMessage:HH:mm:ss}</div>\n"; htmlLine += $" <div class=\"el level\">{logLevelString}</div>\n"; htmlLine += $" <div class=\"el pad\">{IndentString()}</div>\n"; htmlLine += $" <div class=\"el msg\">{message}</div>\n"; htmlLine += "</div>\n"; break; } NumberOfLoglevelMessages[loglevel]++; LogFileHandle.Write(htmlLine); return(htmlLine.Length); }
/// <summary> /// The log function enter. Should be called/inserted when entering a model/adapter function. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="nameOfReturnType"> /// The name of return type. /// </param> /// <param name="functionName"> /// The function name. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogFunctionEnter(StfLogLevel loglevel, string nameOfReturnType, string functionName) { return(LogFunctionEnter(loglevel, nameOfReturnType, functionName, null)); }
/// <summary> /// The log image. /// </summary> /// <param name="stfLogLevel"> /// The log level. /// </param> /// <param name="imageFile"> /// The image file. /// </param> /// <param name="message"> /// The message. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogImage(StfLogLevel stfLogLevel, string imageFile, string message) { return(LogOneImage(stfLogLevel, imageFile, message)); }
/// <summary> /// Dump an AutomationIdentification <c>object</c>. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="automationIdObj"> /// The automation id obj. /// </param> /// <param name="message"> /// The Message. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogAutomationIdObject(StfLogLevel loglevel, object automationIdObj, string message) { return(LogAutomationIdObjectUserFunction(loglevel, automationIdObj, message)); }
/// <summary> /// The log all windows. /// </summary> /// <param name="stfLogLevel"> /// The log level. /// </param> /// <param name="message"> /// The message. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogAllWindows(StfLogLevel stfLogLevel, string message) { throw new NotImplementedException(); }
/// <summary> /// Initializes a new instance of the <see cref="StfMemberLogLevelAttribute"/> class. /// </summary> /// <param name="logLevel"> /// The log level. /// </param> public StfMemberLogLevelAttribute(StfLogLevel logLevel) { LogLevel = logLevel; }
/// <summary> /// The log function exit. Should be called/inserted when exiting a model/adapter function. /// </summary> /// <param name="loglevel"> /// The log level. /// </param> /// <param name="functionName"> /// The function name. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public int LogFunctionExit(StfLogLevel loglevel, string functionName) { return(LogFunctionExit(loglevel, functionName, null)); }