From f56f2be9fbb5148576c7aff8c63081cb58fd010c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRafael?= <“francisco.lezama@encora.com”> Date: Wed, 8 Jan 2025 11:11:16 -0600 Subject: [PATCH 1/4] Improve message-web text format issue #596 --- .../test/flow/msg/web/WebSequence.java | 158 ++++++++++-------- 1 file changed, 86 insertions(+), 72 deletions(-) diff --git a/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java b/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java index 7950e86d88..d2c304ddb0 100644 --- a/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java +++ b/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java @@ -1,7 +1,6 @@ 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; @@ -12,6 +11,7 @@ import java.util.TreeMap; import java.util.TreeSet; import java.util.function.BiConsumer; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.openqa.selenium.WebDriver; @@ -44,8 +44,7 @@ public class WebSequence extends AbstractMessage { private final WebSequence parent; - private final SortedMap>> operations = new TreeMap<>(); + private final SortedMap>> operations = new TreeMap<>(); private Map results; @@ -56,28 +55,27 @@ public WebSequence() { parent = null; } - private WebSequence( WebSequence parent ) { + private WebSequence(WebSequence parent) { this.parent = parent; } @Override public WebSequence child() { - return copyMasksTo( new WebSequence( self() ) ); + return copyMasksTo(new WebSequence(self())); } @Override - public WebSequence peer( byte[] bytes ) { - WebSequence peer = copyMasksTo( new WebSequence( parent ) ); - peer.operations.putAll( operations ); + public WebSequence peer(byte[] bytes) { + WebSequence peer = copyMasksTo(new WebSequence(parent)); + peer.operations.putAll(operations); try { - ((Map) JSON.readValue( bytes, Map.class )) - .forEach( peer::set ); - } - catch( IOException ioe ) { - throw new UncheckedIOException( String.format( + ((Map) JSON.readValue(bytes, Map.class)) + .forEach(peer::set); + } catch (IOException ioe) { + throw new UncheckedIOException(String.format( "Failed to parse '%s' (%s)", - new String( bytes, UTF_8 ), Arrays.toString( bytes ) ), - ioe ); + new String(bytes, UTF_8), Arrays.toString(bytes)), + ioe); } return peer; } @@ -85,42 +83,62 @@ public WebSequence peer( byte[] bytes ) { @Override public byte[] content() { try { - return JSON.writeValueAsBytes( parameters() ); - } - catch( IOException ioe ) { - throw new UncheckedIOException( ioe ); + return JSON.writeValueAsBytes(parameters()); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); } } @Override protected String asHuman() { - Map params = results != null - ? results - : parameters(); + // Get the parameters to use. If 'results' is not null, use 'results', otherwise + // use 'parameters()'. + Map params = results != null ? results : parameters(); + + // Find the maximum length of the parameter names. This is used for formatting. 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" + .mapToInt(String::length) + .max().orElse(1); + + // Define the format for name-value pairs and padding for multi-line values. + String nvpFmt = " │ %" + nameWidth + "s │ %s │"; + String padFmt = "\n │ %" + nameWidth + "s "; + String pad = String.format(padFmt, ""); + + // Create the formatted string for operations. + String operationsStr = operations().keySet().stream() + .map(o -> " │ " + o + " │") + .collect(Collectors.joining("\n")); + + // Create the formatted string for parameters. + String paramsStr = params.entrySet().stream() + .map(e -> String.format(nvpFmt, + e.getKey(), + Stream.of(e.getValue().split("\n")) + .collect(Collectors.joining(pad)))) + .collect(Collectors.joining("\n")); + + // Create a borderline for the box drawing. + String border = "─".repeat(nameWidth + 4); + + // Return the final formatted string with box drawing characters. + return String.format("┌%s┐\n" + + "│ Operations │\n" + + "├%s┤\n" + + "%s\n" + + "└%s┘\n" + + "┌%s┐\n" + + "│ Parameters │ Values │\n" + + "├%s┤\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" ) ) ); + + "└%s┘", + border, border, operationsStr, border, + border, border, paramsStr, border); } @Override public Set fields() { - return new TreeSet<>( parameters().keySet() ); + return new TreeSet<>(parameters().keySet()); } /** @@ -132,37 +150,36 @@ public Set fields() { * operation * @return this */ - public WebSequence operation( String name, - BiConsumer> op ) { - operations.put( name, op ); + public WebSequence operation(String name, + BiConsumer> op) { + operations.put(name, op); return self(); } @Override - protected Object access( String field ) { - return parameters().get( field ); + protected Object access(String field) { + return parameters().get(field); } private SortedMap>> operations() { SortedMap>> op = new TreeMap<>(); - if( parent != null ) { - op.putAll( parent.operations() ); + if (parent != null) { + op.putAll(parent.operations()); } - op.putAll( operations ); + op.putAll(operations); return op; } private Map parameters() { Map p = new TreeMap<>(); - if( parent != null ) { - p.putAll( parent.parameters() ); + if (parent != null) { + p.putAll(parent.parameters()); } - for( Update update : updates ) { - if( update.value() == DELETE ) { - p.remove( update.field() ); - } - else { - p.put( update.field(), String.valueOf( update.value() ) ); + for (Update update : updates) { + if (update.value() == DELETE) { + p.remove(update.field()); + } else { + p.put(update.field(), String.valueOf(update.value())); } } return p; @@ -174,36 +191,33 @@ private Map parameters() { * @param driver the browser to drive * @return The state of the parameters map after all operations have completed */ - public byte[] process( WebDriver driver ) { + public byte[] process(WebDriver driver) { Map params = parameters(); - operations().forEach( ( name, op ) -> { - if( op != null ) { + operations().forEach((name, op) -> { + if (op != null) { try { - op.accept( driver, params ); - } - catch( Exception e ) { + op.accept(driver, params); + } catch (Exception e) { // our operation has failed! String url = "No URL"; String source = "No page source"; try { url = driver.getCurrentUrl(); source = driver.getPageSource(); - } - catch( Exception f ) { + } catch (Exception f) { source = f.getMessage(); } - throw new IllegalStateException( String.format( + throw new IllegalStateException(String.format( "Operation '%s' failed on page '%s'\n%s", - name, url, source ), - e ); + name, url, source), + e); } } - } ); + }); try { - return JSON.writeValueAsBytes( params ); - } - catch( IOException ioe ) { - throw new UncheckedIOException( ioe ); + return JSON.writeValueAsBytes(params); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); } } From 958530d17584736a424f2859c28fd1bf6a2a03a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRafael?= <“francisco.lezama@encora.com”> Date: Thu, 9 Jan 2025 16:44:20 -0600 Subject: [PATCH 2/4] Modified the method asHuman() to add a better format to show the info, and modified the tests to this new format --- message/message-web/pom.xml | 10 +- .../test/flow/msg/web/WebSequence.java | 176 ++++++++++-------- .../test/flow/msg/web/WebSequenceTest.java | 99 ++++++---- 3 files changed, 169 insertions(+), 116 deletions(-) diff --git a/message/message-web/pom.xml b/message/message-web/pom.xml index 12f2be6673..ec24a5d0ac 100644 --- a/message/message-web/pom.xml +++ b/message/message-web/pom.xml @@ -55,7 +55,15 @@ 92 - + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + diff --git a/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java b/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java index d2c304ddb0..e0262e0350 100644 --- a/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java +++ b/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java @@ -43,8 +43,8 @@ public class WebSequence extends AbstractMessage { private static final ObjectMapper JSON = new ObjectMapper(); private final WebSequence parent; - - private final SortedMap>> operations = new TreeMap<>(); + private final SortedMap>> operations = new TreeMap<>(); private Map results; @@ -55,27 +55,28 @@ public WebSequence() { parent = null; } - private WebSequence(WebSequence parent) { + private WebSequence( WebSequence parent ) { this.parent = parent; } @Override public WebSequence child() { - return copyMasksTo(new WebSequence(self())); + return copyMasksTo( new WebSequence( self() ) ); } @Override - public WebSequence peer(byte[] bytes) { - WebSequence peer = copyMasksTo(new WebSequence(parent)); - peer.operations.putAll(operations); + public WebSequence peer( byte[] bytes ) { + WebSequence peer = copyMasksTo( new WebSequence( parent ) ); + peer.operations.putAll( operations ); try { - ((Map) JSON.readValue(bytes, Map.class)) - .forEach(peer::set); - } catch (IOException ioe) { - throw new UncheckedIOException(String.format( + ((Map) JSON.readValue( bytes, Map.class )) + .forEach( peer::set ); + } + catch( IOException ioe ) { + throw new UncheckedIOException( String.format( "Failed to parse '%s' (%s)", - new String(bytes, UTF_8), Arrays.toString(bytes)), - ioe); + new String( bytes, UTF_8 ), Arrays.toString( bytes ) ), + ioe ); } return peer; } @@ -83,9 +84,10 @@ public WebSequence peer(byte[] bytes) { @Override public byte[] content() { try { - return JSON.writeValueAsBytes(parameters()); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); + return JSON.writeValueAsBytes( parameters() ); + } + catch( IOException ioe ) { + throw new UncheckedIOException( ioe ); } } @@ -95,50 +97,68 @@ protected String asHuman() { // use 'parameters()'. Map params = results != null ? results : parameters(); - // Find the maximum length of the parameter names. This is used for formatting. - int nameWidth = params.keySet().stream() - .mapToInt(String::length) - .max().orElse(1); + // Find the maximum length of the parameter names, values, and operations. This + // is used for formatting. + int nameWidth = Math.max( params.keySet().stream() + .mapToInt( String::length ) + .max().orElse( 1 ), "Parameters".length() ); + int valueWidth = Math.max( params.values().stream() + .flatMap( value -> Stream.of( value.split( "\n" ) ) ) + .mapToInt( String::length ) + .max().orElse( 1 ), "Values".length() ); + int operationsWidth = Math.max( operations().keySet().stream() + .mapToInt( String::length ) + .max().orElse( 1 ), "Operations".length() ); // Define the format for name-value pairs and padding for multi-line values. - String nvpFmt = " │ %" + nameWidth + "s │ %s │"; - String padFmt = "\n │ %" + nameWidth + "s "; - String pad = String.format(padFmt, ""); + String nvpFmt = "│ %" + nameWidth + "s │ %" + valueWidth + "s │"; + String padFmt = "\n│ %" + nameWidth + "s │ %-" + valueWidth + "s │"; // Create the formatted string for operations. String operationsStr = operations().keySet().stream() - .map(o -> " │ " + o + " │") - .collect(Collectors.joining("\n")); + .map( o -> String.format( "│ %" + operationsWidth + "s │", o ) ) + .collect( Collectors.joining( "\n" ) ); // Create the formatted string for parameters. String paramsStr = params.entrySet().stream() - .map(e -> String.format(nvpFmt, - e.getKey(), - Stream.of(e.getValue().split("\n")) - .collect(Collectors.joining(pad)))) - .collect(Collectors.joining("\n")); - - // Create a borderline for the box drawing. - String border = "─".repeat(nameWidth + 4); - - // Return the final formatted string with box drawing characters. - return String.format("┌%s┐\n" - + "│ Operations │\n" - + "├%s┤\n" - + "%s\n" - + "└%s┘\n" - + "┌%s┐\n" - + "│ Parameters │ Values │\n" - + "├%s┤\n" - + "%s\n" - + "└%s┘", - border, border, operationsStr, border, - border, border, paramsStr, border); + .map( e -> { + String key = e.getKey(); + String value = e.getValue(); + String[] lines = value.split( "\n" ); + return String.format( nvpFmt, key, lines[0] ) + + Stream.of( lines ).skip( 1 ) + .map( line -> String.format( padFmt, "", line ) ) + .collect( Collectors.joining() ); + } ) + .collect( Collectors.joining( "\n" ) ); + + // Calculate the width for the box drawing based on the longest line in + // operations and parameters. + int maxOperationsWidth = Math.max( "│ Operations │".length(), + operationsStr.lines().mapToInt( String::length ).max().orElse( 0 ) ); + int maxParamsWidth = Math.max( "│ Parameters │ Values │".length(), + paramsStr.lines().mapToInt( String::length ).max().orElse( 0 ) ); + + String operationsBorder = "─".repeat( maxOperationsWidth - 2 ); + String parametersBorder = "─".repeat( maxParamsWidth - 2 ); + + // Conditionally include the top, middle, and bottom lines only when there is + // data. + String operationsBox = operationsStr.isEmpty() ? "│ Operations │\n" + : String.format( "┌%s┐\n│ %-" + (maxOperationsWidth - 4) + "s │\n├%s┤\n%s\n└%s┘\n", + operationsBorder, + "Operations", operationsBorder, operationsStr, operationsBorder ); + String parametersBox = paramsStr.isEmpty() ? "│ Parameters │ Values │" + : String.format( "┌%s┐\n│ %-" + (maxParamsWidth - 4) + "s │\n├%s┤\n%s\n└%s┘", + parametersBorder, + "Parameters │ Values", parametersBorder, paramsStr, parametersBorder ); + + return operationsBox + parametersBox; } @Override public Set fields() { - return new TreeSet<>(parameters().keySet()); + return new TreeSet<>( parameters().keySet() ); } /** @@ -150,36 +170,37 @@ public Set fields() { * operation * @return this */ - public WebSequence operation(String name, - BiConsumer> op) { - operations.put(name, op); + public WebSequence operation( String name, + BiConsumer> op ) { + operations.put( name, op ); return self(); } @Override - protected Object access(String field) { - return parameters().get(field); + protected Object access( String field ) { + return parameters().get( field ); } private SortedMap>> operations() { SortedMap>> op = new TreeMap<>(); - if (parent != null) { - op.putAll(parent.operations()); + if( parent != null ) { + op.putAll( parent.operations() ); } - op.putAll(operations); + op.putAll( operations ); return op; } private Map parameters() { Map p = new TreeMap<>(); - if (parent != null) { - p.putAll(parent.parameters()); + if( parent != null ) { + p.putAll( parent.parameters() ); } - for (Update update : updates) { - if (update.value() == DELETE) { - p.remove(update.field()); - } else { - p.put(update.field(), String.valueOf(update.value())); + for( Update update : updates ) { + if( update.value() == DELETE ) { + p.remove( update.field() ); + } + else { + p.put( update.field(), String.valueOf( update.value() ) ); } } return p; @@ -191,33 +212,36 @@ private Map parameters() { * @param driver the browser to drive * @return The state of the parameters map after all operations have completed */ - public byte[] process(WebDriver driver) { + public byte[] process( WebDriver driver ) { Map params = parameters(); - operations().forEach((name, op) -> { - if (op != null) { + operations().forEach( ( name, op ) -> { + if( op != null ) { try { - op.accept(driver, params); - } catch (Exception e) { + op.accept( driver, params ); + } + catch( Exception e ) { // our operation has failed! String url = "No URL"; String source = "No page source"; try { url = driver.getCurrentUrl(); source = driver.getPageSource(); - } catch (Exception f) { + } + catch( Exception f ) { source = f.getMessage(); } - throw new IllegalStateException(String.format( + throw new IllegalStateException( String.format( "Operation '%s' failed on page '%s'\n%s", - name, url, source), - e); + name, url, source ), + e ); } } - }); + } ); try { - return JSON.writeValueAsBytes(params); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); + return JSON.writeValueAsBytes( params ); + } + catch( IOException ioe ) { + throw new UncheckedIOException( ioe ); } } diff --git a/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java b/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java index 2069185446..d5e497ae1c 100644 --- a/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java +++ b/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java @@ -29,11 +29,9 @@ class WebSequenceTest { @Test void empty() { WebSequence ws = new WebSequence(); - Assertions.assertEquals( "" - + "Operations:\n" - + "\n" - + "Parameters:\n" - + "", + Assertions.assertEquals( + "│ Operations │\n" + + "│ Parameters │ Values │", ws.assertable() ); } @@ -46,14 +44,16 @@ void unprocessed() { WebSequence ws = new WebSequence() .set( "foo", "bar" ) .set( "multiline", "so\nmany\nlines" ); - Assertions.assertEquals( "" - + "Operations:\n" - + "\n" - + "Parameters:\n" - + " foo : bar\n" - + " multiline : so\n" - + " many\n" - + " lines", + Assertions.assertEquals( + "│ Operations │\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ foo │ bar │\n" + + "│ multiline │ so │\n" + + "│ │ many │\n" + + "│ │ lines │\n" + + "└─────────────────────┘", ws.assertable() ); } @@ -74,13 +74,19 @@ 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( + "┌──────────────┐\n" + + "│ Operations │\n" + + "├──────────────┤\n" + + "│ param update │\n" + + "└──────────────┘\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "│ c │ i │\n" + + "│ g │ h │\n" + + "└─────────────────────┘", results.assertable() ); } @@ -127,11 +133,18 @@ void peer() { WebSequence peer = ws.peer( ws.content() ); - Assertions.assertEquals( "" - + "Operations:\n" - + " op\n" - + "Parameters:\n" - + " a : b", peer.assertable() ); + Assertions.assertEquals( + "┌────────────┐\n" + + "│ Operations │\n" + + "├────────────┤\n" + + "│ op │\n" + + "└────────────┘\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "└─────────────────────┘", + peer.assertable() ); Assertions.assertEquals( "Operation has not been invoked!", ref.get() ); @@ -170,11 +183,13 @@ 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 │\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "└─────────────────────┘", peer.assertable( rng ) ); } @@ -207,15 +222,21 @@ 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( + "┌────────────┐\n" + + "│ Operations │\n" + + "├────────────┤\n" + + "│ first │\n" + + "│ second │\n" + + "│ third │\n" + + "└────────────┘\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "│ c │ d │\n" + + "│ e │ f │\n" + + "└─────────────────────┘", results.assertable() ); } From e44608ebf9cf5c70923a9b1385ce328098942f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CRafael?= <“francisco.lezama@encora.com”> Date: Thu, 9 Jan 2025 16:44:20 -0600 Subject: [PATCH 3/4] Modified the method asHuman() to add a better format to show the info, and modified the tests to this new format --- message/message-web/pom.xml | 10 +- .../test/flow/msg/web/WebSequence.java | 176 ++++++++++-------- .../test/flow/msg/web/WebSequenceTest.java | 99 ++++++---- 3 files changed, 169 insertions(+), 116 deletions(-) diff --git a/message/message-web/pom.xml b/message/message-web/pom.xml index 12f2be6673..ec24a5d0ac 100644 --- a/message/message-web/pom.xml +++ b/message/message-web/pom.xml @@ -55,7 +55,15 @@ 92 - + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + diff --git a/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java b/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java index d2c304ddb0..e0262e0350 100644 --- a/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java +++ b/message/message-web/src/main/java/com/mastercard/test/flow/msg/web/WebSequence.java @@ -43,8 +43,8 @@ public class WebSequence extends AbstractMessage { private static final ObjectMapper JSON = new ObjectMapper(); private final WebSequence parent; - - private final SortedMap>> operations = new TreeMap<>(); + private final SortedMap>> operations = new TreeMap<>(); private Map results; @@ -55,27 +55,28 @@ public WebSequence() { parent = null; } - private WebSequence(WebSequence parent) { + private WebSequence( WebSequence parent ) { this.parent = parent; } @Override public WebSequence child() { - return copyMasksTo(new WebSequence(self())); + return copyMasksTo( new WebSequence( self() ) ); } @Override - public WebSequence peer(byte[] bytes) { - WebSequence peer = copyMasksTo(new WebSequence(parent)); - peer.operations.putAll(operations); + public WebSequence peer( byte[] bytes ) { + WebSequence peer = copyMasksTo( new WebSequence( parent ) ); + peer.operations.putAll( operations ); try { - ((Map) JSON.readValue(bytes, Map.class)) - .forEach(peer::set); - } catch (IOException ioe) { - throw new UncheckedIOException(String.format( + ((Map) JSON.readValue( bytes, Map.class )) + .forEach( peer::set ); + } + catch( IOException ioe ) { + throw new UncheckedIOException( String.format( "Failed to parse '%s' (%s)", - new String(bytes, UTF_8), Arrays.toString(bytes)), - ioe); + new String( bytes, UTF_8 ), Arrays.toString( bytes ) ), + ioe ); } return peer; } @@ -83,9 +84,10 @@ public WebSequence peer(byte[] bytes) { @Override public byte[] content() { try { - return JSON.writeValueAsBytes(parameters()); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); + return JSON.writeValueAsBytes( parameters() ); + } + catch( IOException ioe ) { + throw new UncheckedIOException( ioe ); } } @@ -95,50 +97,68 @@ protected String asHuman() { // use 'parameters()'. Map params = results != null ? results : parameters(); - // Find the maximum length of the parameter names. This is used for formatting. - int nameWidth = params.keySet().stream() - .mapToInt(String::length) - .max().orElse(1); + // Find the maximum length of the parameter names, values, and operations. This + // is used for formatting. + int nameWidth = Math.max( params.keySet().stream() + .mapToInt( String::length ) + .max().orElse( 1 ), "Parameters".length() ); + int valueWidth = Math.max( params.values().stream() + .flatMap( value -> Stream.of( value.split( "\n" ) ) ) + .mapToInt( String::length ) + .max().orElse( 1 ), "Values".length() ); + int operationsWidth = Math.max( operations().keySet().stream() + .mapToInt( String::length ) + .max().orElse( 1 ), "Operations".length() ); // Define the format for name-value pairs and padding for multi-line values. - String nvpFmt = " │ %" + nameWidth + "s │ %s │"; - String padFmt = "\n │ %" + nameWidth + "s "; - String pad = String.format(padFmt, ""); + String nvpFmt = "│ %" + nameWidth + "s │ %" + valueWidth + "s │"; + String padFmt = "\n│ %" + nameWidth + "s │ %-" + valueWidth + "s │"; // Create the formatted string for operations. String operationsStr = operations().keySet().stream() - .map(o -> " │ " + o + " │") - .collect(Collectors.joining("\n")); + .map( o -> String.format( "│ %" + operationsWidth + "s │", o ) ) + .collect( Collectors.joining( "\n" ) ); // Create the formatted string for parameters. String paramsStr = params.entrySet().stream() - .map(e -> String.format(nvpFmt, - e.getKey(), - Stream.of(e.getValue().split("\n")) - .collect(Collectors.joining(pad)))) - .collect(Collectors.joining("\n")); - - // Create a borderline for the box drawing. - String border = "─".repeat(nameWidth + 4); - - // Return the final formatted string with box drawing characters. - return String.format("┌%s┐\n" - + "│ Operations │\n" - + "├%s┤\n" - + "%s\n" - + "└%s┘\n" - + "┌%s┐\n" - + "│ Parameters │ Values │\n" - + "├%s┤\n" - + "%s\n" - + "└%s┘", - border, border, operationsStr, border, - border, border, paramsStr, border); + .map( e -> { + String key = e.getKey(); + String value = e.getValue(); + String[] lines = value.split( "\n" ); + return String.format( nvpFmt, key, lines[0] ) + + Stream.of( lines ).skip( 1 ) + .map( line -> String.format( padFmt, "", line ) ) + .collect( Collectors.joining() ); + } ) + .collect( Collectors.joining( "\n" ) ); + + // Calculate the width for the box drawing based on the longest line in + // operations and parameters. + int maxOperationsWidth = Math.max( "│ Operations │".length(), + operationsStr.lines().mapToInt( String::length ).max().orElse( 0 ) ); + int maxParamsWidth = Math.max( "│ Parameters │ Values │".length(), + paramsStr.lines().mapToInt( String::length ).max().orElse( 0 ) ); + + String operationsBorder = "─".repeat( maxOperationsWidth - 2 ); + String parametersBorder = "─".repeat( maxParamsWidth - 2 ); + + // Conditionally include the top, middle, and bottom lines only when there is + // data. + String operationsBox = operationsStr.isEmpty() ? "│ Operations │\n" + : String.format( "┌%s┐\n│ %-" + (maxOperationsWidth - 4) + "s │\n├%s┤\n%s\n└%s┘\n", + operationsBorder, + "Operations", operationsBorder, operationsStr, operationsBorder ); + String parametersBox = paramsStr.isEmpty() ? "│ Parameters │ Values │" + : String.format( "┌%s┐\n│ %-" + (maxParamsWidth - 4) + "s │\n├%s┤\n%s\n└%s┘", + parametersBorder, + "Parameters │ Values", parametersBorder, paramsStr, parametersBorder ); + + return operationsBox + parametersBox; } @Override public Set fields() { - return new TreeSet<>(parameters().keySet()); + return new TreeSet<>( parameters().keySet() ); } /** @@ -150,36 +170,37 @@ public Set fields() { * operation * @return this */ - public WebSequence operation(String name, - BiConsumer> op) { - operations.put(name, op); + public WebSequence operation( String name, + BiConsumer> op ) { + operations.put( name, op ); return self(); } @Override - protected Object access(String field) { - return parameters().get(field); + protected Object access( String field ) { + return parameters().get( field ); } private SortedMap>> operations() { SortedMap>> op = new TreeMap<>(); - if (parent != null) { - op.putAll(parent.operations()); + if( parent != null ) { + op.putAll( parent.operations() ); } - op.putAll(operations); + op.putAll( operations ); return op; } private Map parameters() { Map p = new TreeMap<>(); - if (parent != null) { - p.putAll(parent.parameters()); + if( parent != null ) { + p.putAll( parent.parameters() ); } - for (Update update : updates) { - if (update.value() == DELETE) { - p.remove(update.field()); - } else { - p.put(update.field(), String.valueOf(update.value())); + for( Update update : updates ) { + if( update.value() == DELETE ) { + p.remove( update.field() ); + } + else { + p.put( update.field(), String.valueOf( update.value() ) ); } } return p; @@ -191,33 +212,36 @@ private Map parameters() { * @param driver the browser to drive * @return The state of the parameters map after all operations have completed */ - public byte[] process(WebDriver driver) { + public byte[] process( WebDriver driver ) { Map params = parameters(); - operations().forEach((name, op) -> { - if (op != null) { + operations().forEach( ( name, op ) -> { + if( op != null ) { try { - op.accept(driver, params); - } catch (Exception e) { + op.accept( driver, params ); + } + catch( Exception e ) { // our operation has failed! String url = "No URL"; String source = "No page source"; try { url = driver.getCurrentUrl(); source = driver.getPageSource(); - } catch (Exception f) { + } + catch( Exception f ) { source = f.getMessage(); } - throw new IllegalStateException(String.format( + throw new IllegalStateException( String.format( "Operation '%s' failed on page '%s'\n%s", - name, url, source), - e); + name, url, source ), + e ); } } - }); + } ); try { - return JSON.writeValueAsBytes(params); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); + return JSON.writeValueAsBytes( params ); + } + catch( IOException ioe ) { + throw new UncheckedIOException( ioe ); } } diff --git a/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java b/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java index 2069185446..d5e497ae1c 100644 --- a/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java +++ b/message/message-web/src/test/java/com/mastercard/test/flow/msg/web/WebSequenceTest.java @@ -29,11 +29,9 @@ class WebSequenceTest { @Test void empty() { WebSequence ws = new WebSequence(); - Assertions.assertEquals( "" - + "Operations:\n" - + "\n" - + "Parameters:\n" - + "", + Assertions.assertEquals( + "│ Operations │\n" + + "│ Parameters │ Values │", ws.assertable() ); } @@ -46,14 +44,16 @@ void unprocessed() { WebSequence ws = new WebSequence() .set( "foo", "bar" ) .set( "multiline", "so\nmany\nlines" ); - Assertions.assertEquals( "" - + "Operations:\n" - + "\n" - + "Parameters:\n" - + " foo : bar\n" - + " multiline : so\n" - + " many\n" - + " lines", + Assertions.assertEquals( + "│ Operations │\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ foo │ bar │\n" + + "│ multiline │ so │\n" + + "│ │ many │\n" + + "│ │ lines │\n" + + "└─────────────────────┘", ws.assertable() ); } @@ -74,13 +74,19 @@ 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( + "┌──────────────┐\n" + + "│ Operations │\n" + + "├──────────────┤\n" + + "│ param update │\n" + + "└──────────────┘\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "│ c │ i │\n" + + "│ g │ h │\n" + + "└─────────────────────┘", results.assertable() ); } @@ -127,11 +133,18 @@ void peer() { WebSequence peer = ws.peer( ws.content() ); - Assertions.assertEquals( "" - + "Operations:\n" - + " op\n" - + "Parameters:\n" - + " a : b", peer.assertable() ); + Assertions.assertEquals( + "┌────────────┐\n" + + "│ Operations │\n" + + "├────────────┤\n" + + "│ op │\n" + + "└────────────┘\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "└─────────────────────┘", + peer.assertable() ); Assertions.assertEquals( "Operation has not been invoked!", ref.get() ); @@ -170,11 +183,13 @@ 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 │\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "└─────────────────────┘", peer.assertable( rng ) ); } @@ -207,15 +222,21 @@ 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( + "┌────────────┐\n" + + "│ Operations │\n" + + "├────────────┤\n" + + "│ first │\n" + + "│ second │\n" + + "│ third │\n" + + "└────────────┘\n" + + "┌─────────────────────┐\n" + + "│ Parameters │ Values │\n" + + "├─────────────────────┤\n" + + "│ a │ b │\n" + + "│ c │ d │\n" + + "│ e │ f │\n" + + "└─────────────────────┘", results.assertable() ); } From a6e1913e37fb52a180c20200c59ef1fbd71943e7 Mon Sep 17 00:00:00 2001 From: lezhdz98 Date: Fri, 10 Jan 2025 11:19:57 -0600 Subject: [PATCH 4/4] reverting pom.xml --- message/message-web/pom.xml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/message/message-web/pom.xml b/message/message-web/pom.xml index ec24a5d0ac..12f2be6673 100644 --- a/message/message-web/pom.xml +++ b/message/message-web/pom.xml @@ -55,15 +55,7 @@ 92 - - org.apache.maven.plugins - maven-compiler-plugin - - 11 - 11 - - - +