Skip to content

Improve message-web text format issue #596 #1029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 17, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ void inheritanceHealth() {
"│Total Debt : 196│",
"├─────Actual──────┬─────Optimal─────┤",
"|roots 362│roots 120|",
"|edges 398│edges 444|",
"|total 760│total 564|",
"|edges 415│edges 461|",
"|total 777│total 581|",
"| 3 25.00%│ 3 21.43%|",
"| 1 8.33%│ 2 14.29%|",
"| 1 8.33%│ 3 21.43%|",
"| 2 16.67%│ 3 21.43%|",
"| 1 8.33%│ 0 0.00%|",
"| 0 0.00%│ 2 14.29%|",
"| 1 8.33%│ 2 14.29%|",
"| 3 25.00%│ 2 14.29%|",
"| 0 0.00%│ 0 0.00%|",
"| 2 16.67%│ 0 0.00%|",
"| 1 8.33%│ 1 7.14%|",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.mastercard.test.flow.msg.web;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Arrays;
Expand All @@ -12,11 +9,14 @@
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.openqa.selenium.WebDriver;

import com.fasterxml.jackson.databind.ObjectMapper;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.mastercard.test.flow.msg.AbstractMessage;

/**
Expand All @@ -43,7 +43,6 @@ public class WebSequence extends AbstractMessage<WebSequence> {
private static final ObjectMapper JSON = new ObjectMapper();

private final WebSequence parent;

private final SortedMap<String,
BiConsumer<WebDriver, Map<String, String>>> operations = new TreeMap<>();

Expand Down Expand Up @@ -94,28 +93,59 @@ public byte[] content() {

@Override
protected String asHuman() {
Map<String, String> params = results != null
? results
: parameters();
int nameWidth = params.keySet().stream()
.mapToInt( String::length )
.max().orElse( 1 );
String nvpFmt = " %" + nameWidth + "s : %s";
String padFmt = "\n %" + nameWidth + "s ";
String pad = String.format( padFmt, "" );
return String.format( "Operations:\n"
+ "%s\n"
+ "Parameters:\n"
+ "%s",
operations().keySet().stream()
.map( o -> " " + o )
.collect( joining( "\n" ) ),
params.entrySet().stream()
.map( e -> String.format( nvpFmt,
e.getKey(),
Stream.of( e.getValue().split( "\n" ) )
.collect( joining( pad ) ) ) )
.collect( joining( "\n" ) ) );
Map<String, String> params = results != null ? results : parameters();
SortedMap<String, BiConsumer<WebDriver, Map<String, String>>> ops = operations();

int nameWidth = Math.max(
params.keySet().stream().mapToInt( String::length ).max().orElse( 1 ),
"Parameters".length() );

int valueWidth = Math.max(
params.values().stream()
.flatMap( value -> Arrays.stream( value.split( "\\R" ) ) )
.mapToInt( str -> replaceTabs( str ).length() )
.max().orElse( 1 ),
"Values".length() );

int operationsWidth = Math.max(
ops.keySet().stream().mapToInt( String::length ).max().orElse( 1 ),
"Operations".length() );

String nvpPadFormat = "│ %-" + nameWidth + "s │ %-" + valueWidth + "s │";
String operationsPadFormat = "│ %-" + operationsWidth + "s │";

// For parameters: fixed characters ("│ ", " │ ", " │") add up to 7.
int paramsBoxWidth = nameWidth + valueWidth + 7;
// For operations: fixed characters ("│ ", " │") add up to 4.
int operationsBoxWidth = operationsWidth + 4;

String parametersBorder = "─".repeat( paramsBoxWidth - 2 );
String operationsBorder = "─".repeat( operationsBoxWidth - 2 );

String operationsStr = ops.keySet().stream()
.map( o -> String.format( operationsPadFormat, o ) )
.collect( Collectors.joining( "\n" ) );

String paramsStr = params.entrySet().stream()
.map( entry -> {
String key = entry.getKey();
String[] lines = entry.getValue().split( "\\R" );
return IntStream.range( 0, lines.length )
.mapToObj(
i -> String.format( nvpPadFormat, i == 0 ? key : "", replaceTabs( lines[i] ) ) )
.collect( Collectors.joining( "\n" ) );
} )
.collect( Collectors.joining( "\n" ) );

String operationsHeader = String.format( operationsPadFormat, "Operations" );
String operationsBox = formatBox( operationsBorder, operationsHeader, operationsStr,
String.format( operationsPadFormat, "" ) );

String parametersHeader = String.format( nvpPadFormat, "Parameters", "Values" );
String parametersBox = formatBox( parametersBorder, parametersHeader, paramsStr,
String.format( nvpPadFormat, "", "" ) );

return operationsBox + "\n" + parametersBox;
}

@Override
Expand Down Expand Up @@ -207,4 +237,22 @@ public byte[] process( WebDriver driver ) {
}
}

private String replaceTabs( String input ) {
return input.replace( "\t", " " );
}

private String formatBox( String border, String header, String content, String defaultContent ) {
if( content == null || content.isEmpty() ) {
content = defaultContent;
}
return String.format(
"""
┌%s┐
%s
├%s┤
%s
└%s┘""",
border, header, border, content, border );
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package com.mastercard.test.flow.msg.web;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;

import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -15,6 +10,11 @@
import org.mockito.Mockito;
import org.openqa.selenium.WebDriver;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;

import com.mastercard.test.flow.Unpredictable;

/**
Expand All @@ -29,11 +29,18 @@ class WebSequenceTest {
@Test
void empty() {
WebSequence ws = new WebSequence();
Assertions.assertEquals( ""
+ "Operations:\n"
+ "\n"
+ "Parameters:\n"
+ "",
Assertions.assertEquals(
"""
┌────────────┐
│ Operations │
├────────────┤
│ │
└────────────┘
┌─────────────────────┐
│ Parameters │ Values │
├─────────────────────┤
│ │ │
└─────────────────────┘""",
ws.assertable() );
}

Expand All @@ -45,15 +52,52 @@ void empty() {
void unprocessed() {
WebSequence ws = new WebSequence()
.set( "foo", "bar" )
.set( "multiline", "so\nmany\nlines with a lot of data" );
Assertions.assertEquals(
"""
┌────────────┐
│ Operations │
├────────────┤
│ │
└────────────┘
┌───────────────────────────────────────┐
│ Parameters │ Values │
├───────────────────────────────────────┤
│ foo │ bar │
│ multiline │ so │
│ │ many │
│ │ lines with a lot of data │
└───────────────────────────────────────┘""",
ws.assertable() );
}

/**
* Validate tabs for page source
*/
@Test
void pageSource() {
WebSequence ws = new WebSequence()
.set( "foo", "bar" )
.set( "page_source", "<html><head>\n\t\t<title>Histogram</title>\n\t</head></html>" )
.set( "multiline", "so\nmany\nlines" );
Assertions.assertEquals( ""
+ "Operations:\n"
+ "\n"
+ "Parameters:\n"
+ " foo : bar\n"
+ " multiline : so\n"
+ " many\n"
+ " lines",
Assertions.assertEquals(
"""
┌────────────┐
│ Operations │
├────────────┤
│ │
└────────────┘
┌────────────────────────────────────────────────┐
│ Parameters │ Values │
├────────────────────────────────────────────────┤
│ foo │ bar │
│ multiline │ so │
│ │ many │
│ │ lines │
│ page_source │ <html><head> │
│ │ <title>Histogram</title> │
│ │ </head></html> │
└────────────────────────────────────────────────┘""",
ws.assertable() );
}

Expand All @@ -74,13 +118,20 @@ void processed() {

WebSequence results = ws.peer( ws.process( null ) );

Assertions.assertEquals( ""
+ "Operations:\n"
+ " param update\n"
+ "Parameters:\n"
+ " a : b\n"
+ " c : i\n"
+ " g : h",
Assertions.assertEquals(
"""
┌──────────────┐
│ Operations │
├──────────────┤
│ param update │
└──────────────┘
┌─────────────────────┐
│ Parameters │ Values │
├─────────────────────┤
│ a │ b │
│ c │ i │
│ g │ h │
└─────────────────────┘""",
results.assertable() );
}

Expand Down Expand Up @@ -109,7 +160,7 @@ void fields() {
void get() {
WebSequence ws = new WebSequence()
.set( "a", "b" );
Assertions.assertEquals( null, ws.get( "foo" ) );
Assertions.assertNull( ws.get( "foo" ) );
Assertions.assertEquals( "b", ws.get( "a" ) );
}

Expand All @@ -127,11 +178,19 @@ void peer() {

WebSequence peer = ws.peer( ws.content() );

Assertions.assertEquals( ""
+ "Operations:\n"
+ " op\n"
+ "Parameters:\n"
+ " a : b", peer.assertable() );
Assertions.assertEquals(
"""
┌────────────┐
│ Operations │
├────────────┤
│ op │
└────────────┘
┌─────────────────────┐
│ Parameters │ Values │
├─────────────────────┤
│ a │ b │
└─────────────────────┘""",
peer.assertable() );

Assertions.assertEquals( "Operation has not been invoked!", ref.get() );

Expand Down Expand Up @@ -170,11 +229,18 @@ void masking() {
.masking( rng, m -> m.delete( "c" ) );

WebSequence peer = ws.peer( ws.content() );
Assertions.assertEquals( ""
+ "Operations:\n"
+ "\n"
+ "Parameters:\n"
+ " a : b",
Assertions.assertEquals(
"""
┌────────────┐
│ Operations │
├────────────┤
│ │
└────────────┘
┌─────────────────────┐
│ Parameters │ Values │
├─────────────────────┤
│ a │ b │
└─────────────────────┘""",
peer.assertable( rng ) );
}

Expand Down Expand Up @@ -207,15 +273,22 @@ void sequence() {
+ "third operation invoked with {a=b, c=d}]",
operations.toString() );

Assertions.assertEquals( ""
+ "Operations:\n"
+ " first\n"
+ " second\n"
+ " third\n"
+ "Parameters:\n"
+ " a : b\n"
+ " c : d\n"
+ " e : f",
Assertions.assertEquals(
"""
┌────────────┐
│ Operations │
├────────────┤
│ first │
│ second │
│ third │
└────────────┘
┌─────────────────────┐
│ Parameters │ Values │
├─────────────────────┤
│ a │ b │
│ c │ d │
│ e │ f │
└─────────────────────┘""",
results.assertable() );
}

Expand Down
Loading