Skip to content

Commit

Permalink
[Core] Add name to embedding
Browse files Browse the repository at this point in the history
Add name to EmbedEvent. Allow the JSONFormatter and HTMLFormatter to display the
name of the embedding in reports.
  • Loading branch information
Konrad Maciaszczyk authored and mpkorstanje committed Jul 16, 2019
1 parent fbd394c commit 06bbe1a
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 24 deletions.
9 changes: 9 additions & 0 deletions core/src/main/java/cucumber/api/Scenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ public interface Scenario {
*/
void embed(byte[] data, String mimeType);

/**
* Like {@link Scenario#embed(byte[], String)}, but with name for the embedding.
*
* @param data what to embed, for example an image.
* @param mimeType what is the data?
* @param name embedding name
*/
void embed(byte[] data, String mimeType, String name);

/**
* Outputs some text into the report.
*
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/cucumber/api/event/EmbedEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
public final class EmbedEvent extends TestCaseEvent {
public final byte[] data;
public final String mimeType;
public final String name;

@Deprecated
public EmbedEvent(Long timeStamp, TestCase testCase, byte[] data, String mimeType) {
Expand All @@ -15,6 +16,14 @@ public EmbedEvent(Long timeStamp, long timeStampMillis, TestCase testCase, byte[
super(timeStamp, timeStampMillis, testCase);
this.data = data;
this.mimeType = mimeType;
this.name = null;
}

public EmbedEvent(Long timeStamp, long timeStampMillis, TestCase testCase, byte[] data, String mimeType, String name) {
super(timeStamp, timeStampMillis, testCase);
this.data = data;
this.mimeType = mimeType;
this.name = name;
}

}
13 changes: 7 additions & 6 deletions core/src/main/java/cucumber/runner/Scenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,17 @@ public boolean isFailed() {

@Override
public void embed(byte[] data, String mimeType) {
if (bus != null) {
bus.send(new EmbedEvent(bus.getTime(), bus.getTimeMillis(), testCase, data, mimeType));
}
bus.send(new EmbedEvent(bus.getTime(), bus.getTimeMillis(), testCase, data, mimeType));
}

@Override
public void embed(byte[] data, String mimeType, String name) {
bus.send(new EmbedEvent(bus.getTime(), bus.getTimeMillis(), testCase, data, mimeType, name));
}

@Override
public void write(String text) {
if (bus != null) {
bus.send(new WriteEvent(bus.getTime(), bus.getTimeMillis(), testCase, text));
}
bus.send(new WriteEvent(bus.getTime(), bus.getTimeMillis(), testCase, text));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,14 @@ private void handleEmbed(EmbedEvent event) {
String mimeType = event.mimeType;
if(mimeType.startsWith("text/")) {
// just pass straight to the formatter to output in the html
jsFunctionCall("embedding", mimeType, new String(event.data));
jsFunctionCall("embedding", mimeType, new String(event.data), event.name);
} else {
// Creating a file instead of using data urls to not clutter the js file
String extension = MIME_TYPES_EXTENSIONS.get(mimeType);
if (extension != null) {
StringBuilder fileName = new StringBuilder("embedded").append(embeddedIndex++).append(".").append(extension);
writeBytesToURL(event.data, toUrl(fileName.toString()));
jsFunctionCall("embedding", mimeType, fileName);
jsFunctionCall("embedding", mimeType, fileName, event.name);
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions core/src/main/java/cucumber/runtime/formatter/JSONFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ private void handleWrite(WriteEvent event) {
}

private void handleEmbed(EmbedEvent event) {
addEmbeddingToHookMap(event.data, event.mimeType);
addEmbeddingToHookMap(event.data, event.mimeType, event.name);
}

private void handleTestStepFinished(TestStepFinished event) {
Expand Down Expand Up @@ -338,18 +338,21 @@ private void addOutputToHookMap(String text) {
((List<String>)currentStepOrHookMap.get("output")).add(text);
}

private void addEmbeddingToHookMap(byte[] data, String mimeType) {
private void addEmbeddingToHookMap(byte[] data, String mimeType, String name) {
if (!currentStepOrHookMap.containsKey("embeddings")) {
currentStepOrHookMap.put("embeddings", new ArrayList<Map<String, Object>>());
}
Map<String, Object> embedMap = createEmbeddingMap(data, mimeType);
Map<String, Object> embedMap = createEmbeddingMap(data, mimeType, name);
((List<Map<String, Object>>)currentStepOrHookMap.get("embeddings")).add(embedMap);
}

private Map<String, Object> createEmbeddingMap(byte[] data, String mimeType) {
private Map<String, Object> createEmbeddingMap(byte[] data, String mimeType, String name) {
Map<String, Object> embedMap = new HashMap<String, Object>();
embedMap.put("mime_type", mimeType);
embedMap.put("data", Base64.encodeBytes(data));
if (name != null) {
embedMap.put("name", name);
}
return embedMap;
}

Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/io/cucumber/core/api/Scenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public interface Scenario {
*/
void embed(byte[] data, String mimeType);

/**
* Like {@link Scenario#embed(byte[], String)}, but with name for the embedding.
*
* @param data what to embed, for example an image.
* @param mimeType what is the data?
* @param name embedding name
*/
void embed(byte[] data, String mimeType, String name);

/**
* Outputs some text into the report.
*
Expand Down
14 changes: 10 additions & 4 deletions core/src/main/resources/io/cucumber/formatter/html/formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,27 @@ CucumberHTML.DOMFormatter = function(rootNode) {
}
};

this.embedding = function(mimeType, data) {
this.embedding = function(mimeType, data, name) {
var nameHtml;
if (!name) {
nameHtml = "";
} else {
nameHtml = "<h4>" + name + "</h4>";
}
if (currentStepIndex == 1) {
this.dummyStep();
}
if (mimeType.match(/^image\//))
{
currentStep.append('<img src="' + data + '">');
currentStep.append(nameHtml + '<img src="' + data + '">');
}
else if (mimeType.match(/^video\//))
{
currentStep.append('<video src="' + data + '" type="' + mimeType + '" autobuffer controls>Your browser doesn\'t support video.</video>');
currentStep.append(nameHtml + '<video src="' + data + '" type="' + mimeType + '" autobuffer controls>Your browser doesn\'t support video.</video>');
}
else if (mimeType.match(/^text\//))
{
this.write(data);
this.write(nameHtml + data);
}
};

Expand Down
11 changes: 9 additions & 2 deletions core/src/test/java/cucumber/runner/TestHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -465,17 +465,24 @@ public Object answer(InvocationOnMock invocation) {
}

public static Answer<Object> createEmbedHookAction(final byte[] data, final String mimeType) {
return createEmbedHookAction(data, mimeType, null);
}

public static Answer<Object> createEmbedHookAction(final byte[] data, final String mimeType, final String name) {
return new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) {
Scenario scenario = (Scenario) invocation.getArguments()[0];
scenario.embed(data, mimeType);
if (name != null) {
scenario.embed(data, mimeType, name);
} else {
scenario.embed(data, mimeType);
}
return null;
}
};
}


private static AssertionFailedError mockAssertionFailedError() {
AssertionFailedError error = mock(AssertionFailedError.class);
Answer<Object> printStackTraceHandler = new Answer<Object>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ public void writes_valid_report_js() throws Throwable {
"formatter.result({\n" +
" \"status\": \"passed\"\n" +
"});\n",
"formatter.embedding(\"image/png\", \"embedded0.png\");\n",
"formatter.embedding(\"image/png\", \"embedded0.png\", \"Fake image\");\n",
"formatter.after({\n" +
" \"status\": \"passed\"\n" +
"});\n",
"formatter.embedding(\"text/plain\", \"dodgy stack trace here\");\n",
"formatter.embedding(\"text/plain\", \"dodgy stack trace here\", null);\n",
"formatter.after({\n" +
" \"status\": \"passed\"\n" +
"});\n"),
Expand All @@ -110,8 +110,8 @@ public void includes_uri() throws Throwable {
public void included_embedding() throws Throwable {
writeReport();
String reportJs = FixJava.readReader(new InputStreamReader(new URL(outputDir, "report.js").openStream(), "UTF-8"));
assertContains("formatter.embedding(\"image/png\", \"embedded0.png\");", reportJs);
assertContains("formatter.embedding(\"text/plain\", \"dodgy stack trace here\");", reportJs);
assertContains("formatter.embedding(\"image/png\", \"embedded0.png\", \"Fake image\");", reportJs);
assertContains("formatter.embedding(\"text/plain\", \"dodgy stack trace here\", null);", reportJs);
}

@Test
Expand Down Expand Up @@ -650,7 +650,7 @@ public void should_handle_text_embeddings_from_before_hooks() throws Throwable {
" \"keyword\": \"Scenario\",\n" +
" \"name\": \"scenario name\"\n" +
"});\n", "" +
"formatter.embedding(\"text/ascii\", \"embedded from hook\");\n", "" +
"formatter.embedding(\"text/ascii\", \"embedded from hook\", null);\n", "" +
"formatter.before({\n" +
" \"status\": \"passed\"\n" +
"});\n", "" +
Expand Down Expand Up @@ -737,7 +737,7 @@ private void runFeaturesWithFormatter(URL outputDir) throws Throwable {
stepsToLocation.put("first step", "path/step_definitions.java:3");
hooks.add(TestHelper.hookEntry("after", result("passed")));
hooks.add(TestHelper.hookEntry("after", result("passed")));
hookActions.add(createEmbedHookAction("fakedata".getBytes("US-ASCII"), "image/png"));
hookActions.add(createEmbedHookAction("fakedata".getBytes("US-ASCII"), "image/png", "Fake image"));
hookActions.add(createEmbedHookAction("dodgy stack trace here".getBytes("US-ASCII"), "text/plain"));
stepDuration = 1L;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,81 @@ public void should_handle_embed_from_a_hook() {
assertThat(formatterOutput, sameJSONAs(expected));
}

@Test
public void should_handle_embed_with_name_from_a_hook() {
CucumberFeature feature = TestHelper.feature("path/test.feature", "" +
"Feature: Banana party\n" +
"\n" +
" Scenario: Monkey eats bananas\n" +
" Given there are bananas\n");
features.add(feature);
stepsToResult.put("there are bananas", result("passed"));
stepsToLocation.put("there are bananas", "StepDefs.there_are_bananas()");
hooks.add(TestHelper.hookEntry("before", result("passed")));
hookLocations.add("Hooks.before_hook_1()");
hookActions.add(createEmbedHookAction(new byte[]{1, 2, 3}, "mime-type;base64", "someEmbedding"));
stepDurationMillis = 1L;

String formatterOutput = runFeaturesWithFormatter();

String expected = "" +
"[\n" +
" {\n" +
" \"id\": \"banana-party\",\n" +
" \"uri\": \"file:path/test.feature\",\n" +
" \"keyword\": \"Feature\",\n" +
" \"name\": \"Banana party\",\n" +
" \"line\": 1,\n" +
" \"description\": \"\",\n" +
" \"elements\": [\n" +
" {\n" +
" \"id\": \"banana-party;monkey-eats-bananas\",\n" +
" \"keyword\": \"Scenario\",\n" +
" \"start_timestamp\": \"1970-01-01T00:00:00.000Z\",\n" +
" \"name\": \"Monkey eats bananas\",\n" +
" \"line\": 3,\n" +
" \"description\": \"\",\n" +
" \"type\": \"scenario\",\n" +
" \"before\": [\n" +
" {\n" +
" \"match\": {\n" +
" \"location\": \"Hooks.before_hook_1()\"\n" +
" },\n" +
" \"embeddings\": [\n" +
" {\n" +
" \"mime_type\": \"mime-type;base64\",\n" +
" \"data\": \"AQID\",\n" +
" \"name\": \"someEmbedding\"\n" +
" }\n" +
" ],\n" +
" \"result\": {\n" +
" \"status\": \"passed\",\n" +
" \"duration\": 1000000\n" +
" }\n" +
" }\n" +
" ],\n" +
" \"steps\": [\n" +
" {\n" +
" \"keyword\": \"Given \",\n" +
" \"name\": \"there are bananas\",\n" +
" \"line\": 4,\n" +
" \"match\": {\n" +
" \"location\": \"StepDefs.there_are_bananas()\"\n" +
" },\n" +
" \"result\": {\n" +
" \"status\": \"passed\",\n" +
" \"duration\": 1000000\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
" ],\n" +
" \"tags\": []\n" +
" }\n" +
"]";
assertThat(formatterOutput, sameJSONAs(expected));
}

@Test
public void should_format_scenario_with_a_step_with_a_doc_string() {
CucumberFeature feature = TestHelper.feature("path/test.feature", "" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ public void embed(byte[] data, String mimeType) {
scenario.embed(data, mimeType);
}

@Override
public void embed(byte[] data, String mimeType, String name) {
scenario.embed(data, mimeType, name);
}

@Override
public void write(String text) {
scenario.write(text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ public void embed(byte[] data, String mimeType) {
scenario.embed(data, mimeType);
}

@Override
public void embed(byte[] data, String mimeType, String name) {
scenario.embed(data, mimeType, name);
}

@Override
public void write(String text) {
scenario.write(text);
Expand Down

0 comments on commit 06bbe1a

Please sign in to comment.