diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10a9868b4..1f60704e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: - name: Tag latest images with release version run: | - VERSION="2.1.0" + VERSION="2.1.1" IMAGES="alex-frontend alex-backend alex-cli alex-docs" for img in $IMAGES diff --git a/CHANGELOG.md b/CHANGELOG.md index 287800c53..be835013f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# ALEX 2.1.1 + +## Fixes + +* Fix bug where test cases could not be executed. +* Fix bug where tests could not be saved when pre steps have changed. + + # ALEX 2.1.0 ## Breaking Changes diff --git a/README.md b/README.md index 2ffb879db..212b0690f 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ For **Windows 10** ### Production -1. [Download](https://github.com/LearnLib/alex/releases/latest) the `docker-compose.alex-2.1.0.yml` file. -2. Run `docker-compose -f docker-compose.alex-2.1.0.yml pull` once. -3. Run `docker-compose -f docker-compose.alex-2.1.0.yml up`. +1. [Download](https://github.com/LearnLib/alex/releases/latest) the `docker-compose.alex-2.1.1.yml` file. +2. Run `docker-compose -f docker-compose.alex-2.1.1.yml pull` once. +3. Run `docker-compose -f docker-compose.alex-2.1.1.yml up`. 4. Open `127.0.0.1` in a web browser to access the frontend. **Services** diff --git a/backend/Dockerfile b/backend/Dockerfile index cd416384d..559aa33b9 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -13,7 +13,7 @@ RUN tar -xzf ltsmin-v3.0.2-linux.tgz RUN mv v3.0.2 ltsmin FROM openjdk:15 -COPY --from=builder-backend /backend/target/ALEX-2.1.0.jar /usr/share/java/alex/alex.jar +COPY --from=builder-backend /backend/target/ALEX-2.1.1.jar /usr/share/java/alex/alex.jar COPY --from=builder-ltsmin /ltsmin/ltsmin /opt/ltsmin WORKDIR /var/lib/alex diff --git a/backend/pom.xml b/backend/pom.xml index 94c8bf7fb..c03d37827 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -61,7 +61,7 @@ jar Automata Learning Experience (ALEX) - 2.1.0 + 2.1.1 de.learnlib.alex diff --git a/backend/src/main/java/de/learnlib/alex/learning/services/TestGenerator.java b/backend/src/main/java/de/learnlib/alex/learning/services/TestGenerator.java index b38c9d39e..715632e5c 100644 --- a/backend/src/main/java/de/learnlib/alex/learning/services/TestGenerator.java +++ b/backend/src/main/java/de/learnlib/alex/learning/services/TestGenerator.java @@ -169,7 +169,7 @@ public TestSuite generate(User user, Long projectId, Long testNo, TestSuiteGener } for (TestCase tc : testSuite.getTestCases()) { - testDAO.update(user, project.getId(), tc); + testDAO.update(user, project.getId(), tc.getId(), tc); } return testSuite; diff --git a/backend/src/main/java/de/learnlib/alex/testing/dao/TestDAO.java b/backend/src/main/java/de/learnlib/alex/testing/dao/TestDAO.java index a2c115837..38e8fdf5c 100644 --- a/backend/src/main/java/de/learnlib/alex/testing/dao/TestDAO.java +++ b/backend/src/main/java/de/learnlib/alex/testing/dao/TestDAO.java @@ -238,8 +238,11 @@ private List create(User user, Long projectId, List tests, TestSuite } public Test get(User user, Long projectId, Long testId) { - final Project project = projectRepository.findById(projectId).orElse(null); - return get(user, project, testId); + final var project = projectRepository.findById(projectId).orElse(null); + final var test = testRepository.findById(testId).orElse(null); + checkAccess(user, project, test); + loadLazyRelations(test); + return test; } public List get(User user, Long projectId, List ids) { @@ -262,8 +265,9 @@ public Test getRoot(User user, Long projectId) { return root; } - public void update(User user, Long projectId, Test test) { - final Project project = projectRepository.findById(projectId).orElse(null); + public Test update(User user, Long projectId, Long testId, Test test) { + final var project = projectRepository.findById(projectId).orElse(null); + final var testInDB = testRepository.findById(testId).orElse(null); checkAccess(user, project, test); checkRunningTestProcess(user, project, test); @@ -271,58 +275,65 @@ public void update(User user, Long projectId, Test test) { testPresenceService.checkLockStatus(projectId, test.getId(), user.getId()); // make sure the name of the Test Case is unique - Test testInDB = testRepository.findOneByParent_IdAndName(test.getParentId(), test.getName()); - if (testInDB != null && !testInDB.getId().equals(test.getId())) { + final var testWithSameName = testRepository.findOneByParent_IdAndName(test.getParentId(), test.getName()); + if (testWithSameName != null && !testWithSameName.getId().equals(testInDB.getId())) { throw new ValidationException("To update a test case or suite its name must be unique within its parent."); } - final Test root = testRepository.findFirstByProject_IdOrderByIdAsc(test.getProjectId()); - if (test.getId().equals(root.getId()) && !test.getName().equals("Root")) { + final var rootTestSuite = testRepository.findFirstByProject_IdOrderByIdAsc(test.getProjectId()); + if (test.getId().equals(rootTestSuite.getId()) && !test.getName().equals("Root")) { throw new ValidationException("The name of the root test suite may not be changed."); } - testInDB = get(user, test.getProjectId(), test.getId()); - - test.setId(testInDB.getId()); - test.setProject(testInDB.getProject()); - test.setParent(getParent(user, projectId, testInDB.getParentId())); - - if (test instanceof TestSuite) { - updateTestSuite(user, (TestSuite) test, test.getProject()); - } else if (test instanceof TestCase) { - updateTestCase(user, (TestCase) test, test.getProject()); + if (testInDB instanceof TestSuite && test instanceof TestSuite) { + final var updatedTestSuite = updateTestSuite((TestSuite) testInDB, (TestSuite) test); + loadLazyRelations(updatedTestSuite); + return updatedTestSuite; + } else if (testInDB instanceof TestCase && test instanceof TestCase) { + final var updatedTestCase = updateTestCase(user, (TestCase) testInDB, (TestCase) test); + loadLazyRelations(updatedTestCase); + return updatedTestCase; + } else { + throw new IllegalStateException("Cannot update a test case with a test suite or vice versa."); } } - private List getStepsWithIds(List steps) { - return steps.stream() - .filter(s -> s.getId() != null) - .map(TestCaseStep::getId) - .collect(Collectors.toList()); - } - - private void updateTestCase(User user, TestCase testCase, Project project) { + private Test updateTestCase(User user, TestCase testCaseInDB, TestCase testCase) { checkIfOutputMappingNamesAreUnique(testCase); - beforeSaving(user, project, testCase); - - testCase.setGenerated(false); - testCase.setUpdatedOn(ZonedDateTime.now()); - testCase.setLastUpdatedBy(user); - - final List allStepIds = new ArrayList<>(); // all ids that still exist in the db - allStepIds.addAll(getStepsWithIds(testCase.getPreSteps())); - allStepIds.addAll(getStepsWithIds(testCase.getSteps())); - allStepIds.addAll(getStepsWithIds(testCase.getPostSteps())); - - testCaseStepRepository.deleteAllByTestCase_IdAndIdNotIn(testCase.getId(), allStepIds); - - // delete all test case steps that have been removed in the update. - saveTestCaseSteps(testCase.getPreSteps()); - saveTestCaseSteps(testCase.getSteps()); - saveTestCaseSteps(testCase.getPostSteps()); - - testRepository.save(testCase); + testCaseInDB.setName(testCase.getName()); + testCaseInDB.setGenerated(false); + testCaseInDB.setUpdatedOn(ZonedDateTime.now()); + testCaseInDB.setLastUpdatedBy(user); + + testCaseInDB.getPreSteps().clear(); + testCaseInDB.getSteps().clear(); + testCaseInDB.getPostSteps().clear(); + testRepository.save(testCaseInDB); + + testCaseInDB.getPreSteps().addAll(testCase.getPreSteps()); + testCaseInDB.getSteps().addAll(testCase.getSteps()); + testCaseInDB.getPostSteps().addAll(testCase.getPostSteps()); + removeIdsFromSteps(testCaseInDB); + beforeSaving(user, testCaseInDB.getProject(), testCaseInDB); + + saveTestCaseSteps(testCaseInDB.getPreSteps()); + saveTestCaseSteps(testCaseInDB.getSteps()); + saveTestCaseSteps(testCaseInDB.getPostSteps()); + testRepository.save(testCaseInDB); + + return testCaseInDB; + } + + private void removeIdsFromSteps(TestCase testCase) { + Stream.of(testCase.getPreSteps(), testCase.getSteps(), testCase.getPostSteps()) + .flatMap(Collection::stream) + .forEach(s -> { + s.setId(null); + s.getPSymbol().setId(null); + s.getPSymbol().getOutputMappings().forEach(om -> om.setId(null)); + s.getPSymbol().getParameterValues().forEach(om -> om.setId(null)); + }); } private void checkIfOutputMappingNamesAreUnique(TestCase testCase) { @@ -336,10 +347,9 @@ private void checkIfOutputMappingNamesAreUnique(TestCase testCase) { SymbolOutputMappingUtils.checkIfMappedNamesAreUnique(oms); } - private void updateTestSuite(User user, TestSuite testSuite, Project project) { - testSuite.getTests().forEach(t -> t.setParent(null)); - beforeSaving(user, project, testSuite); - testRepository.save(testSuite); + private Test updateTestSuite(TestSuite testSuiteInDB, TestSuite testSuite) { + testSuiteInDB.setName(testSuite.getName()); + return testRepository.save(testSuiteInDB); } public void delete(User user, Long projectId, Long testId) { @@ -568,13 +578,6 @@ private void saveTestCaseSteps(List steps) { }); } - private Test get(User user, Project project, Long testId) { - final Test test = testRepository.findById(testId).orElse(null); - checkAccess(user, project, test); - loadLazyRelations(test); - return test; - } - private void loadLazyRelations(TestResult testResult) { if (testResult instanceof TestCaseResult) { Hibernate.initialize(((TestCaseResult) testResult).getOutputs()); @@ -606,7 +609,8 @@ private void beforeSaving(User user, Project project, Test test) { if (test instanceof TestSuite) { TestSuite testSuite = (TestSuite) test; for (Long testId : testSuite.getTestsAsIds()) { - Test otherTest = get(user, project, testId); + final var otherTest = testRepository.findById(testId).orElse(null); + checkAccess(user, project, otherTest); testSuite.addTest(otherTest); } } else if (test instanceof TestCase) { diff --git a/backend/src/main/java/de/learnlib/alex/testing/rest/TestResource.java b/backend/src/main/java/de/learnlib/alex/testing/rest/TestResource.java index b34bb5b2d..ef4626352 100644 --- a/backend/src/main/java/de/learnlib/alex/testing/rest/TestResource.java +++ b/backend/src/main/java/de/learnlib/alex/testing/rest/TestResource.java @@ -250,9 +250,9 @@ public ResponseEntity update(@PathVariable("projectId") Long projectId, @PathVariable("testId") Long testId, @RequestBody Test test) { final var user = authContext.getUser(); - testDAO.update(user, projectId, test); - webhookService.fireEvent(user, new TestEvent.Updated(test)); - return ResponseEntity.ok(test); + final var updatedTest = testDAO.update(user, projectId, testId, test); + webhookService.fireEvent(user, new TestEvent.Updated(updatedTest)); + return ResponseEntity.ok(updatedTest); } /** diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 82f63137d..230dd8034 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -29,7 +29,7 @@ server: alex: filesRootDir: "./target/postgresql/files" - version: "2.1.0" + version: "2.1.1" admin: email: "admin@alex.example" password: "admin" diff --git a/backend/src/test/java/de/learnlib/alex/integrationtests/resources/ATestResourceIT.java b/backend/src/test/java/de/learnlib/alex/integrationtests/resources/ATestResourceIT.java index 185742b78..f8d8ceca8 100644 --- a/backend/src/test/java/de/learnlib/alex/integrationtests/resources/ATestResourceIT.java +++ b/backend/src/test/java/de/learnlib/alex/integrationtests/resources/ATestResourceIT.java @@ -17,6 +17,7 @@ package de.learnlib.alex.integrationtests.resources; import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -270,6 +271,42 @@ public void shouldUpdateTest() throws Exception { assertEquals(testCase.getName(), testCaseIdDb.getName()); } + @Test + public void shouldUpdateTestMoveStepToPreSteps() throws Exception { + final var testCase = createTestCaseWithSteps(project.getId(), "test", null, jwtUser1); + + final var step = testCase.getSteps().remove(0); + testCase.getPreSteps().add(step); + + final var res = testApi.update(testCase.getProjectId(), testCase.getId(), objectMapper.writeValueAsString(testCase), jwtUser1); + assertEquals(HttpStatus.OK.value(), res.getStatus()); + + final var updatedTestCase = res.readEntity(TestCase.class); + assertAll( + () -> assertEquals(2, updatedTestCase.getPreSteps().size()), + () -> assertEquals(1, updatedTestCase.getSteps().size()), + () -> assertEquals(0, updatedTestCase.getPostSteps().size()) + ); + } + + @Test + public void shouldUpdateTestMoveStepToPostSteps() throws Exception { + final var testCase = createTestCaseWithSteps(project.getId(), "test", null, jwtUser1); + + final var step = testCase.getSteps().remove(0); + testCase.getPostSteps().add(step); + + final var res = testApi.update(testCase.getProjectId(), testCase.getId(), objectMapper.writeValueAsString(testCase), jwtUser1); + assertEquals(HttpStatus.OK.value(), res.getStatus()); + + final var updatedTestCase = res.readEntity(TestCase.class); + assertAll( + () -> assertEquals(1, updatedTestCase.getPreSteps().size()), + () -> assertEquals(1, updatedTestCase.getSteps().size()), + () -> assertEquals(1, updatedTestCase.getPostSteps().size()) + ); + } + @Test public void shouldUpdateTestLockedByUser() throws Exception { WebSocketUser webSocketUser = new WebSocketUser("webSocketUser", client, port); diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index 3a1e582f8..b0ae99de1 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -23,7 +23,7 @@ server: alex: filesRootDir: "./target/test-files" - version: "2.1.0" + version: "2.1.1" admin: email: "admin@alex.example" password: "admin" diff --git a/backend/src/test/resources/integrationtest/ALEX-rest.project.json b/backend/src/test/resources/integrationtest/ALEX-rest.project.json index 649219b9b..62e530688 100644 --- a/backend/src/test/resources/integrationtest/ALEX-rest.project.json +++ b/backend/src/test/resources/integrationtest/ALEX-rest.project.json @@ -1,5 +1,5 @@ { - "version": "2.1.0", + "version": "2.1.1", "type": "project", "project": { "name": "ALEX", diff --git a/backend/src/test/resources/integrationtest/ALEX-web.project.json b/backend/src/test/resources/integrationtest/ALEX-web.project.json index 0ccd829f5..649a697be 100644 --- a/backend/src/test/resources/integrationtest/ALEX-web.project.json +++ b/backend/src/test/resources/integrationtest/ALEX-web.project.json @@ -1,5 +1,5 @@ { - "version": "2.1.0", + "version": "2.1.1", "type": "project", "project": { "name": "ALEX", diff --git a/cli/examples/google/project.json b/cli/examples/google/project.json index 21763f5fe..832dcf7ca 100644 --- a/cli/examples/google/project.json +++ b/cli/examples/google/project.json @@ -1,5 +1,5 @@ { - "version": "2.1.0", + "version": "2.1.1", "type": "project", "project": { "name": "google", diff --git a/cli/examples/google/symbol-groups.json b/cli/examples/google/symbol-groups.json index 99326f18f..c9f8632b8 100644 --- a/cli/examples/google/symbol-groups.json +++ b/cli/examples/google/symbol-groups.json @@ -1,5 +1,5 @@ { - "version": "2.1.0", + "version": "2.1.1", "type": "symbolGroups", "symbolGroups": [ { diff --git a/cli/examples/google/symbols.json b/cli/examples/google/symbols.json index b93383592..441eeb749 100644 --- a/cli/examples/google/symbols.json +++ b/cli/examples/google/symbols.json @@ -1,5 +1,5 @@ { - "version": "2.1.0", + "version": "2.1.1", "type": "symbols", "symbols": [ { diff --git a/cli/examples/google/tests.json b/cli/examples/google/tests.json index 2a5e6837c..623c5a1e8 100644 --- a/cli/examples/google/tests.json +++ b/cli/examples/google/tests.json @@ -1,5 +1,5 @@ { - "version": "2.1.0", + "version": "2.1.1", "type": "tests", "tests": [ { diff --git a/cli/package-lock.json b/cli/package-lock.json index 953bd0e88..9d6a8fb63 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,6 +1,6 @@ { "name": "alex-cli", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cli/package.json b/cli/package.json index ab7e6c392..98f5e6b4f 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,10 +1,10 @@ { "name": "alex-cli", - "version": "2.1.0", + "version": "2.1.1", "repository": { "url": "https://github.com/LearnLib/alex/tree/developer/cli" }, - "description": "A command line interface for executing tests and learning experiments with ALEX v2.1.0", + "description": "A command line interface for executing tests and learning experiments with ALEX v2.1.1", "main": "alex-cli.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/cli/src/constants.js b/cli/src/constants.js index 771d40f9a..a65e38ec2 100644 --- a/cli/src/constants.js +++ b/cli/src/constants.js @@ -19,4 +19,4 @@ * * @type {string} */ -module.exports.VERSION = "2.1.0" \ No newline at end of file +module.exports.VERSION = "2.1.1" \ No newline at end of file diff --git a/docker-compose.production.yml b/docker-compose.production.yml index 4327d77e6..62dd1be83 100644 --- a/docker-compose.production.yml +++ b/docker-compose.production.yml @@ -28,14 +28,14 @@ services: volumes: - alex-database:/var/lib/postgresql alex-frontend: - image: ghcr.io/learnlib/alex/alex-frontend:unstable + image: ghcr.io/learnlib/alex/alex-frontend:2.1.1 environment: - ALEX_BACKEND_ADDRESS=http://localhost - ALEX_BACKEND_PORT=8000 ports: - 80:4200 alex-backend: - image: ghcr.io/learnlib/alex/alex-backend:unstable + image: ghcr.io/learnlib/alex/alex-backend:2.1.1 depends_on: - alex-database - selenium-hub diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index eccc01f29..b3f566c0a 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -2,7 +2,7 @@ const env = require('./env.default.js'); module.exports = { base: env.BASE, - title: 'ALEX Docs (v2.1.0)', + title: 'ALEX Docs (v2.1.1)', description: 'User documentation for ALEX', dest: './.vuepress/dist', markdown: { diff --git a/docs/contents/dev-docs/cli/README.md b/docs/contents/dev-docs/cli/README.md index fe332280c..7ad44f1c6 100644 --- a/docs/contents/dev-docs/cli/README.md +++ b/docs/contents/dev-docs/cli/README.md @@ -15,7 +15,7 @@ The CLI is available as a NodeJS module *alex-cli* and can be installed with 1. The CLI is available as a Docker image and can be installed with - `docker pull ghcr.io/learnlib/alex/alex-cli:2.1.0` + `docker pull ghcr.io/learnlib/alex/alex-cli:2.1.1` 2. Run the docker image and execute CLI commands: diff --git a/docs/contents/dev-docs/development/README.md b/docs/contents/dev-docs/development/README.md index 4b4a36681..cb6aac2f3 100644 --- a/docs/contents/dev-docs/development/README.md +++ b/docs/contents/dev-docs/development/README.md @@ -61,7 +61,7 @@ In the `developer` branch, perform the following steps: - Ensure that the [CI pipeline][ci] passes. 4. In the `master` branch, create a new tag with the new version and perform a GitHub release. - Append the current `docker-compose.production.yml` file. - For this purpose, rename the file according to the current release version, e.g. ``docker-compose.alex-2.1.0.yml`` + For this purpose, rename the file according to the current release version, e.g. ``docker-compose.alex-2.1.1.yml`` 5. In the `developer` branch, increment the version in all files from step 1 to the next minor version and append the *-SNAPSHOT* suffix. diff --git a/docs/contents/examples/todomvc/README.md b/docs/contents/examples/todomvc/README.md index cccaec636..4c39dc3d9 100644 --- a/docs/contents/examples/todomvc/README.md +++ b/docs/contents/examples/todomvc/README.md @@ -7,7 +7,7 @@ In this section, we present the steps in order to learn the *ReactJS* implementa ## Requirements -* ALEX v2.1.0 +* ALEX v2.1.1 * [TodoMVC](http://todomvc.com/) v1.3 diff --git a/docs/contents/getting-started/installation/README.md b/docs/contents/getting-started/installation/README.md index 4ae0bfb3c..c161febf2 100644 --- a/docs/contents/getting-started/installation/README.md +++ b/docs/contents/getting-started/installation/README.md @@ -11,8 +11,8 @@ For **Windows 10** ## Using the latest Docker Compose file -1. [Download][download] the latest `docker-compose.alex-2.1.0.yml` file. -2. Open a terminal and start ALEX via `docker-compose -f docker-compose.alex-2.1.0.yml up`. +1. [Download][download] the latest `docker-compose.alex-2.1.1.yml` file. +2. Open a terminal and start ALEX via `docker-compose -f docker-compose.alex-2.1.1.yml up`. 3. Wait until the command line prints something like `Started App in XX.XXX seconds`. 4. Open [http://127.0.0.1](http://127.0.0.1) in a Web browser. diff --git a/docs/package-lock.json b/docs/package-lock.json index aeb84b747..56102da7c 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -1,12 +1,12 @@ { "name": "alex-docs", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "alex-docs", - "version": "2.1.0", + "version": "2.1.1", "devDependencies": { "stylus": "^0.54.8", "stylus-loader": "^3.0.2", diff --git a/docs/package.json b/docs/package.json index 4b6fe58f2..18e7a86a7 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "alex-docs", - "version": "2.1.0", + "version": "2.1.1", "description": "Documentation for ALEX.", "licence": { "type": "Apache-2.0", diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 43e9a6f67..b02049937 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "alex-frontend", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "alex-frontend", - "version": "2.1.0", + "version": "2.1.1", "dependencies": { "@angular/animations": "^11.0.4", "@angular/cdk": "^11.0.2", diff --git a/frontend/package.json b/frontend/package.json index 9f050f7a0..56a204fe0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "alex-frontend", - "version": "2.1.0", + "version": "2.1.1", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/frontend/src/app/common/test-status-widget/test-status-widget.component.html b/frontend/src/app/common/test-status-widget/test-status-widget.component.html index 581a63ad6..66d20111c 100644 --- a/frontend/src/app/common/test-status-widget/test-status-widget.component.html +++ b/frontend/src/app/common/test-status-widget/test-status-widget.component.html @@ -6,13 +6,13 @@
-
+
There is no active test run.
-
+
- +
diff --git a/frontend/src/app/views/root-view/about-modal/about-modal.component.html b/frontend/src/app/views/root-view/about-modal/about-modal.component.html index 901a99510..5664207aa 100644 --- a/frontend/src/app/views/root-view/about-modal/about-modal.component.html +++ b/frontend/src/app/views/root-view/about-modal/about-modal.component.html @@ -36,7 +36,7 @@
Related links
Homepage
  • - Documentation + Documentation
  • ALEX @ GitHub diff --git a/frontend/src/app/views/root-view/root-view.component.html b/frontend/src/app/views/root-view/root-view.component.html index fb846cad6..8a9dcaae8 100644 --- a/frontend/src/app/views/root-view/root-view.component.html +++ b/frontend/src/app/views/root-view/root-view.component.html @@ -35,7 +35,7 @@
  • diff --git a/frontend/src/app/views/test-case-view/test-case-view.component.html b/frontend/src/app/views/test-case-view/test-case-view.component.html index 5b9350fd1..bab5a8d68 100644 --- a/frontend/src/app/views/test-case-view/test-case-view.component.html +++ b/frontend/src/app/views/test-case-view/test-case-view.component.html @@ -2,7 +2,7 @@
    -
    - +
    diff --git a/frontend/src/app/views/test-suite-view/test-suite-view.component.html b/frontend/src/app/views/test-suite-view/test-suite-view.component.html index cd9f85177..ac0ec46b7 100644 --- a/frontend/src/app/views/test-suite-view/test-suite-view.component.html +++ b/frontend/src/app/views/test-suite-view/test-suite-view.component.html @@ -70,17 +70,11 @@
    -
    - -
    -
    - -
    @@ -191,7 +185,7 @@

    - +
    diff --git a/frontend/src/app/views/test-suite-view/test-suite-view.component.ts b/frontend/src/app/views/test-suite-view/test-suite-view.component.ts index 4b06ab8e9..6e0f63dbf 100644 --- a/frontend/src/app/views/test-suite-view/test-suite-view.component.ts +++ b/frontend/src/app/views/test-suite-view/test-suite-view.component.ts @@ -34,13 +34,11 @@ import { AppStoreService } from '../../services/app-store.service'; import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TestsImportModalComponent } from './tests-import-modal/tests-import-modal.component'; -import { - TestConfigModalAction, - TestConfigModalComponent -} from '../tests-view/test-config-modal/test-config-modal.component'; +import { TestConfigModalComponent } from '../tests-view/test-config-modal/test-config-modal.component'; import { TestsMoveModalComponent } from './tests-move-modal/tests-move-modal.component'; import { TestReportStatus, TestStatus } from '../../entities/test-status'; import { TestLockInfo, TestPresenceService } from '../../services/test-presence.service'; +import { TestExecutionConfig } from '../../entities/test-execution-config'; @Component({ selector: 'test-suite-view', @@ -100,7 +98,11 @@ export class TestSuiteViewComponent implements OnInit, OnDestroy { this.testConfigs = testConfigs; const i = this.testConfigs.findIndex(c => c.default); if (i > -1) { - this.testConfig = this.testConfigs[i]; + this.testConfig = testConfigs[i]; + this.testConfig.environment = this.project.getEnvironmentById(this.testConfig.environment.id); + } else { + this.testConfig = new TestExecutionConfig(); + this.testConfig.environment = this.project.getDefaultEnvironment(); } }, console.error @@ -274,32 +276,16 @@ export class TestSuiteViewComponent implements OnInit, OnDestroy { && this.testStatus.currentTest.id === test.id; } - openCreateTestConfigModal(): void { - const modalRef = this.modalService.open(TestConfigModalComponent); - modalRef.componentInstance.action = TestConfigModalAction.CREATE; - modalRef.componentInstance.configuration = {}; - modalRef.componentInstance.configuration.driverConfig = {}; - modalRef.componentInstance.project = this.project; - modalRef.result.then(_ => { - this.testConfigApi.getAll(this.project.id).subscribe( - testConfigs => { - this.testConfigs = testConfigs; - }, - console.error - ); - }).catch(() => { - }); - } - - openEditTestConfigModal(): void { + openTestConfigModal(): void { const modalRef = this.modalService.open(TestConfigModalComponent); - modalRef.componentInstance.action = TestConfigModalAction.EDIT; - modalRef.componentInstance.configuration = JSON.parse(JSON.stringify(this.testConfig)); + if (this.testConfig != null) { + modalRef.componentInstance.configuration = JSON.parse(JSON.stringify(this.testConfig)); + } modalRef.componentInstance.project = this.project; modalRef.result.then(config => { - const i = this.testConfigs.findIndex(value => value.id === config.id); - this.testConfigs[i] = config; - }).catch(() => { + this.testConfig = config; + this.toastService.success(`Config has been saved for the moment.`); + }).catch(() => { }); } @@ -415,7 +401,7 @@ export class TestSuiteViewComponent implements OnInit, OnDestroy { return {}; } - if (this.report.status === TestReportStatus.IN_PROGRESS && this.testStatus != null) { + if (this.report.status === TestReportStatus.IN_PROGRESS && this.testStatus?.currentTestRun?.results != null) { return this.testStatus.currentTestRun.results; } @@ -424,4 +410,7 @@ export class TestSuiteViewComponent implements OnInit, OnDestroy { return map; } + get canExecute(): boolean { + return this.selectedTests.isAnySelected() && TestExecutionConfig.isValid(this.testConfig); + } } diff --git a/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.html b/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.html index e0c75ab63..20f920408 100644 --- a/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.html +++ b/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.html @@ -31,9 +31,9 @@
    {{env.name}} @@ -41,33 +41,6 @@
    - - Test - -
    - -
    - - -
    -
    - - -
    -
    -
    @@ -75,7 +48,6 @@
    diff --git a/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.ts b/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.ts index a96f3e450..7e01fce24 100644 --- a/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.ts +++ b/frontend/src/app/views/tests-view/test-config-modal/test-config-modal.component.ts @@ -15,15 +15,11 @@ */ import { Project } from '../../../entities/project'; -import { ProjectEnvironment } from '../../../entities/project-environment'; import { Component, Input, OnInit } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TestConfigApiService } from '../../../services/api/test-config-api.service'; import { ToastService } from '../../../services/toast.service'; - -export enum TestConfigModalAction { - CREATE, EDIT -} +import { TestExecutionConfig } from '../../../entities/test-execution-config'; /** * A modal dialog for the web driver configuration. @@ -36,20 +32,12 @@ export class TestConfigModalComponent implements OnInit { /** The web driver configuration. */ @Input() - configuration: any; + configuration: TestExecutionConfig; /** The current project. */ @Input() project: Project; - /** The model for the url ids. */ - @Input() - selectedEnvironment: ProjectEnvironment; - - /** The action for which this modal has been opened. */ - @Input() - action: TestConfigModalAction; - /** Constructor. */ constructor(public modal: NgbActiveModal, public testConfigApi: TestConfigApiService, @@ -57,40 +45,17 @@ export class TestConfigModalComponent implements OnInit { } ngOnInit(): void { - this.selectedEnvironment = this.project.getDefaultEnvironment(); - } - - create(): void { - this.configuration.id = null; - this.configuration.driverConfig.id = null; - this.configuration.tests = []; - this.configuration.project = this.project.id; - this.configuration.environmentId = this.selectedEnvironment.id; - - this.testConfigApi.create(this.project.id, this.configuration).subscribe(config => { - this.toastService.success('The config has been created.'); - this.modal.close(config); - }, res => { - this.toastService.danger(`The config couldn't be created. ${res.error.message}`); - this.modal.dismiss(); - }); + if (this.configuration == null) { + this.configuration = new TestExecutionConfig(); + this.configuration.environmentId = this.project.getDefaultEnvironment().id; + } } - /** - * Close the modal window and pass the configuration. - */ update(): void { - this.configuration.environmentId = this.selectedEnvironment.id; - this.testConfigApi.update(this.project.id, this.configuration).subscribe(config => { - this.toastService.success('The config has been updated.'); - this.modal.close(config); - }, res => { - this.toastService.danger(`The config couldn't be updated. ${res.error.message}`); - this.modal.dismiss(); - }); + this.modal.close(this.configuration); } - get TestConfigModalAction() { - return TestConfigModalAction; + get validConfig(): boolean { + return TestExecutionConfig.isValid(this.configuration); } } diff --git a/frontend/src/environments/environment.prod.ts b/frontend/src/environments/environment.prod.ts index e6562dd6d..0949e1ccb 100644 --- a/frontend/src/environments/environment.prod.ts +++ b/frontend/src/environments/environment.prod.ts @@ -1,4 +1,4 @@ export const environment = { production: true, - version: '2.1.0' + version: '2.1.1' }; diff --git a/frontend/src/environments/environment.ts b/frontend/src/environments/environment.ts index a34bd0c17..19e36c90f 100644 --- a/frontend/src/environments/environment.ts +++ b/frontend/src/environments/environment.ts @@ -4,7 +4,7 @@ export const environment = { production: false, - version: '2.1.0' + version: '2.1.1' }; /*