Skip to content

Commit 8281a46

Browse files
committed
feat(cli): Improve console display
1 parent 9287078 commit 8281a46

7 files changed

Lines changed: 50 additions & 45 deletions

File tree

src/main/java/dev/dochia/cli/core/DochiaMain.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import dev.dochia.cli.core.util.ConsoleUtils;
77
import io.github.ludovicianul.prettylogger.PrettyLogger;
88
import io.github.ludovicianul.prettylogger.PrettyLoggerFactory;
9+
import io.quarkus.runtime.Quarkus;
910
import io.quarkus.runtime.QuarkusApplication;
1011
import io.quarkus.runtime.annotations.QuarkusMain;
1112
import jakarta.inject.Inject;
@@ -15,7 +16,6 @@
1516
import java.io.FileInputStream;
1617
import java.io.InputStream;
1718
import java.util.Arrays;
18-
import java.util.Locale;
1919
import java.util.Properties;
2020

2121
/**
@@ -32,6 +32,12 @@ public class DochiaMain implements QuarkusApplication {
3232

3333
private final PrettyLogger logger = PrettyLoggerFactory.getLogger(DochiaMain.class);
3434

35+
public static void main(String[] args) {
36+
checkForSummaryReport(args);
37+
38+
Quarkus.run(DochiaMain.class, args);
39+
}
40+
3541
@Override
3642
public int run(String... args) {
3743
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
@@ -62,6 +68,13 @@ public int run(String... args) {
6268
return commandLine.setParameterExceptionHandler(new ShortErrorMessageHandler()).execute(args);
6369
}
6470

71+
private static void checkForSummaryReport(String[] args) {
72+
boolean verbose = Arrays.asList(args).contains("-vv") || Arrays.asList(args).contains("-vvv");
73+
if (verbose) {
74+
System.setProperty("quarkus.log.console.format", "[%X{id_ansi}][%X{playbook}] %m %n");
75+
}
76+
}
77+
6578
private void loadConfigIfSupplied(CommandLine commandLine, String... args) {
6679
File configFile = findConfigFile(args);
6780
if (configFile != null && configFile.exists()) {
@@ -77,7 +90,7 @@ private void loadConfigIfSupplied(CommandLine commandLine, String... args) {
7790
}
7891

7992
private void checkForConsoleColorsDisabled(String... args) {
80-
boolean colorsDisabled = Arrays.stream(args).anyMatch(arg -> arg.trim().toLowerCase(Locale.ROOT).equals("--no-color"));
93+
boolean colorsDisabled = Arrays.asList(args).contains("--no-color");
8194
if (colorsDisabled) {
8295
PrettyLogger.disableColors();
8396
PrettyLogger.changeMessageFormat("%1$-12s");

src/main/java/dev/dochia/cli/core/args/ReportingArguments.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ public static List<PrettyLevel> getAsPrettyLevelList(List<String> logsAsString)
9090
*/
9191
public void processLogData() {
9292
if (isVerbosityOne()) {
93-
PrettyLogger.enableLevels(PrettyLevel.CONFIG, PrettyLevel.FATAL);
93+
PrettyLogger.enableLevels(PrettyLevel.CONFIG, PrettyLevel.FATAL, PrettyLevel.TIMER);
9494
} else if (isNoVerbosity()) {
95-
PrettyLogger.enableLevels(PrettyLevel.FATAL);
95+
PrettyLogger.enableLevels(PrettyLevel.FATAL, PrettyLevel.TIMER);
9696
} else {
9797
prepareDetailedLogging();
9898
}
@@ -114,10 +114,6 @@ private boolean isVerbosityThree() {
114114
return verbosity != null && verbosity.length >= 3;
115115
}
116116

117-
private void prepareSummaryLogging() {
118-
119-
}
120-
121117
private void prepareDetailedLogging() {
122118
if (isVerbosityThree()) {
123119
CommonUtils.setDochiaLogLevel("ALL");

src/main/java/dev/dochia/cli/core/command/TestCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ private void doLogic() throws IOException {
210210
testCaseListener.initReportingPath();
211211
this.printConfiguration(openAPI);
212212
this.initGlobalData(openAPI);
213-
testCaseListener.renderFuzzingHeader();
214213
this.startFuzzing(openAPI);
215214
}
216215

@@ -279,6 +278,8 @@ private void initGlobalData(OpenAPI openAPI) {
279278
}
280279

281280
void startFuzzing(OpenAPI openAPI) {
281+
testCaseListener.renderStartHeader();
282+
282283
List<String> suppliedPaths = filterArguments.getPathsToRun(openAPI);
283284

284285
for (Map.Entry<String, PathItem> entry :

src/main/java/dev/dochia/cli/core/report/TestCaseExporter.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.github.ludovicianul.prettylogger.PrettyLoggerFactory;
2020
import jakarta.inject.Inject;
2121
import lombok.Getter;
22+
import lombok.extern.slf4j.Slf4j;
2223
import org.apache.commons.lang3.StringUtils;
2324
import org.eclipse.microprofile.config.inject.ConfigProperty;
2425
import org.fusesource.jansi.Ansi;
@@ -47,6 +48,7 @@
4748
* This class is responsible for writing the final report file(s).
4849
*/
4950

51+
@Slf4j
5052
public abstract class TestCaseExporter {
5153
static final String REPORT_HTML = "index.html";
5254
static final MustacheFactory mustacheFactory = new DefaultMustacheFactory();
@@ -157,9 +159,9 @@ public void writeErrorsByReason(List<TestCaseSummary> testCaseSummaryDetails) {
157159
}
158160
String redCross = ansi().fgRed().a("✖").reset().toString();
159161
ConsoleUtils.emptyLine();
160-
logger.info("Errors by reason:");
162+
logger.info("Errors found:");
161163
resultReasonCounts.forEach((reason, count) ->
162-
logger.noFormat(" {} {}: {} errors", redCross, reason, count));
164+
logger.noFormat(" {} {} ({} error(s))", redCross, reason, count));
163165
}
164166

165167
/**
@@ -237,16 +239,17 @@ private void writeExecutionTimesForPathAndHttpMethod(String key, List<TestCaseEx
237239
* @param executionStatisticsListener the listener providing statistics on dochia execution
238240
*/
239241
public void printExecutionDetails(ExecutionStatisticsListener executionStatisticsListener) {
240-
String dochiaFinished = ansi().fgBlue().a("dochia finished in {}. Total requests {}. ").toString();
241-
String passed = ansi().fgGreen().bold().a("✔ Passed {}, ").toString();
242-
String warnings = ansi().fgYellow().bold().a("⚠ warnings: {}, ").toString();
243-
String errors = ansi().fgRed().bold().a("‼ errors: {}").toString();
244-
String check = ansi().reset().fgBlue().a(String.format("You can open the report here: %s ", reportingPath.toUri() + getSummaryReportTitle())).reset().toString();
242+
String dochiaFinished = ansi().fgBlue().a("{} tests completed in {}\n").toString();
243+
String passed = ansi().fgGreen().bold().a(" ✔ {} passed, ").toString();
244+
String warnings = ansi().fgYellow().bold().a("⚠ {} warnings, ").toString();
245+
String errors = ansi().fgRed().bold().a("‼ {} errors").toString();
246+
String check = ansi().reset().fgBlue().a(String.format("Full Report: %s ", reportingPath.toUri() + getSummaryReportTitle())).reset().toString();
245247
String finalMessage = dochiaFinished + passed + warnings + errors;
246248
String duration = Duration.ofMillis(System.currentTimeMillis() - t0).toString().toLowerCase(Locale.ROOT).substring(2);
247249

248250
ConsoleUtils.emptyLine();
249-
logger.complete(finalMessage, duration, executionStatisticsListener.getAll(), executionStatisticsListener.getSuccess(), executionStatisticsListener.getWarns(), executionStatisticsListener.getErrors(), executionStatisticsListener.getSkipped());
251+
logger.complete(finalMessage, executionStatisticsListener.getAll(), duration, executionStatisticsListener.getSuccess(), executionStatisticsListener.getWarns(), executionStatisticsListener.getErrors(), executionStatisticsListener.getSkipped());
252+
ConsoleUtils.emptyLine();
250253
logger.complete(check);
251254
}
252255

src/main/java/dev/dochia/cli/core/report/TestCaseListener.java

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
import dev.dochia.cli.core.args.IgnoreArguments;
99
import dev.dochia.cli.core.args.ReportingArguments;
1010
import dev.dochia.cli.core.context.GlobalContext;
11-
import dev.dochia.cli.core.playbook.api.DryRun;
12-
import dev.dochia.cli.core.playbook.api.TestCasePlaybook;
1311
import dev.dochia.cli.core.http.HttpMethod;
1412
import dev.dochia.cli.core.http.ResponseCodeFamily;
1513
import dev.dochia.cli.core.http.ResponseCodeFamilyDynamic;
1614
import dev.dochia.cli.core.http.ResponseCodeFamilyPredefined;
1715
import dev.dochia.cli.core.model.*;
16+
import dev.dochia.cli.core.playbook.api.DryRun;
17+
import dev.dochia.cli.core.playbook.api.TestCasePlaybook;
1818
import dev.dochia.cli.core.util.ConsoleUtils;
1919
import dev.dochia.cli.core.util.WordUtils;
2020
import io.github.ludovicianul.prettylogger.PrettyLogger;
@@ -135,9 +135,9 @@ public void afterFuzz(String path) {
135135
* Creates and executes a test by running the provided runnable.
136136
* Logs test start, catches exceptions during execution, logs results, and performs necessary cleanup.
137137
*
138-
* @param externalLogger the external logger for logging test-related information
139-
* @param testCasePlaybook the playbook associated with the test
140-
* @param s the runnable representing the test logic
138+
* @param externalLogger the external logger for logging test-related information
139+
* @param testCasePlaybook the playbook associated with the test
140+
* @param s the runnable representing the test logic
141141
*/
142142
public void createAndExecuteTest(PrettyLogger externalLogger, TestCasePlaybook testCasePlaybook, Runnable s, PlaybookData data) {
143143
this.startTestCase(data);
@@ -337,11 +337,6 @@ public void notifySummaryObservers(String path) {
337337
}
338338
}
339339

340-
private void renderGlobalPlaybooksStatistics() {
341-
String toRenderPreviousPath = "global" + ConsoleUtils.SEPARATOR + executionStatisticsListener.resultAsStringPerPath("N/A");
342-
ConsoleUtils.renderNewRow(toRenderPreviousPath, '✔');
343-
}
344-
345340
private void markPreviousPathAsDone() {
346341
String previousPath = runPerPathListener.peek();
347342
if (previousPath != null) {
@@ -369,14 +364,11 @@ public void startSession() {
369364
MDC.put(PLAYBOOK, this.getKeyDefault());
370365
MDC.put(PLAYBOOK_KEY, this.getKeyDefault());
371366

372-
String osDetails = System.getProperty("os.name") + "-" + System.getProperty("os.version") + "-" + System.getProperty("os.arch");
373-
374367
ConsoleUtils.emptyLine();
375-
logger.start(ansi().bold().a("Starting {}-{}, build time {} UTC, platform {}").reset().toString(),
368+
logger.start(ansi().bold().a("Starting {}-{}, build time {} UTC").reset().toString(),
376369
ansi().fg(Ansi.Color.GREEN).a(appName),
377370
ansi().fg(Ansi.Color.GREEN).a(appVersion),
378-
ansi().fg(Ansi.Color.GREEN).a(appBuildTime),
379-
ansi().fg(Ansi.Color.GREEN).a(osDetails).reset());
371+
ansi().fg(Ansi.Color.GREEN).a(appBuildTime));
380372
}
381373

382374
/**
@@ -421,22 +413,23 @@ public void writeHelperFiles() {
421413
*/
422414
public void endSession() {
423415
markPreviousPathAsDone();
424-
renderGlobalPlaybooksStatistics();
425416
reportingArguments.enableAdditionalLoggingIfSummary();
426417
testReportsGenerator.writeSummary(testCaseSummaryDetails, executionStatisticsListener);
427418
testReportsGenerator.writeHelperFiles();
419+
ConsoleUtils.emptyLine();
428420
testReportsGenerator.writeErrorsByReason(testCaseSummaryDetails);
429421
testReportsGenerator.writePerformanceReport(testCaseExecutionDetails);
430422
testReportsGenerator.printExecutionDetails(executionStatisticsListener);
431423
writeRecordedErrorsIfPresent();
432424
}
433425

434426
/**
435-
* Renders a FUZZING header if logging is SUMMARY.
427+
* Renders a starting header if logging is SUMMARY.
436428
*/
437-
public void renderFuzzingHeader() {
429+
public void renderStartHeader() {
438430
if (reportingArguments.isSummaryInConsole()) {
439-
ConsoleUtils.renderHeader(" FUZZING ");
431+
ConsoleUtils.emptyLine();
432+
ConsoleUtils.renderHeader("Running tests...");
440433
}
441434
}
442435

@@ -839,7 +832,7 @@ public boolean isFieldNotADiscriminator(String fuzzedField) {
839832
/**
840833
* Returns the expected HTTP response code from the --playbooks-config file
841834
*
842-
* @param playbook the name of the playbook
835+
* @param playbook the name of the playbook
843836
* @param defaultValue default value when property is not found
844837
* @return the value of the property if found or null otherwise
845838
*/

src/main/java/dev/dochia/cli/core/util/ConsoleUtils.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
import io.github.ludovicianul.prettylogger.PrettyLogger;
44
import io.github.ludovicianul.prettylogger.PrettyLoggerFactory;
5-
import java.util.Optional;
6-
import java.util.regex.Pattern;
75
import lombok.Getter;
86
import org.apache.commons.lang3.StringUtils;
97
import org.fusesource.jansi.Ansi;
108
import picocli.CommandLine;
119

10+
import java.util.Optional;
11+
import java.util.regex.Pattern;
12+
1213
/**
1314
* Utility class for console-related operations.
1415
*/
@@ -40,7 +41,7 @@ private ConsoleUtils() {
4041
*/
4142
public static void initTerminalWidth(CommandLine.Model.CommandSpec spec) {
4243
try {
43-
terminalWidth = spec.usageMessage().width();
44+
terminalWidth = Math.min(140, spec.usageMessage().width());
4445
} catch (Exception e) {
4546
terminalWidth = 80;
4647
}
@@ -132,7 +133,7 @@ public static void renderNewRow(String path, char progress) {
132133
public static void renderRow(String prefix, String path, char progressChar) {
133134
String withoutAnsi = ANSI_REMOVE_PATTERN.matcher(path).replaceAll("");
134135
int dots = Math.max(terminalWidth - withoutAnsi.length() - 2, 1);
135-
String firstPart = path.substring(0, path.indexOf(SEPARATOR));
136+
String firstPart = " ".repeat(3) + path.substring(0, path.indexOf(SEPARATOR));
136137
String secondPart = path.substring(path.indexOf(SEPARATOR) + 1);
137138
String toPrint = Ansi.ansi().bold().a(prefix + firstPart + " " + ".".repeat(dots) + secondPart + " " + progressChar).reset().toString();
138139

@@ -156,9 +157,7 @@ public static int getConsoleColumns(int toSubtract) {
156157
* @param header The header text to be rendered.
157158
*/
158159
public static void renderHeader(String header) {
159-
LOGGER.noFormat(" ");
160-
int equalsNo = (terminalWidth - header.length()) / 2;
161-
LOGGER.noFormat(Ansi.ansi().bold().a("=".repeat(equalsNo) + header + "=".repeat(equalsNo)).reset().toString());
160+
System.out.print("\uD83E\uDDEA " + Ansi.ansi().bold().a(header).reset().toString());
162161
}
163162

164163
/**

src/main/resources/application.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ quarkus.log.category."dev.dochia.cli".level=INFO
1919
quarkus.log.category."okhttp3".level=OFF
2020
quarkus.log.category."okio".level=OFF
2121
quarkus.banner.enabled=false
22-
quarkus.log.console.format=[%X{id_ansi}][%X{testCasePlaybook}] %m %n
22+
quarkus.log.console.format=%m%n

0 commit comments

Comments
 (0)