Skip to content

Commit

Permalink
feat(server, ui): Show dataset usage in dataset page (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
DelaunayAlex authored Nov 4, 2024
1 parent 1043a71 commit c1688c1
Show file tree
Hide file tree
Showing 23 changed files with 340 additions and 29 deletions.
5 changes: 5 additions & 0 deletions chutney/server-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<scope>compile</scope>
</dependency>

<!-- Test -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import static java.time.temporal.ChronoUnit.MILLIS;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
Expand All @@ -19,13 +20,14 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;

public class DataSet {

public static Comparator<DataSet> datasetComparator = Comparator.comparing(DataSet::getName, String.CASE_INSENSITIVE_ORDER);
public static DataSet NO_DATASET = new DataSet(null, null, null, null, null, emptyMap(), emptyList());
public static DataSet NO_DATASET = new DataSet(null, null, null, null, null, emptyMap(), emptyList(), emptySet(), emptyMap(), emptySet());

public final String id;
public final String name;
Expand All @@ -34,15 +36,21 @@ public class DataSet {
public final List<String> tags;
public final Map<String, String> constants;
public final List<Map<String, String>> datatable;
public final Set<String> campaignUsage;
public final Map<String, Set<String>> scenarioInCampaignUsage;
public final Set<String> scenarioUsage;

private DataSet(String id, String name, String description, Instant creationDate, List<String> tags, Map<String, String> constants, List<Map<String, String>> datatable) {
private DataSet(String id, String name, String description, Instant creationDate, List<String> tags, Map<String, String> constants, List<Map<String, String>> datatable, Set<String> campaignUsage, Map<String, Set<String>> scenarioInCampaignUsage, Set<String> scenarioUsage) {
this.id = id;
this.name = name;
this.description = description;
this.creationDate = creationDate;
this.tags = tags;
this.constants = constants;
this.datatable = datatable;
this.campaignUsage = campaignUsage;
this.scenarioInCampaignUsage = scenarioInCampaignUsage;
this.scenarioUsage = scenarioUsage;
}

private String getName() {
Expand Down Expand Up @@ -88,6 +96,9 @@ public static class DataSetBuilder {
private List<String> tags;
private Map<String, String> constants;
private List<Map<String, String>> datatable;
public Set<String> campaignUsage;
public Set<String> scenarioUsage;
public Map<String, Set<String>> scenarioInCampaignUsage;

private DataSetBuilder() {
}
Expand All @@ -104,7 +115,10 @@ public DataSet build() {
ofNullable(creationDate).orElseGet(() -> Instant.now().truncatedTo(MILLIS)),
(ofNullable(tags).orElse(emptyList())).stream().map(String::toUpperCase).map(String::strip).collect(toList()),
cleanConstants(ofNullable(constants).orElse(emptyMap())),
cleanDatatable(ofNullable(datatable).orElse(emptyList()))
cleanDatatable(ofNullable(datatable).orElse(emptyList())),
ofNullable(campaignUsage).orElse(emptySet()),
ofNullable(scenarioInCampaignUsage).orElse(emptyMap()),
ofNullable(scenarioUsage).orElse(emptySet())
);
}

Expand Down Expand Up @@ -147,6 +161,21 @@ public DataSetBuilder withDatatable(List<Map<String, String>> datatable) {
return this;
}

public DataSetBuilder withScenarioUsage(Set<String> scenarioUsage) {
this.scenarioUsage = scenarioUsage;
return this;
}

public DataSetBuilder withCampaignUsage(Set<String> campaignUsage) {
this.campaignUsage = campaignUsage;
return this;
}

public DataSetBuilder withScenarioInCampaign(Map<String, Set<String>> scenarioInCampaignUsage) {
this.scenarioInCampaignUsage = scenarioInCampaignUsage;
return this;
}

public DataSetBuilder fromDataSet(DataSet dataset) {
return new DataSetBuilder()
.withId(dataset.id)
Expand All @@ -155,7 +184,10 @@ public DataSetBuilder fromDataSet(DataSet dataset) {
.withCreationDate(dataset.creationDate)
.withTags(dataset.tags)
.withConstants(dataset.constants)
.withDatatable(dataset.datatable);
.withDatatable(dataset.datatable)
.withCampaignUsage(dataset.campaignUsage)
.withScenarioUsage(dataset.scenarioUsage)
.withScenarioInCampaign(dataset.scenarioInCampaignUsage);
}

private Map<String, String> cleanConstants(Map<String, String> constants) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public interface AggregatedRepository<T extends TestCase> {

List<TestCaseMetadata> findAll();

List<TestCaseMetadata> findAllByDatasetId(String datasetId);

void removeById(String testCaseId);

Optional<Integer> lastVersion(String testCaseId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ public interface CampaignRepository {
List<Campaign> findCampaignsByScenarioId(String scenarioId);

List<Campaign> findCampaignsByEnvironment(String environment);

List<Campaign> findCampaignsByDatasetId(String datasetId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ void saveWithExplicitId(
String description);

List<CampaignEntity> findByEnvironment(String environment);
List<CampaignEntity> findByDatasetId(String dataset);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
public interface CampaignScenarioJpaRepository extends CrudRepository<CampaignScenarioEntity, Long>, JpaSpecificationExecutor<CampaignScenarioEntity> {

List<CampaignScenarioEntity> findAllByScenarioId(String scenarioId);
List<CampaignScenarioEntity> findAllByDatasetId(String datasetId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,14 @@ public List<Campaign> findCampaignsByEnvironment(String environment) {
.map(CampaignEntity::toDomain)
.toList();
}

@Override
public List<Campaign> findCampaignsByDatasetId(String datasetId) {
if (isNullOrEmpty(datasetId)) {
return emptyList();
}
return campaignJpaRepository.findByDatasetId(datasetId).stream()
.map(CampaignEntity::toDomain)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public DataSetController(DatasetService datasetService) {

@PreAuthorize("hasAuthority('DATASET_READ') or hasAuthority('SCENARIO_WRITE') or hasAuthority('CAMPAIGN_WRITE')")
@GetMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE)
public List<DataSetDto> findAll() {
return datasetService.findAll()
public List<DataSetDto> findAll(@RequestParam("usage") Optional<Boolean> query) {
return datasetService.findAll(query.orElse(false))
.stream()
.map(DataSetMapper::toDto)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import static java.time.Instant.now;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

Expand All @@ -19,6 +20,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.immutables.value.Value;

@Value.Immutable
Expand Down Expand Up @@ -57,6 +59,21 @@ default List<List<KeyValue>> datatable() {
return emptyList();
}

@Value.Default()
default List<String> scenarioUsage() {
return emptyList();
}

@Value.Default()
default List<String> campaignUsage() {
return emptyList();
}

@Value.Default()
default Map<String, Set<String>> scenarioInCampaignUsage() {
return emptyMap();
}

default List<String> duplicatedHeaders() {
if(!datatable().isEmpty()) {
List<String> headers = datatable().get(0).stream().map(KeyValue::key).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public static DataSetDto toDto(DataSet dataSet) {
if (dataSet.tags != null) datasetBuilder.tags(dataSet.tags);
if (dataSet.description != null) datasetBuilder.description(dataSet.description);
if (dataSet.creationDate != null) datasetBuilder.lastUpdated(dataSet.creationDate);
if (dataSet.campaignUsage != null) datasetBuilder.campaignUsage(dataSet.campaignUsage);
if (dataSet.scenarioUsage != null) datasetBuilder.scenarioUsage(dataSet.scenarioUsage);
if (dataSet.scenarioInCampaignUsage != null) datasetBuilder.scenarioInCampaignUsage(dataSet.scenarioInCampaignUsage);
return datasetBuilder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@
package com.chutneytesting.dataset.domain;

import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;

import com.chutneytesting.campaign.domain.CampaignRepository;
import com.chutneytesting.scenario.domain.gwt.GwtTestCase;
import com.chutneytesting.server.core.domain.dataset.DataSet;
import com.chutneytesting.server.core.domain.dataset.DataSetNotFoundException;
import com.chutneytesting.server.core.domain.scenario.AggregatedRepository;
import com.chutneytesting.server.core.domain.scenario.TestCaseMetadata;
import com.chutneytesting.server.core.domain.scenario.TestCaseMetadataImpl;
import com.chutneytesting.server.core.domain.scenario.campaign.Campaign;
import com.chutneytesting.server.core.domain.scenario.campaign.CampaignBuilder;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.stereotype.Component;

@Component
Expand All @@ -38,11 +43,47 @@ public DataSet findById(String id) {
return datasetRepository.findById(id);
}

public List<DataSet> findAll() {
return datasetRepository.findAll()
public List<DataSet> findAll(Boolean usage) {
Stream<DataSet> datasets = datasetRepository.findAll()
.stream()
.sorted(DataSet.datasetComparator)
.collect(toList());
.sorted(DataSet.datasetComparator);
if (!usage) {
return datasets.toList();
}
return datasets
.map(dataset -> {
List<Campaign> campaigns = campaignRepository.findAll();
Set<String> campaignsUsingDataset = campaigns
.stream()
.filter(campaign -> dataset.id.equals(campaign.executionDataset()))
.map(campaign -> campaign.title)
.collect(Collectors.toSet());

Map<String, Set<String>> scenarioInCampaignUsingDataset = campaigns.stream()
.filter(campaign -> campaign.scenarios.stream()
.anyMatch(scenario -> dataset.id.equals(scenario.datasetId())))
.collect(Collectors.groupingBy(
campaign -> campaign.title,
Collectors.flatMapping(
campaign -> campaign.scenarios.stream()
.filter(campaignScenario -> dataset.id.equals(campaignScenario.datasetId()))
.map(campaignScenario -> testCaseRepository.findById(campaignScenario.scenarioId()))
.map(scenario -> scenario.map(s -> s.metadata.title).orElseThrow()),
Collectors.toSet()
)
));
Set<String> scenariosUsingDataset = testCaseRepository.findAllByDatasetId(dataset.id)
.stream()
.map(TestCaseMetadata::title)
.collect(Collectors.toSet());
return DataSet.builder()
.fromDataSet(dataset)
.withCampaignUsage(campaignsUsingDataset)
.withScenarioUsage(scenariosUsingDataset)
.withScenarioInCampaign(scenarioInCampaignUsingDataset)
.build();
})
.toList();
}

public DataSet save(DataSet dataset) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

package com.chutneytesting.scenario.infra;

import static java.util.Optional.ofNullable;

import com.chutneytesting.server.core.domain.scenario.AggregatedRepository;
import com.chutneytesting.server.core.domain.scenario.ScenarioNotFoundException;
import com.chutneytesting.server.core.domain.scenario.TestCase;
Expand Down Expand Up @@ -87,6 +89,20 @@ public List<TestCaseMetadata> findAll() {
.collect(Collectors.toList());
}

@Override
public List<TestCaseMetadata> findAllByDatasetId(String datasetId) {
return aggregatedRepositories
.stream()
.flatMap(r ->
getTestCaseMetadataStream(r::findAll, r.getClass().getSimpleName())
)
.filter(testCase ->
ofNullable(testCase.defaultDataset())
.map(t -> t.equals(datasetId))
.orElse(datasetId == null))
.collect(Collectors.toList());
}

@Override
public void removeById(String testCaseId) {
aggregatedRepositories.forEach(repo -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ public List<TestCaseMetadata> findAll() {
.toList();
}

@Override
public List<TestCaseMetadata> findAllByDatasetId(String datasetId) {
return scenarioJpaRepository.findByActivatedTrueAndDefaultDataset(datasetId).stream()
.map(ScenarioEntity::toTestCaseMetadata)
.toList();
}

@Override
@Transactional
public void removeById(String scenarioId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public interface ScenarioJpaRepository extends CrudRepository<ScenarioEntity, Lo
""")
List<ScenarioEntity> findMetaDataByActivatedTrue();

List<ScenarioEntity> findByActivatedTrueAndDefaultDataset(String defaultDataset);

static Specification<ScenarioEntity> contentContains(String searchWord) {
return (root, query, builder) -> {
Expression<String> content = builder.lower(root.get("content"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,5 +254,45 @@ public void should_find_no_campaigns_related_to_a_given_environment() {
// Then
Assertions.assertThat(scenarioCampaignNames).isEmpty();
}

@Test
public void should_find_campaigns_related_to_a_given_dataset() {
// Given
Campaign campaign1 = new Campaign(null, "campaignTestName1", "campaignDesc1", emptyList(), "env", false, false, "dataset1", null);
Campaign campaign2 = new Campaign(null, "campaignTestName2", "campaignDesc2", emptyList(), "env", false, false, "dataset2", null);
Campaign campaign3 = new Campaign(null, "campaignTestName3", "campaignDesc3", emptyList(), "env", false, false, "dataset2", null);
Campaign campaign4 = new Campaign(null, "campaignTestName4", "campaignDesc4", emptyList(), "env", false, false, "dataset3", null);
sut.createOrUpdate(campaign1);
sut.createOrUpdate(campaign2);
sut.createOrUpdate(campaign3);
sut.createOrUpdate(campaign4);

// When
List<String> scenarioCampaignNames = sut.findCampaignsByDatasetId("dataset2").stream()
.map(sc -> sc.title)
.collect(Collectors.toList());

// Then
Assertions.assertThat(scenarioCampaignNames).containsExactlyInAnyOrder(
campaign2.title,
campaign3.title
);
}

@Test
public void should_find_no_campaigns_related_to_a_given_dataset() {
// Given
ScenarioEntity s1 = givenScenario();
Campaign campaign1 = new Campaign(null, "campaignTestName2", "campaignDesc2", scenariosIds(s1), "env", false, false, "dataset", null);
sut.createOrUpdate(campaign1);

// When
List<String> scenarioCampaignNames = sut.findCampaignsByDatasetId("unknown").stream()
.map(sc -> sc.title)
.collect(Collectors.toList());

// Then
Assertions.assertThat(scenarioCampaignNames).isEmpty();
}
}
}
Loading

0 comments on commit c1688c1

Please sign in to comment.