Feature Add a badge for the logs tab
MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/scriptrunner/impl/jsonreport/JsonReport.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/scriptrunner/impl/jsonreport/JsonReport.java
@@ -595,8 +595,15 @@ public class JsonReport implements IScriptReport {
public void createLogTable(List<String> header, List<LoggerRow> rows) {
assertState(ContextType.TESTCASE, ContextType.ACTION, ContextType.ACTIONGROUP);
-
- rows.stream().map(LogEntry::new).forEachOrdered(jsonpTestcaseWriter::write);
+ TestCase testCase = context.getFirstParentNode(TestCase.class);
+ List<LogEntry> entries = rows.stream().map(LogEntry::new).collect(Collectors.toList());
+ Set<String> levels = entries.stream().map(LogEntry::getLevel).collect(Collectors.toSet());
+ testCase.setHasErrorLogs(levels.contains("ERROR"));
+ testCase.setHasWarnLogs(levels.contains("WARN"));
+
+ exportToFile(testCase, testCase.getName(), false);
+ jsonpTestcaseWriter.updateTestCaseFile(testCase);
+ entries.forEach(jsonpTestcaseWriter::write);
}
public void setOutcomes(OutcomeCollector outcomes) {

MODIFY
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/scriptrunner/impl/jsonreport/beans/TestCase.java
BackEnd/Core/sailfish-core/src/main/java/com/exactpro/sf/scriptrunner/impl/jsonreport/beans/TestCase.java
@@ -47,6 +47,8 @@ public class TestCase implements IJsonReportNode {
private int hash;
private String description;
private Status status;
+ private boolean hasErrorLogs;
+ private boolean hasWarnLogs;
@JsonIgnore private final BugCategory bugRoot;
@JsonIgnore private Map<Bug, List<String>> bugToCategoryMap;
@@ -202,4 +204,20 @@ public class TestCase implements IJsonReportNode {
public void setTags(Set<String> tags) {
this.tags = tags;
}
+
+ public boolean hasErrorLogs() {
+ return hasErrorLogs;
+ }
+
+ public void setHasErrorLogs(boolean hasErrorLogs) {
+ this.hasErrorLogs = hasErrorLogs;
+ }
+
+ public boolean hasWarnLogs() {
+ return hasWarnLogs;
+ }
+
+ public void setHasWarnLogs(boolean hasWarnLogs) {
+ this.hasWarnLogs = hasWarnLogs;
+ }
}

MODIFY
BackEnd/Core/sailfish-core/src/main/kotlin/com/exactpro/sf/scriptrunner/impl/jsonreport/beans/JsonpTestcase.kt
BackEnd/Core/sailfish-core/src/main/kotlin/com/exactpro/sf/scriptrunner/impl/jsonreport/beans/JsonpTestcase.kt
@@ -19,7 +19,6 @@ package com.exactpro.sf.scriptrunner.impl.jsonreport.beans
import com.exactpro.sf.scriptrunner.impl.jsonreport.IJsonReportNode
import com.exactpro.sf.scriptrunner.impl.jsonreport.JsonpChunkedDataWriter
import com.exactpro.sf.scriptrunner.impl.jsonreport.helpers.WorkspaceNode
-import java.nio.file.Path
import java.time.Instant
class JsonpTestcase(
@@ -45,6 +44,8 @@ class JsonpTestcase(
val description: String? = testCase.description
val status: Status? = testCase.status
val bugs: Collection<IJsonReportNode> = testCase.bugTree
+ val hasErrorLogs: Boolean = testCase.hasErrorLogs()
+ val hasWarnLogs: Boolean = testCase.hasWarnLogs()
val indexFiles: Map<String, String> = dataWriters.asSequence().associate {
it.key.simpleName.toLowerCase() to reportRoot.toAbsolutePath().relativize(it.value.indexFile.toAbsolutePath()).toString()

MODIFY
FrontEnd/Sailfish-JS-report/src/__tests__/util/creators.ts
FrontEnd/Sailfish-JS-report/src/__tests__/util/creators.ts
@@ -88,7 +88,9 @@ export function createTestCase(id: string = '0', actions: ActionNode[] = [], mes
hash: 0,
status: { status },
startTime: new Date().toString(),
- finishTime: new Date().toString()
+ finishTime: new Date().toString(),
+ hasErrorLogs: false,
+ hasWarnLogs: false
}
}

MODIFY
FrontEnd/Sailfish-JS-report/src/components/LeftPanel.tsx
FrontEnd/Sailfish-JS-report/src/components/LeftPanel.tsx
@@ -62,14 +62,16 @@ class LeftPanelBase extends React.Component<Props> {
<div className="layout-panel__tabs">
<ToggleButton
isToggled={panel == Panel.ACTIONS}
- onClick={() => this.selectPanel(Panel.ACTIONS)}
- text="Actions" />
+ onClick={() => this.selectPanel(Panel.ACTIONS)}>
+ Actions
+ </ToggleButton>
<ToggleButton
isToggled={panel == Panel.STATUS}
isDisabled={!statusEnabled}
onClick={statusEnabled ? (() => this.selectPanel(Panel.STATUS)) : undefined}
- text="Status"
- title={statusEnabled ? null : "No status info"}/>
+ title={statusEnabled ? null : "No status info"}>
+ Status
+ </ToggleButton>
</div>
{
isCheckpointsEnabled ? (

MODIFY
FrontEnd/Sailfish-JS-report/src/components/ReportLayout.tsx
FrontEnd/Sailfish-JS-report/src/components/ReportLayout.tsx
@@ -150,13 +150,15 @@ export class ReportLayoutBase extends React.Component<Props, State> {
<ToggleButton
textClass="report-summary__button_text"
isToggled={this.state.panel == Panel.ReportSummary}
- onClick={changePanel(Panel.ReportSummary)}
- text="Report Summary"/>
+ onClick={changePanel(Panel.ReportSummary)}>
+ Report Summary
+ </ToggleButton>
<ToggleButton
textClass="report-summary__button_text"
isToggled={this.state.panel == Panel.RunInfo}
- onClick={changePanel(Panel.RunInfo)}
- text="Run Information"/>
+ onClick={changePanel(Panel.RunInfo)}>
+ Run Information
+ </ToggleButton>
</div>
{
this.getPanel()

MODIFY
FrontEnd/Sailfish-JS-report/src/components/RightPanel.tsx
FrontEnd/Sailfish-JS-report/src/components/RightPanel.tsx
@@ -31,7 +31,7 @@ import {
togglePredictions,
uglifyAllMessages
} from '../actions/actionCreators';
-import { createStyleSelector, createTriStateControlClassName } from '../helpers/styleCreators';
+import { createStyleSelector, createTriStateControlClassName, createBemElement } from '../helpers/styleCreators';
import { isAction } from "../models/Action";
import { KnownBugPanel } from "./knownbugs/KnownBugPanel";
import { StatusType } from '../models/Status';
@@ -51,6 +51,8 @@ interface StateProps {
hasKnownBugs: boolean;
beautifiedMessagesEnabled: boolean;
hasLogs: boolean;
+ hasErrorLogs: boolean;
+ hasWarningLogs: boolean;
}
interface DispatchProps {
@@ -114,10 +116,13 @@ class RightPanelBase extends React.Component<Props, State> {
const {
panel, rejectedMessagesEnabled, adminMessages, adminMessagesEnabled, adminEnabledHandler, selectCurrentRejectedMessage,
predictionsEnabled, predictionsAvailable, beautifiedMessagesEnabled, uglifyAllHandler, hasLogs, hasKnownBugs,
+ hasErrorLogs, hasWarningLogs
} = this.props;
const adminControlEnabled = adminMessages.length != 0;
+ const logChipClassName = createBemElement('log-button', 'chip', hasErrorLogs? 'error': hasWarningLogs? 'warning': 'hiden')
+
const adminRootClass = createTriStateControlClassName("layout-control", adminMessagesEnabled, adminControlEnabled),
adminIconClass = createTriStateControlClassName("layout-control__icon admin", adminMessagesEnabled, adminControlEnabled),
adminTitleClass = createTriStateControlClassName("layout-control__title selectable", adminMessagesEnabled, adminControlEnabled),
@@ -137,18 +142,24 @@ class RightPanelBase extends React.Component<Props, State> {
<div className="layout-panel__tabs">
<ToggleButton
isToggled={panel == Panel.MESSAGES}
- onClick={() => this.selectPanel(Panel.MESSAGES)}
- text="Messages"/>
+ onClick={() => this.selectPanel(Panel.MESSAGES)}>
+ Messages
+ </ToggleButton>
<ToggleButton
isToggled={panel == Panel.KNOWN_BUGS}
isDisabled={!hasKnownBugs}
- onClick={() => this.selectPanel(Panel.KNOWN_BUGS)}
- text="Known bugs"/>
+ onClick={() => this.selectPanel(Panel.KNOWN_BUGS)}>
+ Known bugs
+ </ToggleButton>
<ToggleButton
isDisabled={!hasLogs}
isToggled={panel == Panel.LOGS}
- onClick={() => this.selectPanel(Panel.LOGS)}
- text="Logs" />
+ onClick={() => this.selectPanel(Panel.LOGS)}>
+ <div className="log-button">
+ <p>Logs</p>
+ <div className={logChipClassName}/>
+ </div>
+ </ToggleButton>
</div>
{
beautifiedMessagesEnabled ? (
@@ -272,7 +283,9 @@ export const RightPanel = connect(
predictionsEnabled: state.machineLearning.predictionsEnabled,
hasKnownBugs: state.selected.testCase.bugs.length > 0,
- hasLogs: state.selected.testCase.files.logentry.count > 0
+ hasLogs: state.selected.testCase.files.logentry.count > 0,
+ hasErrorLogs: state.selected.testCase.hasErrorLogs,
+ hasWarningLogs: state.selected.testCase.hasWarnLogs
}),
(dispatch) => ({
panelSelectHandler: (panel: Panel.MESSAGES | Panel.KNOWN_BUGS | Panel.LOGS) => dispatch(setRightPane(panel)),

MODIFY
FrontEnd/Sailfish-JS-report/src/components/ToggleButton.tsx
FrontEnd/Sailfish-JS-report/src/components/ToggleButton.tsx
@@ -18,17 +18,26 @@ import * as React from 'react';
import '../styles/buttons.scss';
import { createStyleSelector } from '../helpers/styleCreators';
+type ToggleButtonContent = string | React.ReactNode
+
interface Props {
onClick?: Function;
isToggled?: boolean;
isDisabled?: boolean;
- text: string;
title?: string;
theme?: string;
textClass?: string;
+ children: ToggleButtonContent;
}
-export function ToggleButton({ onClick = () => {}, isToggled = false, text, textClass, theme = 'default', isDisabled = false, title = '' }: Props) {
+export function ToggleButton({ onClick = () => { },
+ isToggled = false,
+ theme = 'default',
+ isDisabled = false,
+ title = '',
+ textClass,
+ children: content }: Props) {
+
const className = createStyleSelector(
"toggle-button",
theme,
@@ -36,10 +45,18 @@ export function ToggleButton({ onClick = () => {}, isToggled = false, text, text
isToggled ? "toggled" : null
);
+ if (textClass) {
+ content = (
+ <span className={textClass}>
+ {content}
+ </span>
+ )
+ }
+
return (
- <div className={className} onClick={() => !isDisabled && onClick(text)} title={title}>
+ <div className={className} onClick={() => !isDisabled && onClick(content)} title={title}>
<div className="toggle-button__title">
- <p className={textClass}>{text}</p>
+ {content}
</div>
</div>
)

MODIFY
FrontEnd/Sailfish-JS-report/src/models/TestCase.ts
FrontEnd/Sailfish-JS-report/src/models/TestCase.ts
@@ -43,6 +43,8 @@ export default interface TestCase {
indexFiles?: TestCaseIndexFiles;
files?: TestCaseFiles;
lastUpdate?: string;
+ hasErrorLogs: boolean;
+ hasWarnLogs: boolean;
}
interface TestCaseIndexFiles {

MODIFY
FrontEnd/Sailfish-JS-report/src/styles/report.scss
FrontEnd/Sailfish-JS-report/src/styles/report.scss
}
}
+.log-button {
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+
+ &__chip {
+ margin-left: 12px;
+ border-radius: 5px;
+ width: 12px;
+ height: 12px;
+
+ &.error {
+ background: #E23636;
+ }
+
+ &.warning {
+ background: #F57A3D;
+ }
+
+ &.hiden {
+ display: none;
+ }
+ }
+}
+
.tc-card {
@include status-card-with-running;

Feature #63303. Add a badge for the logs tab

Change-Id: Ic2efae5330e0428e9f99ee61a25cc8448431c586