Skip to content

Commit

Permalink
Add new methods for attachments, hooks, meta (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidjgoss authored Jan 14, 2025
1 parent a27b1d0 commit 72bed7f
Show file tree
Hide file tree
Showing 11 changed files with 927 additions and 4 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- New method `findAttachmentsBy(TestStepFinished)` ([#67](https://github.com/cucumber/query/pull/67))
- New method `findHookBy(TestStep)` ([#67](https://github.com/cucumber/query/pull/67))
- New method `findMeta()` ([#67](https://github.com/cucumber/query/pull/67))

### Fixed
- [JavaScript] Attachments are not presumed to have a related test step ([#67](https://github.com/cucumber/query/pull/67))

## [13.0.3] - 2024-12-22
### Fixed
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ status of a step, a scenario or an entire file.
| `findAllTestCaseStarted(): List<TestCaseStarted>` | | || ||
| `findAllTestCaseStartedGroupedByFeature(): Map<Optional<Feature>, List<TestCaseStarted>>` | | || ||
| `findAllTestSteps(): List<TestStep>` | | || ||
| `findAttachmentsBy(TestStepFinished): List<Attachment>` | | || ||
| `findFeatureBy(TestCaseStarted): Optional<Feature>` | | || ||
| `findHookBy(TestStep): Optional<Hook>` | | || ||
| `findMeta(): Optional<Meta>` | | || ||
| `findMostSevereTestStepResulBy(TestCaseStarted): Optional<TestStepResult>` | | || ||
| `findNameOf(Pickle, NamingStrategy): String` | | || ||
| `findPickleBy(TestCaseStarted): Optional<Pickle>` | | || ||
Expand Down
41 changes: 41 additions & 0 deletions java/src/main/java/io/cucumber/query/Query.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package io.cucumber.query;

import io.cucumber.messages.Convertor;
import io.cucumber.messages.types.Attachment;
import io.cucumber.messages.types.Envelope;
import io.cucumber.messages.types.Examples;
import io.cucumber.messages.types.Feature;
import io.cucumber.messages.types.GherkinDocument;
import io.cucumber.messages.types.Hook;
import io.cucumber.messages.types.Meta;
import io.cucumber.messages.types.Pickle;
import io.cucumber.messages.types.PickleStep;
import io.cucumber.messages.types.Rule;
Expand Down Expand Up @@ -67,7 +70,10 @@ public final class Query {
private final Map<String, Step> stepById = new ConcurrentHashMap<>();
private final Map<String, TestStep> testStepById = new ConcurrentHashMap<>();
private final Map<String, PickleStep> pickleStepById = new ConcurrentHashMap<>();
private final Map<String, Hook> hookById = new ConcurrentHashMap<>();
private final Map<String, List<Attachment>> attachmentsByTestCaseStartedId = new ConcurrentHashMap<>();
private final Map<Object, Lineage> lineageById = new ConcurrentHashMap<>();
private Meta meta;
private TestRunStarted testRunStarted;
private TestRunFinished testRunFinished;

Expand Down Expand Up @@ -135,10 +141,29 @@ public List<TestStep> findAllTestSteps() {
.collect(toList());
}

public List<Attachment> findAttachmentsBy(TestStepFinished testStepFinished) {
requireNonNull(testStepFinished);
return attachmentsByTestCaseStartedId.getOrDefault(testStepFinished.getTestCaseStartedId(), emptyList()).stream()
.filter(attachment -> attachment.getTestStepId()
.map(testStepId -> testStepFinished.getTestStepId().equals(testStepId))
.orElse(false))
.collect(toList());
}

public Optional<Feature> findFeatureBy(TestCaseStarted testCaseStarted) {
return findLineageBy(testCaseStarted).flatMap(Lineage::feature);
}

public Optional<Hook> findHookBy(TestStep testStep) {
requireNonNull(testStep);
return testStep.getHookId()
.map(hookById::get);
}

public Optional<Meta> findMeta() {
return ofNullable(meta);
}

public Optional<TestStepResult> findMostSevereTestStepResultBy(TestCaseStarted testCaseStarted) {
requireNonNull(testCaseStarted);
return findTestStepsFinishedBy(testCaseStarted)
Expand Down Expand Up @@ -330,6 +355,7 @@ public List<Entry<TestStepFinished, TestStep>> findTestStepFinishedAndTestStepBy
}

public void update(Envelope envelope) {
envelope.getMeta().ifPresent(this::updateMeta);
envelope.getTestRunStarted().ifPresent(this::updateTestRunStarted);
envelope.getTestRunFinished().ifPresent(this::updateTestRunFinished);
envelope.getTestCaseStarted().ifPresent(this::updateTestCaseStarted);
Expand All @@ -338,6 +364,8 @@ public void update(Envelope envelope) {
envelope.getGherkinDocument().ifPresent(this::updateGherkinDocument);
envelope.getPickle().ifPresent(this::updatePickle);
envelope.getTestCase().ifPresent(this::updateTestCase);
envelope.getHook().ifPresent(this::updateHook);
envelope.getAttachment().ifPresent(this::updateAttachment);
}

private Optional<Lineage> findLineageBy(GherkinDocument element) {
Expand Down Expand Up @@ -382,6 +410,15 @@ private Optional<Lineage> findLineageBy(TestCaseStarted testCaseStarted) {
.flatMap(this::findLineageBy);
}

private void updateAttachment(Attachment attachment) {
attachment.getTestCaseStartedId()
.ifPresent(testCaseStartedId -> this.attachmentsByTestCaseStartedId.compute(testCaseStartedId, updateList(attachment)));
}

private void updateHook(Hook hook) {
this.hookById.put(hook.getId(), hook);
}

private void updateTestCaseStarted(TestCaseStarted testCaseStarted) {
this.testCaseStarted.add(testCaseStarted);
}
Expand Down Expand Up @@ -437,6 +474,10 @@ private void updateSteps(List<Step> steps) {
steps.forEach(step -> stepById.put(step.getId(), step));
}

private void updateMeta(Meta event) {
this.meta = event;
}

private <K, E> BiFunction<K, List<E>, List<E>> updateList(E element) {
return (key, existing) -> {
if (existing != null) {
Expand Down
24 changes: 24 additions & 0 deletions java/src/test/java/io/cucumber/query/QueryAcceptanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.cucumber.messages.NdjsonToMessageIterable;
import io.cucumber.messages.types.Envelope;
import io.cucumber.messages.types.Feature;
import io.cucumber.messages.types.Hook;
import io.cucumber.messages.types.Pickle;
import io.cucumber.messages.types.PickleStep;
import io.cucumber.messages.types.Step;
Expand All @@ -31,6 +32,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

import static com.fasterxml.jackson.core.util.DefaultIndenter.SYSTEM_LINEFEED_INSTANCE;
Expand All @@ -50,7 +52,9 @@ public class QueryAcceptanceTest {
static List<TestCase> acceptance() {

return Stream.of(
Paths.get("../testdata/attachments.feature.ndjson"),
Paths.get("../testdata/empty.feature.ndjson"),
Paths.get("../testdata/hooks.feature.ndjson"),
Paths.get("../testdata/minimal.feature.ndjson"),
Paths.get("../testdata/rules.feature.ndjson"),
Paths.get("../testdata/examples-tables.feature.ndjson")
Expand Down Expand Up @@ -111,10 +115,29 @@ private static Map<String, Object> createQueryResults(Query query) {
.map(entry -> Arrays.asList(entry.getKey().map(Feature::getName), entry.getValue().stream()
.map(TestCaseStarted::getId)
.collect(toList()))));
results.put("findAttachmentsBy", query.findAllTestCaseStarted().stream()
.map(query::findTestStepFinishedAndTestStepBy)
.flatMap(Collection::stream)
.map(Map.Entry::getKey)
.map(query::findAttachmentsBy)
.flatMap(Collection::stream)
.map(attachment -> Arrays.asList(
attachment.getTestStepId(),
attachment.getTestCaseStartedId(),
attachment.getMediaType(),
attachment.getContentEncoding()
))
.collect(toList()));
results.put("findFeatureBy", query.findAllTestCaseStarted().stream()
.map(query::findFeatureBy)
.map(feature -> feature.map(Feature::getName))
.collect(toList()));
results.put("findHookBy", query.findAllTestSteps().stream()
.map(query::findHookBy)
.map(hook -> hook.map(Hook::getId))
.filter(Optional::isPresent)
.collect(toList()));
results.put("findMeta", query.findMeta().map(meta -> meta.getImplementation().getName()));
results.put("findMostSevereTestStepResultBy", query.findAllTestCaseStarted().stream()
.map(query::findMostSevereTestStepResultBy)
.map(testStepResult -> testStepResult.map(TestStepResult::getStatus))
Expand Down Expand Up @@ -146,6 +169,7 @@ private static Map<String, Object> createQueryResults(Query query) {
results.put("findPickleStepBy", query.findAllTestSteps().stream()
.map(query::findPickleStepBy)
.map(pickleStep -> pickleStep.map(PickleStep::getText))
.filter(Optional::isPresent)
.collect(toList()));
results.put("findStepBy", query.findAllPickleSteps().stream()
.map(query::findStepBy)
Expand Down
42 changes: 39 additions & 3 deletions javascript/src/Query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import * as messages from '@cucumber/messages'
import {
Attachment,
Duration,
Feature,
getWorstTestStepResult,
GherkinDocument,
Hook,
Meta,
Pickle,
PickleStep,
Rule,
Expand All @@ -18,7 +21,7 @@ import {
TestStepFinished,
TestStepResult,
TestStepResultStatus,
TimeConversion
TimeConversion,
} from '@cucumber/messages'
import {ArrayMultimap} from '@teppeis/multimaps'
import {Lineage, NamingStrategy} from "./Lineage";
Expand All @@ -45,6 +48,7 @@ export default class Query {
readonly messages.StepMatchArgumentsList[]
>()

private meta: Meta
private testRunStarted: TestRunStarted
private testRunFinished: TestRunFinished
private readonly testCaseStarted: Array<TestCaseStarted> = []
Expand All @@ -57,8 +61,13 @@ export default class Query {
private readonly testCaseFinishedByTestCaseStartedId: Map<string, TestCaseFinished> = new Map()
private readonly testStepFinishedByTestCaseStartedId: ArrayMultimap<string, TestStepFinished> =
new ArrayMultimap()
private readonly attachmentsByTestCaseStartedId: ArrayMultimap<string, Attachment> =
new ArrayMultimap()

public update(envelope: messages.Envelope) {
if (envelope.meta) {
this.meta = envelope.meta
}
if (envelope.gherkinDocument) {
this.updateGherkinDocument(envelope.gherkinDocument)
}
Expand All @@ -78,7 +87,7 @@ export default class Query {
this.updateTestCaseStarted(envelope.testCaseStarted)
}
if (envelope.attachment) {
this.attachmentsByTestStepId.put(envelope.attachment.testStepId, envelope.attachment)
this.updateAttachment(envelope.attachment)
}
if (envelope.testStepFinished) {
this.updateTestStepFinished(envelope.testStepFinished)
Expand Down Expand Up @@ -201,6 +210,15 @@ export default class Query {
}
}

private updateAttachment(attachment: Attachment) {
if (attachment.testStepId) {
this.attachmentsByTestStepId.put(attachment.testStepId, attachment)
}
if (attachment.testCaseStartedId) {
this.attachmentsByTestCaseStartedId.put(attachment.testCaseStartedId, attachment)
}
}

private updateTestStepFinished(testStepFinished: TestStepFinished) {
this.testStepFinishedByTestCaseStartedId.put(
testStepFinished.testCaseStartedId,
Expand Down Expand Up @@ -420,10 +438,26 @@ export default class Query {
return testSteps.sort(comparatorById)
}

public findAttachmentsBy(testStepFinished: TestStepFinished): ReadonlyArray<Attachment> {
return this.attachmentsByTestCaseStartedId.get(testStepFinished.testCaseStartedId)
.filter(attachment => attachment.testStepId === testStepFinished.testStepId)
}

public findFeatureBy(testCaseStarted: TestCaseStarted): Feature | undefined {
return this.findLineageBy(testCaseStarted)?.feature
}

public findHookBy(testStep: TestStep): Hook | undefined {
if (!testStep.hookId){
return undefined
}
return this.hooksById.get(testStep.hookId)
}

public findMeta(): Meta | undefined {
return this.meta;
}

public findMostSevereTestStepResultBy(testCaseStarted: TestCaseStarted): TestStepResult | undefined {
return this.findTestStepFinishedAndTestStepBy(testCaseStarted)
.map(([testStepFinished]) => testStepFinished.testStepResult)
Expand All @@ -443,7 +477,9 @@ export default class Query {
}

public findPickleStepBy(testStep: TestStep): PickleStep | undefined {
assert.ok(testStep.pickleStepId, 'Expected TestStep to have a pickleStepId')
if (!testStep.pickleStepId){
return undefined
}
return this.pickleStepById.get(testStep.pickleStepId)
}

Expand Down
23 changes: 22 additions & 1 deletion javascript/src/acceptance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,24 @@ describe('Acceptance Tests', async () => {
findAllTestSteps: query.findAllTestSteps().length,
findAllTestCaseStartedGroupedByFeature: [...query.findAllTestCaseStartedGroupedByFeature().entries()]
.map(([feature, testCaseStarteds]) => [feature.name, testCaseStarteds.map(testCaseStarted => testCaseStarted.id)]),
findAttachmentsBy: query.findAllTestCaseStarted()
.map(testCaseStarted => query.findTestStepsFinishedBy(testCaseStarted))
.map(testStepFinisheds => testStepFinisheds.map(testStepFinished => query.findAttachmentsBy(testStepFinished)))
.flat(2)
.map(attachment => ([
attachment.testStepId,
attachment.testCaseStartedId,
attachment.mediaType,
attachment.contentEncoding,
])),
findFeatureBy: query.findAllTestCaseStarted()
.map(testCaseStarted => query.findFeatureBy(testCaseStarted))
.map(feature => feature?.name),
findHookBy: query.findAllTestSteps()
.map(testStep => query.findHookBy(testStep))
.map(hook => hook?.id)
.filter(value => !!value),
findMeta: query.findMeta()?.implementation?.name,
findMostSevereTestStepResultBy: query.findAllTestCaseStarted()
.map(testCaseStarted => query.findMostSevereTestStepResultBy(testCaseStarted))
.map(testStepResult => testStepResult?.status),
Expand All @@ -78,7 +93,8 @@ describe('Acceptance Tests', async () => {
.map(pickle => pickle?.name),
findPickleStepBy: query.findAllTestSteps()
.map(testStep => query.findPickleStepBy(testStep))
.map(pickleStep => pickleStep?.text),
.map(pickleStep => pickleStep?.text)
.filter(value => !!value),
findStepBy: query.findAllPickleSteps()
.map(pickleStep => query.findStepBy(pickleStep))
.map(step => step?.text),
Expand Down Expand Up @@ -118,7 +134,9 @@ interface ResultsFixture {
findAllTestCaseStarted: number,
findAllTestSteps: number,
findAllTestCaseStartedGroupedByFeature: Array<[string, string[]]>,
findAttachmentsBy: Array<[string, string, string, string]>,
findFeatureBy: Array<string>,
findMeta: string,
findMostSevereTestStepResultBy: Array<TestStepResultStatus>,
findNameOf: {
long: Array<string>,
Expand All @@ -127,6 +145,7 @@ interface ResultsFixture {
short: Array<string>,
shortPickleName: Array<string>
},
findHookBy: Array<string>,
findPickleBy: Array<string>,
findPickleStepBy: Array<string>,
findStepBy: Array<string>,
Expand All @@ -143,6 +162,7 @@ interface ResultsFixture {

const defaults: Partial<ResultsFixture> = {
findAllTestCaseStartedGroupedByFeature: [],
findAttachmentsBy: [],
findFeatureBy: [],
findMostSevereTestStepResultBy: [],
findNameOf: {
Expand All @@ -152,6 +172,7 @@ const defaults: Partial<ResultsFixture> = {
short: [],
shortPickleName: []
},
findHookBy: [],
findPickleBy: [],
findPickleStepBy: [],
findStepBy: [],
Expand Down
Loading

0 comments on commit 72bed7f

Please sign in to comment.