From c1688c10eee7b631fc3308b24a41b7b9af71df97 Mon Sep 17 00:00:00 2001 From: DelaunayAlex <138011689+DelaunayAlex@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:11:09 +0100 Subject: [PATCH] feat(server, ui): Show dataset usage in dataset page (#204) --- chutney/server-core/pom.xml | 5 ++ .../server/core/domain/dataset/DataSet.java | 40 +++++++++-- .../domain/scenario/AggregatedRepository.java | 2 + .../campaign/domain/CampaignRepository.java | 2 + .../campaign/infra/CampaignJpaRepository.java | 1 + .../infra/CampaignScenarioJpaRepository.java | 1 + .../infra/DatabaseCampaignRepository.java | 10 +++ .../dataset/api/DataSetController.java | 4 +- .../dataset/api/DataSetDto.java | 17 +++++ .../dataset/api/DataSetMapper.java | 3 + .../dataset/domain/DatasetService.java | 51 ++++++++++++-- .../infra/TestCaseRepositoryAggregator.java | 16 +++++ .../infra/raw/DatabaseTestCaseRepository.java | 7 ++ .../infra/raw/ScenarioJpaRepository.java | 2 + .../infra/DatabaseCampaignRepositoryTest.java | 40 +++++++++++ .../infra/FakeCampaignRepository.java | 6 ++ .../dataset/api/DataSetMapperTest.java | 7 ++ .../dataset/domain/DatasetServiceTest.java | 42 +++++++++++- .../ui/src/app/core/model/dataset.model.ts | 5 +- .../src/app/core/services/dataset.service.ts | 31 +++++---- .../dataset-list/dataset-list.component.html | 67 ++++++++++++++++++- .../dataset-list/dataset-list.component.scss | 5 ++ .../dataset-list/dataset-list.component.ts | 5 +- 23 files changed, 340 insertions(+), 29 deletions(-) diff --git a/chutney/server-core/pom.xml b/chutney/server-core/pom.xml index 693d9aa3a..1960a167e 100644 --- a/chutney/server-core/pom.xml +++ b/chutney/server-core/pom.xml @@ -72,6 +72,11 @@ org.springframework spring-web + + org.springframework.data + spring-data-commons + compile + diff --git a/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/dataset/DataSet.java b/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/dataset/DataSet.java index 17ee69b34..b433e0d2a 100644 --- a/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/dataset/DataSet.java +++ b/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/dataset/DataSet.java @@ -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; @@ -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 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; @@ -34,8 +36,11 @@ public class DataSet { public final List tags; public final Map constants; public final List> datatable; + public final Set campaignUsage; + public final Map> scenarioInCampaignUsage; + public final Set scenarioUsage; - private DataSet(String id, String name, String description, Instant creationDate, List tags, Map constants, List> datatable) { + private DataSet(String id, String name, String description, Instant creationDate, List tags, Map constants, List> datatable, Set campaignUsage, Map> scenarioInCampaignUsage, Set scenarioUsage) { this.id = id; this.name = name; this.description = description; @@ -43,6 +48,9 @@ private DataSet(String id, String name, String description, Instant creationDate this.tags = tags; this.constants = constants; this.datatable = datatable; + this.campaignUsage = campaignUsage; + this.scenarioInCampaignUsage = scenarioInCampaignUsage; + this.scenarioUsage = scenarioUsage; } private String getName() { @@ -88,6 +96,9 @@ public static class DataSetBuilder { private List tags; private Map constants; private List> datatable; + public Set campaignUsage; + public Set scenarioUsage; + public Map> scenarioInCampaignUsage; private DataSetBuilder() { } @@ -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()) ); } @@ -147,6 +161,21 @@ public DataSetBuilder withDatatable(List> datatable) { return this; } + public DataSetBuilder withScenarioUsage(Set scenarioUsage) { + this.scenarioUsage = scenarioUsage; + return this; + } + + public DataSetBuilder withCampaignUsage(Set campaignUsage) { + this.campaignUsage = campaignUsage; + return this; + } + + public DataSetBuilder withScenarioInCampaign(Map> scenarioInCampaignUsage) { + this.scenarioInCampaignUsage = scenarioInCampaignUsage; + return this; + } + public DataSetBuilder fromDataSet(DataSet dataset) { return new DataSetBuilder() .withId(dataset.id) @@ -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 cleanConstants(Map constants) { diff --git a/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/scenario/AggregatedRepository.java b/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/scenario/AggregatedRepository.java index d3708cc12..8cec6e9cc 100644 --- a/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/scenario/AggregatedRepository.java +++ b/chutney/server-core/src/main/java/com/chutneytesting/server/core/domain/scenario/AggregatedRepository.java @@ -20,6 +20,8 @@ public interface AggregatedRepository { List findAll(); + List findAllByDatasetId(String datasetId); + void removeById(String testCaseId); Optional lastVersion(String testCaseId); diff --git a/chutney/server/src/main/java/com/chutneytesting/campaign/domain/CampaignRepository.java b/chutney/server/src/main/java/com/chutneytesting/campaign/domain/CampaignRepository.java index ff0ca56fe..619221def 100644 --- a/chutney/server/src/main/java/com/chutneytesting/campaign/domain/CampaignRepository.java +++ b/chutney/server/src/main/java/com/chutneytesting/campaign/domain/CampaignRepository.java @@ -33,4 +33,6 @@ public interface CampaignRepository { List findCampaignsByScenarioId(String scenarioId); List findCampaignsByEnvironment(String environment); + + List findCampaignsByDatasetId(String datasetId); } diff --git a/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignJpaRepository.java b/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignJpaRepository.java index 8f336ba68..1731fa736 100644 --- a/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignJpaRepository.java +++ b/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignJpaRepository.java @@ -24,4 +24,5 @@ void saveWithExplicitId( String description); List findByEnvironment(String environment); + List findByDatasetId(String dataset); } diff --git a/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignScenarioJpaRepository.java b/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignScenarioJpaRepository.java index 26469837d..e8a57e5e5 100644 --- a/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignScenarioJpaRepository.java +++ b/chutney/server/src/main/java/com/chutneytesting/campaign/infra/CampaignScenarioJpaRepository.java @@ -15,4 +15,5 @@ public interface CampaignScenarioJpaRepository extends CrudRepository, JpaSpecificationExecutor { List findAllByScenarioId(String scenarioId); + List findAllByDatasetId(String datasetId); } diff --git a/chutney/server/src/main/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepository.java b/chutney/server/src/main/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepository.java index 3db3cd652..9c996f05c 100644 --- a/chutney/server/src/main/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepository.java +++ b/chutney/server/src/main/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepository.java @@ -136,4 +136,14 @@ public List findCampaignsByEnvironment(String environment) { .map(CampaignEntity::toDomain) .toList(); } + + @Override + public List findCampaignsByDatasetId(String datasetId) { + if (isNullOrEmpty(datasetId)) { + return emptyList(); + } + return campaignJpaRepository.findByDatasetId(datasetId).stream() + .map(CampaignEntity::toDomain) + .toList(); + } } diff --git a/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetController.java b/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetController.java index 3eb54bbaa..d12588f98 100644 --- a/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetController.java +++ b/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetController.java @@ -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 findAll() { - return datasetService.findAll() + public List findAll(@RequestParam("usage") Optional query) { + return datasetService.findAll(query.orElse(false)) .stream() .map(DataSetMapper::toDto) .collect(Collectors.toList()); diff --git a/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetDto.java b/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetDto.java index acff6b8a3..d4fa31eb0 100644 --- a/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetDto.java +++ b/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetDto.java @@ -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; @@ -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 @@ -57,6 +59,21 @@ default List> datatable() { return emptyList(); } + @Value.Default() + default List scenarioUsage() { + return emptyList(); + } + + @Value.Default() + default List campaignUsage() { + return emptyList(); + } + + @Value.Default() + default Map> scenarioInCampaignUsage() { + return emptyMap(); + } + default List duplicatedHeaders() { if(!datatable().isEmpty()) { List headers = datatable().get(0).stream().map(KeyValue::key).toList(); diff --git a/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetMapper.java b/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetMapper.java index d26744b76..1ae254742 100644 --- a/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetMapper.java +++ b/chutney/server/src/main/java/com/chutneytesting/dataset/api/DataSetMapper.java @@ -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(); } diff --git a/chutney/server/src/main/java/com/chutneytesting/dataset/domain/DatasetService.java b/chutney/server/src/main/java/com/chutneytesting/dataset/domain/DatasetService.java index 13c957643..b6c73e368 100644 --- a/chutney/server/src/main/java/com/chutneytesting/dataset/domain/DatasetService.java +++ b/chutney/server/src/main/java/com/chutneytesting/dataset/domain/DatasetService.java @@ -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 @@ -38,11 +43,47 @@ public DataSet findById(String id) { return datasetRepository.findById(id); } - public List findAll() { - return datasetRepository.findAll() + public List findAll(Boolean usage) { + Stream datasets = datasetRepository.findAll() .stream() - .sorted(DataSet.datasetComparator) - .collect(toList()); + .sorted(DataSet.datasetComparator); + if (!usage) { + return datasets.toList(); + } + return datasets + .map(dataset -> { + List campaigns = campaignRepository.findAll(); + Set campaignsUsingDataset = campaigns + .stream() + .filter(campaign -> dataset.id.equals(campaign.executionDataset())) + .map(campaign -> campaign.title) + .collect(Collectors.toSet()); + + Map> 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 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) { diff --git a/chutney/server/src/main/java/com/chutneytesting/scenario/infra/TestCaseRepositoryAggregator.java b/chutney/server/src/main/java/com/chutneytesting/scenario/infra/TestCaseRepositoryAggregator.java index 75a76fc18..ae4d57fb3 100644 --- a/chutney/server/src/main/java/com/chutneytesting/scenario/infra/TestCaseRepositoryAggregator.java +++ b/chutney/server/src/main/java/com/chutneytesting/scenario/infra/TestCaseRepositoryAggregator.java @@ -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; @@ -87,6 +89,20 @@ public List findAll() { .collect(Collectors.toList()); } + @Override + public List 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 -> { diff --git a/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/DatabaseTestCaseRepository.java b/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/DatabaseTestCaseRepository.java index 7add3ba6d..b6c8fddf3 100644 --- a/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/DatabaseTestCaseRepository.java +++ b/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/DatabaseTestCaseRepository.java @@ -106,6 +106,13 @@ public List findAll() { .toList(); } + @Override + public List findAllByDatasetId(String datasetId) { + return scenarioJpaRepository.findByActivatedTrueAndDefaultDataset(datasetId).stream() + .map(ScenarioEntity::toTestCaseMetadata) + .toList(); + } + @Override @Transactional public void removeById(String scenarioId) { diff --git a/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/ScenarioJpaRepository.java b/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/ScenarioJpaRepository.java index dd74e0274..84d4491af 100644 --- a/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/ScenarioJpaRepository.java +++ b/chutney/server/src/main/java/com/chutneytesting/scenario/infra/raw/ScenarioJpaRepository.java @@ -40,6 +40,8 @@ public interface ScenarioJpaRepository extends CrudRepository findMetaDataByActivatedTrue(); + List findByActivatedTrueAndDefaultDataset(String defaultDataset); + static Specification contentContains(String searchWord) { return (root, query, builder) -> { Expression content = builder.lower(root.get("content")); diff --git a/chutney/server/src/test/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepositoryTest.java b/chutney/server/src/test/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepositoryTest.java index b9a3a8789..6aba1fec8 100644 --- a/chutney/server/src/test/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepositoryTest.java +++ b/chutney/server/src/test/java/com/chutneytesting/campaign/infra/DatabaseCampaignRepositoryTest.java @@ -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 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 scenarioCampaignNames = sut.findCampaignsByDatasetId("unknown").stream() + .map(sc -> sc.title) + .collect(Collectors.toList()); + + // Then + Assertions.assertThat(scenarioCampaignNames).isEmpty(); + } } } diff --git a/chutney/server/src/test/java/com/chutneytesting/campaign/infra/FakeCampaignRepository.java b/chutney/server/src/test/java/com/chutneytesting/campaign/infra/FakeCampaignRepository.java index 152936207..fa50cffe1 100644 --- a/chutney/server/src/test/java/com/chutneytesting/campaign/infra/FakeCampaignRepository.java +++ b/chutney/server/src/test/java/com/chutneytesting/campaign/infra/FakeCampaignRepository.java @@ -135,6 +135,12 @@ public List findCampaignsByEnvironment(String environment) { return emptyList(); } + @Override + public List findCampaignsByDatasetId(String datasetId) { + // not needed in tests + return emptyList(); + } + @Override public List currentExecutions(Long campaignId) { // not needed in tests diff --git a/chutney/server/src/test/java/com/chutneytesting/dataset/api/DataSetMapperTest.java b/chutney/server/src/test/java/com/chutneytesting/dataset/api/DataSetMapperTest.java index 9eb7a184e..97a6aef9c 100644 --- a/chutney/server/src/test/java/com/chutneytesting/dataset/api/DataSetMapperTest.java +++ b/chutney/server/src/test/java/com/chutneytesting/dataset/api/DataSetMapperTest.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.IntStream; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -90,6 +91,9 @@ public void should_build_dataset_with_every_field() { .withDescription("description") .withCreationDate(Instant.now()) .withTags(List.of("TAG")) + .withCampaignUsage(Set.of("TOTO")) + .withScenarioInCampaign(Map.of("TUTU", Set.of("BIBI"))) + .withScenarioUsage(Set.of("JEJE")) .build(); DataSetDto datasetDto = DataSetMapper.toDto(dataSet); @@ -104,6 +108,9 @@ public void should_build_dataset_with_every_field() { assertThat(datasetDto.lastUpdated()).isAfter(Instant.now().minus(1, ChronoUnit.HOURS)); assertThat(datasetDto.id().get()).isEqualTo("id"); assertThat(datasetDto.name()).isEqualTo("dataset"); + assertThat(datasetDto.campaignUsage()).containsExactly("TOTO"); + assertThat(datasetDto.scenarioUsage()).containsExactly("JEJE"); + assertThat(datasetDto.scenarioInCampaignUsage()).containsEntry("TUTU", Set.of("BIBI")); } @Test diff --git a/chutney/server/src/test/java/com/chutneytesting/dataset/domain/DatasetServiceTest.java b/chutney/server/src/test/java/com/chutneytesting/dataset/domain/DatasetServiceTest.java index 92c15839c..c27c7eaac 100644 --- a/chutney/server/src/test/java/com/chutneytesting/dataset/domain/DatasetServiceTest.java +++ b/chutney/server/src/test/java/com/chutneytesting/dataset/domain/DatasetServiceTest.java @@ -20,10 +20,13 @@ import com.chutneytesting.scenario.domain.gwt.GwtTestCase; import com.chutneytesting.server.core.domain.dataset.DataSet; 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.Optional; +import java.util.Set; import org.junit.jupiter.api.Test; class DatasetServiceTest { @@ -45,12 +48,49 @@ public void should_sort_dataset_by_name() { .thenReturn(List.of(thirdDataset, secondDataset, firstDataset)); // When - List actual = sut.findAll(); + List actual = sut.findAll(false); // Then assertThat(actual).containsExactly(firstDataset, secondDataset, thirdDataset); } + @Test + public void should_get_all_dataset_with_scenario_usage() { + // Given + DataSet firstDataset = DataSet.builder().withName("A").withId("A").build(); + DataSet secondDataset = DataSet.builder().withName("B").withId("B").build(); + + Campaign.CampaignScenario campaignScenario = new Campaign.CampaignScenario("Scenario1", "A"); + + Campaign campaign1 = new Campaign(1L, "campaign1", "description", List.of(campaignScenario), "env", false, false, "A", List.of()); + Campaign campaign2 = new Campaign(1L, "campaign2", "description", List.of(), "env", false, false, "A", List.of()); + + TestCaseMetadata testCaseMetadata = TestCaseMetadataImpl.builder().withTitle("Scenario1").withId("Scenario1").withDefaultDataset("A").build(); + + GwtTestCase gwtTestCase = GwtTestCase.builder().withMetadata(TestCaseMetadataImpl.builder().withTitle("Scenario1").withId("testCaseId").build()).build(); + + when(datasetRepository.findAll()) + .thenReturn(List.of(firstDataset, secondDataset)); + when(testCaseRepository.findAllByDatasetId("A")) + .thenReturn(List.of(testCaseMetadata)); + when(campaignRepository.findAll()) + .thenReturn(List.of(campaign1, campaign2)); + when(testCaseRepository.findById("Scenario1")) + .thenReturn(Optional.ofNullable(gwtTestCase)); + + // When + List actual = sut.findAll(true); + + // Then + assertThat(actual).hasSize(2); + assertThat(actual.get(0).scenarioUsage).hasSize(1); + assertThat(actual.get(0).scenarioUsage).contains("Scenario1"); + assertThat(actual.get(0).campaignUsage).hasSize(2); + assertThat(actual.get(0).campaignUsage).contains("campaign1"); + assertThat(actual.get(0).campaignUsage).contains("campaign2"); + assertThat(actual.get(0).scenarioInCampaignUsage).containsEntry("campaign1", Set.of("Scenario1")); + } + @Test public void should_update_dataset_reference_in_scenarios_on_rename() { String oldId = "old_id"; diff --git a/chutney/ui/src/app/core/model/dataset.model.ts b/chutney/ui/src/app/core/model/dataset.model.ts index baecb39a2..bce547be2 100644 --- a/chutney/ui/src/app/core/model/dataset.model.ts +++ b/chutney/ui/src/app/core/model/dataset.model.ts @@ -15,7 +15,10 @@ export class Dataset { public lastUpdated: Date, public uniqueValues: Array, public multipleValues: Array>, - public id?: string) { + public id?: string, + public scenarioUsage?: Array, + public campaignUsage?: Array, + public scenarioInCampaignUsage?: { [key: string]: string[] }) { } getMultipleValueHeader(): Array { diff --git a/chutney/ui/src/app/core/services/dataset.service.ts b/chutney/ui/src/app/core/services/dataset.service.ts index 6f66583f6..7cdbe668c 100644 --- a/chutney/ui/src/app/core/services/dataset.service.ts +++ b/chutney/ui/src/app/core/services/dataset.service.ts @@ -10,7 +10,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { environment } from '@env/environment'; import { Dataset, KeyValue } from '@model'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; @Injectable({ providedIn: 'root' @@ -22,18 +22,25 @@ export class DataSetService { constructor(private httpClient: HttpClient) { } - findAll(): Observable> { - return this.httpClient.get>(environment.backend + this.resourceUrl) + findAll(usage: boolean = false): Observable> { + let params = new HttpParams(); + params = params.append('usage', usage ? 'true' : 'false'); + return this.httpClient.get>(environment.backend + this.resourceUrl, { params }) .pipe(map((res: Array) => { - res = res.map(dto => new Dataset( - dto.name, - dto.description, - dto.tags, - dto.lastUpdated, - dto.uniqueValues, - dto.multipleValues, - dto.id - )); + res = res.map(dto => { + return new Dataset( + dto.name, + dto.description, + dto.tags, + dto.lastUpdated, + dto.uniqueValues, + dto.multipleValues, + dto.id, + dto.scenarioUsage, + dto.campaignUsage, + dto.scenarioInCampaignUsage, + ) + }); return res; })); diff --git a/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.html b/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.html index 2860e3256..e5559bf55 100644 --- a/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.html +++ b/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.html @@ -37,12 +37,18 @@
+ +
+ Show usage of dataset in scenario, campaign and scenario in campaign +
+
- + - + + @@ -50,7 +56,7 @@ @for (dataset of (datasets | dataSetSearch : selectedTags | searchTextPipe : dataSetFilter : ['name', 'description']); track dataset.id) { + class="cursor-pointer text-center"> + } diff --git a/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.scss b/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.scss index 8f8768ad0..bc2696b6e 100644 --- a/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.scss +++ b/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.scss @@ -24,4 +24,9 @@ .popover-body { border-radius: 0.5rem; } + + .tooltip-inner { + max-width: none; + + } } diff --git a/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.ts b/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.ts index 5808f2bb3..dbb127352 100644 --- a/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.ts +++ b/chutney/ui/src/app/modules/dataset/components/dataset-list/dataset-list.component.ts @@ -16,6 +16,7 @@ import { Subscription } from 'rxjs'; import { map } from 'rxjs/operators'; import { DROPDOWN_SETTINGS } from '@core/model/dropdown-settings'; import { IDropdownSettings } from 'ng-multiselect-dropdown'; +import {ExecutionStatus} from "@core/model/scenario/execution-status"; @Component({ selector: 'chutney-dataset-list', @@ -24,6 +25,8 @@ import { IDropdownSettings } from 'ng-multiselect-dropdown'; }) export class DatasetListComponent implements OnInit, OnDestroy { + readonly Object = Object; + datasets: Array = []; preview: Dataset = null; @@ -44,7 +47,7 @@ export class DatasetListComponent implements OnInit, OnDestroy { ) {} ngOnInit(): void { - this.dataSetService.findAll().subscribe( + this.dataSetService.findAll(true).subscribe( (res) => { this.datasets = res; this.initTags();
  Name TagsDescriptionDescriptionUsage LastUpdated
{{dataset.description}} + +
+ @for (scenarioUsage of dataset.scenarioUsage; track $index) { + Scenario {{scenarioUsage}}
+ } +
+
+ @if (dataset.scenarioUsage.length > 0) { +
+ + + {{ dataset.scenarioUsage.length }} + +
+ } + +
+ @for (campaignUsage of dataset.campaignUsage; track campaignUsage) { + Campaign {{campaignUsage}}
+ } +
+
+ @if (dataset.campaignUsage.length > 0) { +
+ + + {{ dataset.campaignUsage.length }} + +
+ } + +
+ @for (scenarioInCampaignUsage of Object.keys(dataset.scenarioInCampaignUsage); track scenarioInCampaignUsage) { + Campaign {{scenarioInCampaignUsage}} : +
+ @for (scenario of dataset.scenarioInCampaignUsage[scenarioInCampaignUsage]; track $index) { + Scenario {{scenario}} + } +
+ } +
+
+ @if (Object.keys(dataset.scenarioInCampaignUsage).length > 0) { +
+ + + {{ Object.values(dataset.scenarioInCampaignUsage).flat().length }} + +
+ } +
{{dataset.lastUpdated | amDateFormat: 'YYYY-MM-DD HH:mm'}}