From e76734deec91c5e71b2978eacf3e18c1dab8aeee Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Sat, 6 Apr 2024 14:16:30 +0200 Subject: [PATCH 01/11] Add create wallet test --- .../karate/src/test/java/fe/features/wallet.feature | 12 +++++++++--- tests/karate/src/test/java/fe/utils/android.feature | 11 +++++++++++ tests/karate/src/test/java/fe/utils/web.feature | 12 +++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/karate/src/test/java/fe/features/wallet.feature b/tests/karate/src/test/java/fe/features/wallet.feature index 2aaf0b74f8..1d23712e21 100644 --- a/tests/karate/src/test/java/fe/features/wallet.feature +++ b/tests/karate/src/test/java/fe/features/wallet.feature @@ -1,6 +1,12 @@ Feature: Wallet Scenario: Open the app for the first time and see the wallet seed - When call read('classpath:fe/utils/platform.feature') { name: 'open_app' } - Then match text(wallet_seed_wallet_text) == "#regex ^([a-z]+\\s){11}[a-z]+$" - And screenshot() + Given call read('classpath:fe/utils/platform.feature') { name: 'open_app' } + When match text(wallet_seed_wallet_text) == "#regex ^([a-z]+\\s){11}[a-z]+$" + Then screenshot() + + Scenario: Create a new wallet + Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } + When waitFor(lao_join_button) + Then screenshot() + diff --git a/tests/karate/src/test/java/fe/utils/android.feature b/tests/karate/src/test/java/fe/utils/android.feature index 355e00f9fd..0f74948955 100644 --- a/tests/karate/src/test/java/fe/utils/android.feature +++ b/tests/karate/src/test/java/fe/utils/android.feature @@ -4,8 +4,19 @@ Feature: android page object # Wallet screen * def wallet_button_empty_ok = '//*[@text="OK"]' * def wallet_seed_wallet_text = '#com.github.dedis.popstellar:id/seed_wallet_text' + * def wallet_new_wallet_button = "#com.github.dedis.popstellar:id/button_confirm_seed" + * def wallet_confirm_new_wallet_button = '//*[@text="YES"]' + # Lao screen + * def lao_join_button = '#com.github.dedis.popstellar:id/home_join_button' @name=open_app Scenario: Given driver webDriverOptions Then waitFor(wallet_button_empty_ok).click() + + @name=create_new_wallet + Scenario: + Given call read('android.feature@name=open_app') + When waitFor(wallet_new_wallet_button) + Then click(wallet_new_wallet_button) + Then waitFor(wallet_confirm_new_wallet_button).click() diff --git a/tests/karate/src/test/java/fe/utils/web.feature b/tests/karate/src/test/java/fe/utils/web.feature index 0935e23a4e..ee2aa78ee0 100644 --- a/tests/karate/src/test/java/fe/utils/web.feature +++ b/tests/karate/src/test/java/fe/utils/web.feature @@ -3,6 +3,11 @@ Feature: web page object Background: # Wallet screen * def wallet_seed_wallet_text = "[data-testid='seed_wallet_text']" + * def wallet_new_wallet_button = "[data-testid='exploring_selector']" + + # Lao screen + * def lao_create_button = "{}Create" + * def lao_join_button = "{^}Join" @name=open_app Scenario: @@ -10,4 +15,9 @@ Feature: web page object Given driver 'about:blank' And driver.dimensions = { left: 0, top: 0, width: screenWidth, height: screenHeight } Then driver frontendURL - And delay(1000) + + @name=create_new_wallet + Scenario: + Given call read('web.feature@name=open_app') + When waitFor(wallet_new_wallet_button) + Then click(wallet_new_wallet_button) From 58da3f6599b342e2d9e486bc6f56cf99e62963a6 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Sat, 6 Apr 2024 15:01:15 +0200 Subject: [PATCH 02/11] Add restore wallet test --- tests/karate/src/test/java/fe/features/wallet.feature | 5 +++++ tests/karate/src/test/java/fe/utils/android.feature | 9 +++++++++ tests/karate/src/test/java/fe/utils/platform.feature | 3 ++- tests/karate/src/test/java/fe/utils/web.feature | 11 +++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/karate/src/test/java/fe/features/wallet.feature b/tests/karate/src/test/java/fe/features/wallet.feature index 1d23712e21..f2a962e53c 100644 --- a/tests/karate/src/test/java/fe/features/wallet.feature +++ b/tests/karate/src/test/java/fe/features/wallet.feature @@ -10,3 +10,8 @@ Feature: Wallet When waitFor(lao_join_button) Then screenshot() + Scenario: Restore a wallet + Given call read('classpath:fe/utils/platform.feature') {name: 'restore_wallet', params: { seed: 'present guilt frost screen fabric rotate citizen decide have message chat hood' } } + When waitFor(lao_join_button) + Then screenshot() + diff --git a/tests/karate/src/test/java/fe/utils/android.feature b/tests/karate/src/test/java/fe/utils/android.feature index 0f74948955..4360e079d1 100644 --- a/tests/karate/src/test/java/fe/utils/android.feature +++ b/tests/karate/src/test/java/fe/utils/android.feature @@ -6,6 +6,9 @@ Feature: android page object * def wallet_seed_wallet_text = '#com.github.dedis.popstellar:id/seed_wallet_text' * def wallet_new_wallet_button = "#com.github.dedis.popstellar:id/button_confirm_seed" * def wallet_confirm_new_wallet_button = '//*[@text="YES"]' + * def wallet_restore_button = '#com.github.dedis.popstellar:id/import_seed_button' + * def wallet_restore_input = '#com.github.dedis.popstellar:id/import_seed_entry_edit_text' + # Lao screen * def lao_join_button = '#com.github.dedis.popstellar:id/home_join_button' @@ -20,3 +23,9 @@ Feature: android page object When waitFor(wallet_new_wallet_button) Then click(wallet_new_wallet_button) Then waitFor(wallet_confirm_new_wallet_button).click() + + @name=restore_wallet + Scenario: + Given call read('android.feature@name=open_app') + When input(wallet_restore_input, params.seed) + Then click(wallet_restore_button) diff --git a/tests/karate/src/test/java/fe/utils/platform.feature b/tests/karate/src/test/java/fe/utils/platform.feature index b66e80a9df..4c29db95b0 100644 --- a/tests/karate/src/test/java/fe/utils/platform.feature +++ b/tests/karate/src/test/java/fe/utils/platform.feature @@ -4,4 +4,5 @@ Feature: current env page object * def page_object = 'classpath:fe/utils/.feature@name=' * replace page_object.env = karate.env * replace page_object.name = name - * call read(page_object) + * def params = karate.get('params', {}) + * call read(page_object) params diff --git a/tests/karate/src/test/java/fe/utils/web.feature b/tests/karate/src/test/java/fe/utils/web.feature index ee2aa78ee0..6a03cc8019 100644 --- a/tests/karate/src/test/java/fe/utils/web.feature +++ b/tests/karate/src/test/java/fe/utils/web.feature @@ -4,6 +4,9 @@ Feature: web page object # Wallet screen * def wallet_seed_wallet_text = "[data-testid='seed_wallet_text']" * def wallet_new_wallet_button = "[data-testid='exploring_selector']" + * def wallet_goto_restore_wallet_button = "{}Restore" + * def wallet_restore_wallet_button = "{}Restore Wallet" + * def wallet_restore_input = "input" # Lao screen * def lao_create_button = "{}Create" @@ -21,3 +24,11 @@ Feature: web page object Given call read('web.feature@name=open_app') When waitFor(wallet_new_wallet_button) Then click(wallet_new_wallet_button) + + @name=restore_wallet + Scenario: + Given call read('web.feature@name=open_app') + When waitFor(wallet_goto_restore_wallet_button).click() + Then input(wallet_restore_input, params.seed) + Then click(wallet_restore_wallet_button) + From 8a96cd6950552da8c89061eb92b3f3cae8270ca8 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Mon, 8 Apr 2024 21:59:15 +0200 Subject: [PATCH 03/11] Added lao creation test --- tests/karate/docs/README.md | 37 ++++++++++--------- .../src/test/java/fe/features/lao.feature | 11 ++++++ .../src/test/java/fe/features/wallet.feature | 4 +- .../src/test/java/fe/utils/android.feature | 7 ++++ .../karate/src/test/java/fe/utils/web.feature | 8 ++++ tests/karate/src/test/java/karate-config.js | 2 + 6 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 tests/karate/src/test/java/fe/features/lao.feature diff --git a/tests/karate/docs/README.md b/tests/karate/docs/README.md index d5166562a9..2ffc96c330 100644 --- a/tests/karate/docs/README.md +++ b/tests/karate/docs/README.md @@ -178,33 +178,34 @@ With the Karate plugin for IntelliJ, the full tests can also be run directly fro ### Android Front-end Build the application by running `./gradlew assembleDebug` in the corresponding directory. -Then, start an emulator from Android Studio and launch the Appium server (using the command `appium`). +Then, launch the Appium server (using the command `appium`) as well as a backend server. -Finally run the tests. -``` -mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -``` +Finally run the tests: +* All tests: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest` +* One feature: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature"` +* One scenario: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature --tags=@name="` -In case you have multiple emulator running, you may specify one by name. -```shell -mvn test -Dkarate.env=android -Davd= -Dtest=FrontEndTest#fullTest -#e.g. mvn test -Dkarate.env=android -Davd=Pixel_3a_API_34 -Dtest=FrontEndTest#fullTest -``` +The following options are available (option names must be prefixed by `-D`). +| Name | Description | Default | +|--------------|------------------------------------------------|-------------------------------------------| +| browser | One of 'chrome', 'safari', 'edge' or 'firefox' | 'chrome' | +| url | URL of the web app | 'file:../../fe1-web/web-build/index.html' | +| screenWidth | Width of the browser | 1920 | +| screenHeight | Height of the browser | 1080 | +| serverURL | Client URL of the backend server | 'ws://localhost:9000/client' for the web and 'ws://10.0.2.2:9000/client' for android | ### Web Front-end Build the app with `npm run build-web` in the corresponding directory. Launch the Appium server (with `appium`). -Run the tests. -``` -mvn test -Dkarate.env=web -Dtest=FrontEndTest#fullTest -``` +Finally run the tests: +* All tests: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest` +* One feature: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature"` +* One scenario: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature --tags=@name="` The following options are available (option names must be prefixed by `-D`). | Name | Description | Default | |--------------|------------------------------------------------|-------------------------------------------| -| browser | One of 'chrome', 'safari', 'edge' or 'firefox' | 'chrome' | -| url | URL of the web app | 'file:../../fe1-web/web-build/index.html' | -| screenWidth | Width of the browser | 1920 | -| screenHeight | Height of the browser | 1080 | +| avd | Name of the android emulator | Choosen automatically by appium | +| serverURL | Client URL of the backend server | 'ws://localhost:9000/client' for the web and 'ws://10.0.2.2:9000/client' for android | diff --git a/tests/karate/src/test/java/fe/features/lao.feature b/tests/karate/src/test/java/fe/features/lao.feature new file mode 100644 index 0000000000..72a570e2c7 --- /dev/null +++ b/tests/karate/src/test/java/fe/features/lao.feature @@ -0,0 +1,11 @@ +Feature: LAO + Scenario: Create a new LAO + Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } + And def organization_name = 'My test organization' + When waitFor(lao_create_button).click() + And waitFor(lao_organization_name_input).input(organization_name) + And waitFor(lao_server_url_input).clear().input(serverURL) + And screenshot() + And click(lao_launch_button) + Then waitFor(event_create_button) + Then screenshot() diff --git a/tests/karate/src/test/java/fe/features/wallet.feature b/tests/karate/src/test/java/fe/features/wallet.feature index f2a962e53c..a058839e92 100644 --- a/tests/karate/src/test/java/fe/features/wallet.feature +++ b/tests/karate/src/test/java/fe/features/wallet.feature @@ -1,15 +1,17 @@ Feature: Wallet - + @name=open_app Scenario: Open the app for the first time and see the wallet seed Given call read('classpath:fe/utils/platform.feature') { name: 'open_app' } When match text(wallet_seed_wallet_text) == "#regex ^([a-z]+\\s){11}[a-z]+$" Then screenshot() + @name=wallet_create Scenario: Create a new wallet Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } When waitFor(lao_join_button) Then screenshot() + @name=wallet_restore Scenario: Restore a wallet Given call read('classpath:fe/utils/platform.feature') {name: 'restore_wallet', params: { seed: 'present guilt frost screen fabric rotate citizen decide have message chat hood' } } When waitFor(lao_join_button) diff --git a/tests/karate/src/test/java/fe/utils/android.feature b/tests/karate/src/test/java/fe/utils/android.feature index 4360e079d1..c81bb5537f 100644 --- a/tests/karate/src/test/java/fe/utils/android.feature +++ b/tests/karate/src/test/java/fe/utils/android.feature @@ -10,7 +10,14 @@ Feature: android page object * def wallet_restore_input = '#com.github.dedis.popstellar:id/import_seed_entry_edit_text' # Lao screen + * def lao_create_button = "#com.github.dedis.popstellar:id/home_create_button" * def lao_join_button = '#com.github.dedis.popstellar:id/home_join_button' + * def lao_organization_name_input = "#com.github.dedis.popstellar:id/lao_name_entry_edit_text" + * def lao_server_url_input = "#com.github.dedis.popstellar:id/server_url_entry_edit_text" + * def lao_launch_button = "#com.github.dedis.popstellar:id/button_create" + + # Event screen + * def event_create_button = "#com.github.dedis.popstellar:id/add_event" @name=open_app Scenario: diff --git a/tests/karate/src/test/java/fe/utils/web.feature b/tests/karate/src/test/java/fe/utils/web.feature index 6a03cc8019..4822d60899 100644 --- a/tests/karate/src/test/java/fe/utils/web.feature +++ b/tests/karate/src/test/java/fe/utils/web.feature @@ -1,6 +1,8 @@ @ignore @report=false Feature: web page object Background: + # Functions + # Wallet screen * def wallet_seed_wallet_text = "[data-testid='seed_wallet_text']" * def wallet_new_wallet_button = "[data-testid='exploring_selector']" @@ -11,6 +13,12 @@ Feature: web page object # Lao screen * def lao_create_button = "{}Create" * def lao_join_button = "{^}Join" + * def lao_organization_name_input = "input[data-testid='launch_organization_name_selector']" + * def lao_server_url_input = "input[data-testid='launch_address_selector']" + * def lao_launch_button = "[data-testid='launch_launch_selector']" + + # Event screen + * def event_create_button = "[data-testid='create_event_selector']" @name=open_app Scenario: diff --git a/tests/karate/src/test/java/karate-config.js b/tests/karate/src/test/java/karate-config.js index 65090d4374..ce370b0c96 100644 --- a/tests/karate/src/test/java/karate-config.js +++ b/tests/karate/src/test/java/karate-config.js @@ -33,6 +33,7 @@ function fn() { config.frontendWsURL = `ws://${config.host}:${config.frontendPort}/${config.frontendPath}`; config.backendWsURL = `ws://${config.host}:${config.backendPort}/${config.backendPath}`; } else if (env === 'web') { + config.serverURL = karate.properties['serverURL'] || 'ws://localhost:9000/client'; config.frontendURL = karate.properties['url'] || `file://${karate.toAbsolutePath('file:../../fe1-web/web-build/index.html')}`; config.screenWidth = karate.properties['screenWidth'] || 1920; config.screenHeight = karate.properties['screenHeight'] || 1080; @@ -97,6 +98,7 @@ function fn() { } }; } else if (env === 'android') { + config.serverURL = karate.properties['serverURL'] || 'ws://10.0.2.2:9000/client'; karate.configure('driver', { type: 'android', webDriverPath : "/", start: false }); const app = karate.properties['app'] || '../../fe2-android/app/build/outputs/apk/debug/app-debug.apk'; config.webDriverOptions = { From c8e5a44effa1f004f7fdba8746bd5fe47d3e599a Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Wed, 10 Apr 2024 13:27:39 +0200 Subject: [PATCH 04/11] First test with mocked client --- .../src/test/java/fe/features/lao.feature | 22 ++++++++- .../src/test/java/fe/utils/android.feature | 3 ++ .../test/java/fe/utils/mock_client.feature | 48 +++++++++++++++++++ .../karate/src/test/java/fe/utils/web.feature | 6 ++- 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/karate/src/test/java/fe/utils/mock_client.feature diff --git a/tests/karate/src/test/java/fe/features/lao.feature b/tests/karate/src/test/java/fe/features/lao.feature index 72a570e2c7..6accdf9aaf 100644 --- a/tests/karate/src/test/java/fe/features/lao.feature +++ b/tests/karate/src/test/java/fe/features/lao.feature @@ -1,6 +1,11 @@ Feature: LAO - Scenario: Create a new LAO + Background: + * def mock = call read('classpath:fe/utils/mock_client.feature') Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } + + + @name=lao_create + Scenario: Create a new LAO And def organization_name = 'My test organization' When waitFor(lao_create_button).click() And waitFor(lao_organization_name_input).input(organization_name) @@ -9,3 +14,18 @@ Feature: LAO And click(lao_launch_button) Then waitFor(event_create_button) Then screenshot() + + @name=lao_join + Scenario: Manually connect to an existing LAO + * def organizer = mock.create_client() + * def lao = organizer.createValidLao() + * mock.create_lao(organizer, lao) + * waitFor(lao_join_button).click() + * waitFor(lao_enter_manually_button).click() + And waitFor(lao_enter_manually_server_input).clear().input(serverURL) + And waitFor(lao_enter_manually_lao_input).clear().input(lao.id) + And screenshot() + And click(lao_enter_manually_submit_button) + Then waitFor(event_create_button) + * organizer.stop() + Then screenshot() diff --git a/tests/karate/src/test/java/fe/utils/android.feature b/tests/karate/src/test/java/fe/utils/android.feature index c81bb5537f..a4702d43b9 100644 --- a/tests/karate/src/test/java/fe/utils/android.feature +++ b/tests/karate/src/test/java/fe/utils/android.feature @@ -15,6 +15,9 @@ Feature: android page object * def lao_organization_name_input = "#com.github.dedis.popstellar:id/lao_name_entry_edit_text" * def lao_server_url_input = "#com.github.dedis.popstellar:id/server_url_entry_edit_text" * def lao_launch_button = "#com.github.dedis.popstellar:id/button_create" + * def lao_enter_manually_button = "#com.github.dedis.popstellar:id/scanner_enter_manually" + * def lao_enter_manually_lao_input = "#com.github.dedis.popstellar:id/manual_add_edit_text" + * def lao_enter_manually_submit_button = "#com.github.dedis.popstellar:id/manual_add_button" # Event screen * def event_create_button = "#com.github.dedis.popstellar:id/add_event" diff --git a/tests/karate/src/test/java/fe/utils/mock_client.feature b/tests/karate/src/test/java/fe/utils/mock_client.feature new file mode 100644 index 0000000000..305b5bb763 --- /dev/null +++ b/tests/karate/src/test/java/fe/utils/mock_client.feature @@ -0,0 +1,48 @@ +@ignore @report=false +Feature: Mock Client + + Scenario: Creates mock clients that can connect to a server as a frontend or server + * def create_client = + """ + function(){ + var MockClient = Java.type('be.utils.MockClient') + var mockFrontend = new MockClient(serverURL) + return mockFrontend + } + """ + + * def create_lao = + """ + function(client, lao){ + const request = { + "object": "lao", + "action": "create", + "id": lao.id, + "name": lao.name, + "creation": lao.creation, + "organizer": lao.organizerPk, + "witnesses": lao.witnesses + }; + organizer.publish(request, "/root"); + organizer.getBackendResponse(request) + organizer.send({ + "method": "subscribe", + "id": 2, + "params": { + "channel": lao.channel, + }, + "jsonrpc": "2.0" + }) + + organizer.takeTimeout(1000) + organizer.send( { + "method": "catchup", + "id": 5, + "params": { + "channel": lao.channel, + }, + "jsonrpc": "2.0" + }) + organizer.takeTimeout(1000) + } + """ diff --git a/tests/karate/src/test/java/fe/utils/web.feature b/tests/karate/src/test/java/fe/utils/web.feature index 4822d60899..55ff7fe253 100644 --- a/tests/karate/src/test/java/fe/utils/web.feature +++ b/tests/karate/src/test/java/fe/utils/web.feature @@ -12,10 +12,14 @@ Feature: web page object # Lao screen * def lao_create_button = "{}Create" - * def lao_join_button = "{^}Join" + * def lao_join_button = "{}Join" * def lao_organization_name_input = "input[data-testid='launch_organization_name_selector']" * def lao_server_url_input = "input[data-testid='launch_address_selector']" * def lao_launch_button = "[data-testid='launch_launch_selector']" + * def lao_enter_manually_button = "{}Enter Manually" + * def lao_enter_manually_server_input = "input[placeholder='Server URI']" + * def lao_enter_manually_lao_input = "input[placeholder='LAO ID']" + * def lao_enter_manually_submit_button = "[data-testid='connect-button']" # Event screen * def event_create_button = "[data-testid='create_event_selector']" From bd34182c86d44d2a4c0f88a1393a2525a26ec2fc Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Fri, 12 Apr 2024 08:05:21 +0200 Subject: [PATCH 05/11] Rename MockClient functions --- tests/karate/docs/README.md | 4 ++-- .../src/test/java/be/features/LAO/create.feature | 2 +- .../src/test/java/be/features/LAO/update.feature | 2 +- .../features/decentralizedCom/getMessagesById.feature | 4 ++-- .../be/features/decentralizedCom/heartbeat.feature | 4 ++-- .../java/be/features/digitalCash/transaction.feature | 4 ++-- .../test/java/be/features/election/castVote.feature | 8 ++++---- .../test/java/be/features/election/electionEnd.feature | 6 +++--- .../java/be/features/election/electionOpen.feature | 8 ++++---- .../java/be/features/election/electionSetup.feature | 6 +++--- .../java/be/features/rollCall/closeRollCall.feature | 6 +++--- .../java/be/features/rollCall/createRollCall.feature | 8 ++++---- .../java/be/features/rollCall/openRollCall.feature | 6 +++--- tests/karate/src/test/java/be/utils/MockClient.java | 10 +++++++--- tests/karate/src/test/java/fe/features/lao.feature | 2 +- 15 files changed, 42 insertions(+), 38 deletions(-) diff --git a/tests/karate/docs/README.md b/tests/karate/docs/README.md index 3616118f6e..2a11c65822 100644 --- a/tests/karate/docs/README.md +++ b/tests/karate/docs/README.md @@ -68,8 +68,8 @@ Feature: Create a Roll Call * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def validRollCall = organizer.createValidRollCall(lao) + * def lao = organizer.generateValidLao() + * def validRollCall = organizer.generateValidRollCall(lao) * call read(createLaoScenario) { organizer: '#(organizer)', lao: '#(lao)' } @createRollCall1 diff --git a/tests/karate/src/test/java/be/features/LAO/create.feature b/tests/karate/src/test/java/be/features/LAO/create.feature index 5d91b5e892..57b5b46fe9 100644 --- a/tests/karate/src/test/java/be/features/LAO/create.feature +++ b/tests/karate/src/test/java/be/features/LAO/create.feature @@ -8,7 +8,7 @@ Feature: Create a pop LAO * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def validLao = organizer.createValidLao() + * def validLao = organizer.generateValidLao() @create1 Scenario: Create Lao request with empty lao name should fail with an error response diff --git a/tests/karate/src/test/java/be/features/LAO/update.feature b/tests/karate/src/test/java/be/features/LAO/update.feature index fd093798bf..49e62143ea 100644 --- a/tests/karate/src/test/java/be/features/LAO/update.feature +++ b/tests/karate/src/test/java/be/features/LAO/update.feature @@ -7,7 +7,7 @@ Feature: Update a LAO * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() + * def lao = organizer.generateValidLao() # This call executes all the steps to create a valid lao on the server before every scenario # (lao creation, subscribe, catchup) diff --git a/tests/karate/src/test/java/be/features/decentralizedCom/getMessagesById.feature b/tests/karate/src/test/java/be/features/decentralizedCom/getMessagesById.feature index 8cd2db3f5f..04e8fd8d2a 100644 --- a/tests/karate/src/test/java/be/features/decentralizedCom/getMessagesById.feature +++ b/tests/karate/src/test/java/be/features/decentralizedCom/getMessagesById.feature @@ -8,7 +8,7 @@ Feature: Request messages by id from other servers * call read(mockClientFeature) * def mockBackend = call createMockBackend * def mockFrontend = call createMockFrontend - * def lao = mockFrontend.createValidLao() + * def lao = mockFrontend.generateValidLao() # Create the template for heartbeat message # This is used in combination with 'eval' to dynamically resolve the channel keys in the heartbeat JSON @@ -63,7 +63,7 @@ Feature: Request messages by id from other servers # trigger a getMessagesById anymore @getMessagesById4 Scenario: Server should not request messages that it already has - Given def validRollCall = mockFrontend.createValidRollCall(lao) + Given def validRollCall = mockFrontend.generateValidRollCall(lao) And def validCreateRollCall = """ { diff --git a/tests/karate/src/test/java/be/features/decentralizedCom/heartbeat.feature b/tests/karate/src/test/java/be/features/decentralizedCom/heartbeat.feature index 8345301539..3a9b881125 100644 --- a/tests/karate/src/test/java/be/features/decentralizedCom/heartbeat.feature +++ b/tests/karate/src/test/java/be/features/decentralizedCom/heartbeat.feature @@ -8,8 +8,8 @@ Feature: Send heartbeats to other servers * call read(mockClientFeature) * def mockBackend = call createMockBackend * def mockFrontend = call createMockFrontend - * def lao = mockFrontend.createValidLao() - * def validRollCall = mockFrontend.createValidRollCall(lao) + * def lao = mockFrontend.generateValidLao() + * def validRollCall = mockFrontend.generateValidRollCall(lao) # This call executes all the steps to create a valid lao on the server before every scenario # (lao creation, subscribe, catchup) diff --git a/tests/karate/src/test/java/be/features/digitalCash/transaction.feature b/tests/karate/src/test/java/be/features/digitalCash/transaction.feature index c23a2b17c3..c5fce21b8e 100644 --- a/tests/karate/src/test/java/be/features/digitalCash/transaction.feature +++ b/tests/karate/src/test/java/be/features/digitalCash/transaction.feature @@ -7,8 +7,8 @@ Feature: Simple Transactions for digital cash * call read(mockClientFeature) * def organizer = call createMockFrontend * def recipient = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) # This call executes all the steps to set up a lao, complete a roll call and subscribe to the coin channel * call read(setupCoinChannelScenario) { organizer: '#(organizer)', lao: '#(lao)', rollCall: '#(rollCall)' } diff --git a/tests/karate/src/test/java/be/features/election/castVote.feature b/tests/karate/src/test/java/be/features/election/castVote.feature index e924b04db5..83f0c46bb5 100644 --- a/tests/karate/src/test/java/be/features/election/castVote.feature +++ b/tests/karate/src/test/java/be/features/election/castVote.feature @@ -6,9 +6,9 @@ Feature: Cast a vote * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) - * def election = organizer.createValidElection(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) + * def election = organizer.generateValidElection(lao) * def question = election.createQuestion() # This call executes all the steps to set up a lao, complete a roll call and open an election with one question @@ -71,7 +71,7 @@ Feature: Cast a vote # upon casting a vote @castVote3 Scenario: Casting a valid vote on non existent election should return an error - Given def newElection = organizer.createValidElection(lao) + Given def newElection = organizer.generateValidElection(lao) And def newQuestion = newElection.createQuestion() And def newVote = newQuestion.createVote(0) And def newCastVote = newElection.castVote(newVote) diff --git a/tests/karate/src/test/java/be/features/election/electionEnd.feature b/tests/karate/src/test/java/be/features/election/electionEnd.feature index 5918c09967..ffe927b29b 100644 --- a/tests/karate/src/test/java/be/features/election/electionEnd.feature +++ b/tests/karate/src/test/java/be/features/election/electionEnd.feature @@ -6,9 +6,9 @@ Feature: Terminate an election * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) - * def election = organizer.createValidElection(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) + * def election = organizer.generateValidElection(lao) * def question = election.createQuestion() # This call executes all the steps to set up a lao, complete a roll call, open an election and cast a vote diff --git a/tests/karate/src/test/java/be/features/election/electionOpen.feature b/tests/karate/src/test/java/be/features/election/electionOpen.feature index b51b7ebedf..bb5e70695e 100644 --- a/tests/karate/src/test/java/be/features/election/electionOpen.feature +++ b/tests/karate/src/test/java/be/features/election/electionOpen.feature @@ -6,9 +6,9 @@ Feature: Open an Election * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) - * def election = organizer.createValidElection(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) + * def election = organizer.generateValidElection(lao) * def question = election.createQuestion() # This call executes all the steps to set up a lao, complete a roll call and create an election with one question @@ -38,7 +38,7 @@ Feature: Open an Election # upon an open election message @electionOpen2 Scenario: Opening the election without a setup should result in an error - Given def newElection = organizer.createValidElection(lao) + Given def newElection = organizer.generateValidElection(lao) And def newElectionOpen = newElection.open() And def validElectionOpen = """ diff --git a/tests/karate/src/test/java/be/features/election/electionSetup.feature b/tests/karate/src/test/java/be/features/election/electionSetup.feature index 467d2e96bb..c6850b86da 100644 --- a/tests/karate/src/test/java/be/features/election/electionSetup.feature +++ b/tests/karate/src/test/java/be/features/election/electionSetup.feature @@ -6,9 +6,9 @@ Feature: Setup an Election * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) - * def election = organizer.createValidElection(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) + * def election = organizer.generateValidElection(lao) * def question = election.createQuestion() # This call executes all the steps to set up a lao and complete a roll call, to get a valid pop token diff --git a/tests/karate/src/test/java/be/features/rollCall/closeRollCall.feature b/tests/karate/src/test/java/be/features/rollCall/closeRollCall.feature index f4909f9fd2..c5828e0cad 100644 --- a/tests/karate/src/test/java/be/features/rollCall/closeRollCall.feature +++ b/tests/karate/src/test/java/be/features/rollCall/closeRollCall.feature @@ -8,8 +8,8 @@ Feature: Close a Roll Call * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) # This call executes all the steps to open a valid roll call on the server before every scenario # (lao creation, subscribe, catchup, roll call creation, roll call open) @@ -78,7 +78,7 @@ Feature: Close a Roll Call @closeRollCall4 Scenario: Closing a Roll Call that was not opened on the server returns an error - Given def newRollCall = organizer.createValidRollCall(lao) + Given def newRollCall = organizer.generateValidRollCall(lao) # This call creates the new roll call on the server without opening it And call read(createRollCallScenario) { organizer: '#(organizer)', lao: '#(lao)', rollCall: '#(newRollCall)' } And def closeNewRollCall = newRollCall.close() diff --git a/tests/karate/src/test/java/be/features/rollCall/createRollCall.feature b/tests/karate/src/test/java/be/features/rollCall/createRollCall.feature index bf37bca415..680ad3706c 100644 --- a/tests/karate/src/test/java/be/features/rollCall/createRollCall.feature +++ b/tests/karate/src/test/java/be/features/rollCall/createRollCall.feature @@ -8,8 +8,8 @@ Feature: Create a Roll Call * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def validRollCall = organizer.createValidRollCall(lao) + * def lao = organizer.generateValidLao() + * def validRollCall = organizer.generateValidRollCall(lao) # This call executes all the steps to create a valid lao on the server before every scenario # (lao creation, subscribe, catchup) @@ -213,8 +213,8 @@ Feature: Create a Roll Call # in an error message from the backend. @createRollCall9 Scenario: Roll Call Creation for non existent lao should return an error - Given def randomLao = organizer.createValidLao() - And def randomRollCall = organizer.createValidRollCall(randomLao) + Given def randomLao = organizer.generateValidLao() + And def randomRollCall = organizer.generateValidRollCall(randomLao) Given def validCreateRollCall = """ { diff --git a/tests/karate/src/test/java/be/features/rollCall/openRollCall.feature b/tests/karate/src/test/java/be/features/rollCall/openRollCall.feature index 61c46bc2b3..554e8099b8 100644 --- a/tests/karate/src/test/java/be/features/rollCall/openRollCall.feature +++ b/tests/karate/src/test/java/be/features/rollCall/openRollCall.feature @@ -8,8 +8,8 @@ Feature: Roll Call Open * call read(serverFeature) * call read(mockClientFeature) * def organizer = call createMockFrontend - * def lao = organizer.createValidLao() - * def rollCall = organizer.createValidRollCall(lao) + * def lao = organizer.generateValidLao() + * def rollCall = organizer.generateValidRollCall(lao) # This call executes all the steps to create a valid roll call on the server before every scenario # (lao creation, subscribe, catchup, roll call creation) @@ -56,7 +56,7 @@ Feature: Roll Call Open @openRollCall3 Scenario: Opening a Roll Call that was not created on the server returns an error - Given def newRollCall = organizer.createValidRollCall(lao) + Given def newRollCall = organizer.generateValidRollCall(lao) And def openNewRollCall = newRollCall.open() And def validOpenRollCall = """ diff --git a/tests/karate/src/test/java/be/utils/MockClient.java b/tests/karate/src/test/java/be/utils/MockClient.java index e8b47e70c1..9dff2415be 100644 --- a/tests/karate/src/test/java/be/utils/MockClient.java +++ b/tests/karate/src/test/java/be/utils/MockClient.java @@ -22,7 +22,7 @@ public MockClient(String wsURL) { /** * @return a valid lao with the client's public key, the current time, and a random valid lao name. */ - public Lao createValidLao() { + public Lao generateValidLao() { // Name needs to be random so that the same organizer does not create the same lao twice if it happens in the same second String randomName = RandomUtils.generateRandomName(); System.out.println("Client with public key: " + publicKey + " is creating a lao: " + randomName); @@ -33,7 +33,7 @@ public Lao createValidLao() { * @param lao the lao to create a roll call for * @return a valid roll call for the given lao */ - public RollCall createValidRollCall(Lao lao) { + public RollCall generateValidRollCall(Lao lao) { System.out.println("Client with public key: " + publicKey + " is creating roll call for lao: " + lao.id); long rollCallCreation = Instant.now().getEpochSecond(); // Name needs to be random so that the same organizer does not create the same roll call twice if it happens in the same second @@ -57,7 +57,7 @@ public RollCall createValidRollCall(Lao lao) { * @param lao the lao to create an election for * @return a valid empty election for the given lao, questions still need to be added! */ - public Election createValidElection(Lao lao) { + public Election generateValidElection(Lao lao) { System.out.println("Client with public key: " + publicKey + " is creating an election for lao: " + lao.id); long electionCreation = Instant.now().getEpochSecond(); // Name needs to be random so that the same organizer does not create the same election twice if it happens in the same second @@ -90,4 +90,8 @@ public Transaction issueCoins(MockClient receiver, long amountToGive) throws Gen transaction.issueInitialCoins(receiver.publicKey, publicKey, privateKey, amountToGive); return transaction; } + + public void sendCreateLao(Lao lao = lao) { + + } } diff --git a/tests/karate/src/test/java/fe/features/lao.feature b/tests/karate/src/test/java/fe/features/lao.feature index 6accdf9aaf..fad419cedc 100644 --- a/tests/karate/src/test/java/fe/features/lao.feature +++ b/tests/karate/src/test/java/fe/features/lao.feature @@ -18,7 +18,7 @@ Feature: LAO @name=lao_join Scenario: Manually connect to an existing LAO * def organizer = mock.create_client() - * def lao = organizer.createValidLao() + * def lao = organizer.generateValidLao() * mock.create_lao(organizer, lao) * waitFor(lao_join_button).click() * waitFor(lao_enter_manually_button).click() From b8be0abb945de6d0fbb91594105b32114320ae8c Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Mon, 15 Apr 2024 00:41:08 +0200 Subject: [PATCH 06/11] Add lao join test --- .../src/test/java/be/utils/MockClient.java | 30 ++++++++++++- .../src/test/java/fe/features/lao.feature | 19 +++------ .../src/test/java/fe/features/wallet.feature | 6 +-- .../src/test/java/fe/utils/android.feature | 5 +++ .../src/test/java/fe/utils/constants.feature | 3 +- .../test/java/fe/utils/mock_client.feature | 42 ++++--------------- .../karate/src/test/java/fe/utils/web.feature | 10 +++++ 7 files changed, 63 insertions(+), 52 deletions(-) diff --git a/tests/karate/src/test/java/be/utils/MockClient.java b/tests/karate/src/test/java/be/utils/MockClient.java index 9dff2415be..ddce2a1d97 100644 --- a/tests/karate/src/test/java/be/utils/MockClient.java +++ b/tests/karate/src/test/java/be/utils/MockClient.java @@ -11,6 +11,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.HashMap; +import java.util.Map; /** Websocket client capable of creating lao, roll call, and election objects and issuing coins */ public class MockClient extends MultiMsgWebSocketClient { @@ -91,7 +93,33 @@ public Transaction issueCoins(MockClient receiver, long amountToGive) throws Gen return transaction; } - public void sendCreateLao(Lao lao = lao) { + /** + * Creates a newly generated lao. + * @return the lao created + */ + public Lao createLao() { + Lao lao = generateValidLao(); + return createLao(lao); + } + + /** + * Creates a lao. + * @param lao the lao to create + * @return the lao passed as argument + */ + public Lao createLao(Lao lao) { + Map request = new HashMap<>(); + request.put("object", "lao"); + request.put("action", "create"); + request.put("id", lao.id); + request.put("name", lao.name); + request.put("creation", lao.creation); + request.put("organizer", lao.organizerPk); + request.put("witnesses", lao.witnesses); + + this.publish(request, "/root"); + this.getBackendResponse(request); + return lao; } } diff --git a/tests/karate/src/test/java/fe/features/lao.feature b/tests/karate/src/test/java/fe/features/lao.feature index fad419cedc..2f3c2d429f 100644 --- a/tests/karate/src/test/java/fe/features/lao.feature +++ b/tests/karate/src/test/java/fe/features/lao.feature @@ -1,11 +1,11 @@ Feature: LAO Background: - * def mock = call read('classpath:fe/utils/mock_client.feature') - Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } + Given call read('classpath:fe/utils/mock_client.feature') @name=lao_create Scenario: Create a new LAO + Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } And def organization_name = 'My test organization' When waitFor(lao_create_button).click() And waitFor(lao_organization_name_input).input(organization_name) @@ -17,15 +17,8 @@ Feature: LAO @name=lao_join Scenario: Manually connect to an existing LAO - * def organizer = mock.create_client() - * def lao = organizer.generateValidLao() - * mock.create_lao(organizer, lao) - * waitFor(lao_join_button).click() - * waitFor(lao_enter_manually_button).click() - And waitFor(lao_enter_manually_server_input).clear().input(serverURL) - And waitFor(lao_enter_manually_lao_input).clear().input(lao.id) + Given def organizer = createMockClient() + And def lao = organizer.createLao() + When call read('classpath:fe/utils/platform.feature') { name: 'lao_join', params: { lao: '#(lao)' } } + Then assert !exists(event_create_button) And screenshot() - And click(lao_enter_manually_submit_button) - Then waitFor(event_create_button) - * organizer.stop() - Then screenshot() diff --git a/tests/karate/src/test/java/fe/features/wallet.feature b/tests/karate/src/test/java/fe/features/wallet.feature index b4a1cec942..438f4c3465 100644 --- a/tests/karate/src/test/java/fe/features/wallet.feature +++ b/tests/karate/src/test/java/fe/features/wallet.feature @@ -4,18 +4,18 @@ Feature: Wallet @name=open_app Scenario: Open the app for the first time and see the wallet seed - Given call read(PLATFORM_FEATURES) { name: "#(OPEN_APP)" } + Given call read(PLATFORM_FEATURE) { name: "#(OPEN_APP)" } When match text(wallet_seed_wallet_text) == "#regex ^([a-z]+\\s){11}[a-z]+$" Then screenshot() @name=wallet_create Scenario: Create a new wallet - Given call read(PLATFORM_FEATURES) { name: "#(CREATE_NEW_WALLET)" } + Given call read(PLATFORM_FEATURE) { name: "#(CREATE_NEW_WALLET)" } When waitFor(lao_join_button) Then screenshot() @name=wallet_restore Scenario: Restore a wallet - Given call read(PLATFORM_FEATURES) {name: "#(RESTORE_WALLET)", params: { seed: 'present guilt frost screen fabric rotate citizen decide have message chat hood' } } + Given call read(PLATFORM_FEATURE) {name: "#(RESTORE_WALLET)", params: { seed: 'present guilt frost screen fabric rotate citizen decide have message chat hood' } } When waitFor(lao_join_button) Then screenshot() diff --git a/tests/karate/src/test/java/fe/utils/android.feature b/tests/karate/src/test/java/fe/utils/android.feature index a4702d43b9..f9a4389cdc 100644 --- a/tests/karate/src/test/java/fe/utils/android.feature +++ b/tests/karate/src/test/java/fe/utils/android.feature @@ -39,3 +39,8 @@ Feature: android page object Given call read('android.feature@name=open_app') When input(wallet_restore_input, params.seed) Then click(wallet_restore_button) + + @name=lao_join + Scenario: + # Not implemented yet + * assert false diff --git a/tests/karate/src/test/java/fe/utils/constants.feature b/tests/karate/src/test/java/fe/utils/constants.feature index 19a2f25c66..a9e4c00eb4 100644 --- a/tests/karate/src/test/java/fe/utils/constants.feature +++ b/tests/karate/src/test/java/fe/utils/constants.feature @@ -1,7 +1,8 @@ @ignore @report=false Feature: Constants Scenario: Creates constants that will be used by other features - * def PLATFORM_FEATURES = 'classpath:fe/utils/platform.feature' + * def PLATFORM_FEATURE = 'classpath:fe/utils/platform.feature' + * def MOCK_CLIENT_FEATURE = 'classpath:fe/utils/mock_client.feature' * def OPEN_APP = 'open_app' * def CREATE_NEW_WALLET = 'create_new_wallet' * def RESTORE_WALLET = 'restore_wallet' diff --git a/tests/karate/src/test/java/fe/utils/mock_client.feature b/tests/karate/src/test/java/fe/utils/mock_client.feature index 305b5bb763..593d5d63fc 100644 --- a/tests/karate/src/test/java/fe/utils/mock_client.feature +++ b/tests/karate/src/test/java/fe/utils/mock_client.feature @@ -2,7 +2,8 @@ Feature: Mock Client Scenario: Creates mock clients that can connect to a server as a frontend or server - * def create_client = + * def mockClients = [] + * def createMockClient = """ function(){ var MockClient = Java.type('be.utils.MockClient') @@ -10,39 +11,12 @@ Feature: Mock Client return mockFrontend } """ - - * def create_lao = + * def stopAllMockClients = """ - function(client, lao){ - const request = { - "object": "lao", - "action": "create", - "id": lao.id, - "name": lao.name, - "creation": lao.creation, - "organizer": lao.organizerPk, - "witnesses": lao.witnesses - }; - organizer.publish(request, "/root"); - organizer.getBackendResponse(request) - organizer.send({ - "method": "subscribe", - "id": 2, - "params": { - "channel": lao.channel, - }, - "jsonrpc": "2.0" - }) - - organizer.takeTimeout(1000) - organizer.send( { - "method": "catchup", - "id": 5, - "params": { - "channel": lao.channel, - }, - "jsonrpc": "2.0" - }) - organizer.takeTimeout(1000) + function(){ + for (var i = 0; i < mockClients.length; i++) { + mockClients[i].close(); + } } """ + * configure afterScenario = stopAllMockClients diff --git a/tests/karate/src/test/java/fe/utils/web.feature b/tests/karate/src/test/java/fe/utils/web.feature index 55ff7fe253..d77a23d619 100644 --- a/tests/karate/src/test/java/fe/utils/web.feature +++ b/tests/karate/src/test/java/fe/utils/web.feature @@ -23,6 +23,7 @@ Feature: web page object # Event screen * def event_create_button = "[data-testid='create_event_selector']" + * def event_title = "{}Events" @name=open_app Scenario: @@ -44,3 +45,12 @@ Feature: web page object Then input(wallet_restore_input, params.seed) Then click(wallet_restore_wallet_button) + @name=lao_join + Scenario: + Given call read('web.feature@name=create_new_wallet') + When waitFor(lao_join_button).click() + And waitFor(lao_enter_manually_button).click() + And waitFor(lao_enter_manually_server_input).clear().input(serverURL) + And waitFor(lao_enter_manually_lao_input).clear().input(params.lao.id) + And click(lao_enter_manually_submit_button) + Then waitFor(event_title) From 1335595f0f827b32e5dadd99b82d57f3c6fd3f55 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Mon, 15 Apr 2024 01:11:45 +0200 Subject: [PATCH 07/11] Refactor frontend tests --- tests/karate/src/test/java/fe/features/lao.feature | 9 ++++----- tests/karate/src/test/java/fe/utils/android.feature | 8 ++++---- tests/karate/src/test/java/fe/utils/constants.feature | 5 +++++ .../karate/src/test/java/fe/utils/mock_client.feature | 2 +- tests/karate/src/test/java/fe/utils/web.feature | 10 +++++----- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/tests/karate/src/test/java/fe/features/lao.feature b/tests/karate/src/test/java/fe/features/lao.feature index 2f3c2d429f..20fc65cd3e 100644 --- a/tests/karate/src/test/java/fe/features/lao.feature +++ b/tests/karate/src/test/java/fe/features/lao.feature @@ -1,16 +1,15 @@ Feature: LAO Background: - Given call read('classpath:fe/utils/mock_client.feature') - + * call read('classpath:fe/utils/constants.feature') + * call read(MOCK_CLIENT_FEATURE) @name=lao_create Scenario: Create a new LAO - Given call read('classpath:fe/utils/platform.feature') { name: 'create_new_wallet' } + Given call read(PLATFORM_FEATURE) { name: '#(CREATE_NEW_WALLET)' } And def organization_name = 'My test organization' When waitFor(lao_create_button).click() And waitFor(lao_organization_name_input).input(organization_name) And waitFor(lao_server_url_input).clear().input(serverURL) - And screenshot() And click(lao_launch_button) Then waitFor(event_create_button) Then screenshot() @@ -19,6 +18,6 @@ Feature: LAO Scenario: Manually connect to an existing LAO Given def organizer = createMockClient() And def lao = organizer.createLao() - When call read('classpath:fe/utils/platform.feature') { name: 'lao_join', params: { lao: '#(lao)' } } + When call read(PLATFORM_FEATURE) { name: '#(JOIN_LAO)', params: { lao: '#(lao)' } } Then assert !exists(event_create_button) And screenshot() diff --git a/tests/karate/src/test/java/fe/utils/android.feature b/tests/karate/src/test/java/fe/utils/android.feature index f9a4389cdc..68fc6e7a89 100644 --- a/tests/karate/src/test/java/fe/utils/android.feature +++ b/tests/karate/src/test/java/fe/utils/android.feature @@ -25,20 +25,20 @@ Feature: android page object @name=open_app Scenario: Given driver webDriverOptions - Then waitFor(wallet_button_empty_ok).click() + When waitFor(wallet_button_empty_ok).click() @name=create_new_wallet Scenario: Given call read('android.feature@name=open_app') When waitFor(wallet_new_wallet_button) - Then click(wallet_new_wallet_button) - Then waitFor(wallet_confirm_new_wallet_button).click() + And click(wallet_new_wallet_button) + And waitFor(wallet_confirm_new_wallet_button).click() @name=restore_wallet Scenario: Given call read('android.feature@name=open_app') When input(wallet_restore_input, params.seed) - Then click(wallet_restore_button) + And click(wallet_restore_button) @name=lao_join Scenario: diff --git a/tests/karate/src/test/java/fe/utils/constants.feature b/tests/karate/src/test/java/fe/utils/constants.feature index a9e4c00eb4..bae23bec27 100644 --- a/tests/karate/src/test/java/fe/utils/constants.feature +++ b/tests/karate/src/test/java/fe/utils/constants.feature @@ -1,8 +1,13 @@ @ignore @report=false Feature: Constants Scenario: Creates constants that will be used by other features + # Features * def PLATFORM_FEATURE = 'classpath:fe/utils/platform.feature' * def MOCK_CLIENT_FEATURE = 'classpath:fe/utils/mock_client.feature' + # Wallet * def OPEN_APP = 'open_app' * def CREATE_NEW_WALLET = 'create_new_wallet' * def RESTORE_WALLET = 'restore_wallet' + # Lao + * def JOIN_LAO = 'lao_join' + * def CREATE_LAO = 'lao_create' diff --git a/tests/karate/src/test/java/fe/utils/mock_client.feature b/tests/karate/src/test/java/fe/utils/mock_client.feature index 593d5d63fc..f40ed7935b 100644 --- a/tests/karate/src/test/java/fe/utils/mock_client.feature +++ b/tests/karate/src/test/java/fe/utils/mock_client.feature @@ -1,7 +1,7 @@ @ignore @report=false Feature: Mock Client - Scenario: Creates mock clients that can connect to a server as a frontend or server + Scenario: Creates mock clients that can connect to a server as a frontend or server. Close the connections after each scenario. * def mockClients = [] * def createMockClient = """ diff --git a/tests/karate/src/test/java/fe/utils/web.feature b/tests/karate/src/test/java/fe/utils/web.feature index d77a23d619..3520c59a3f 100644 --- a/tests/karate/src/test/java/fe/utils/web.feature +++ b/tests/karate/src/test/java/fe/utils/web.feature @@ -28,22 +28,22 @@ Feature: web page object @name=open_app Scenario: Given driver webDriverOptions - Given driver 'about:blank' + And driver 'about:blank' And driver.dimensions = { left: 0, top: 0, width: screenWidth, height: screenHeight } - Then driver frontendURL + When driver frontendURL @name=create_new_wallet Scenario: Given call read('web.feature@name=open_app') When waitFor(wallet_new_wallet_button) - Then click(wallet_new_wallet_button) + And click(wallet_new_wallet_button) @name=restore_wallet Scenario: Given call read('web.feature@name=open_app') When waitFor(wallet_goto_restore_wallet_button).click() - Then input(wallet_restore_input, params.seed) - Then click(wallet_restore_wallet_button) + And input(wallet_restore_input, params.seed) + And click(wallet_restore_wallet_button) @name=lao_join Scenario: From 07342ca9444aae73ec34ab16390dfdd04cd38507 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Mon, 15 Apr 2024 01:25:34 +0200 Subject: [PATCH 08/11] Karate move models and some utils to common --- .../src/test/java/be/features/utils/constants.feature | 2 +- .../test/java/be/features/utils/mockClient.feature | 4 ++-- .../karate/src/test/java/be/utils/JsonConverter.java | 1 + .../src/test/java/be/utils/JsonConverterTest.java | 1 + .../src/test/java/{be => common}/model/Election.java | 6 +++--- .../java/{be => common}/model/ElectionQuestion.java | 2 +- .../src/test/java/{be => common}/model/KeyPair.java | 2 +- .../src/test/java/{be => common}/model/Lao.java | 4 ++-- .../src/test/java/{be => common}/model/PlainVote.java | 2 +- .../src/test/java/{be => common}/model/RollCall.java | 4 ++-- .../test/java/{be => common}/model/Transaction.java | 4 ++-- .../test/java/common/net/MultiMsgWebSocketClient.java | 4 ++-- .../src/test/java/{be => common}/utils/Hash.java | 2 +- .../test/java/{be => common}/utils/MockClient.java | 4 ++-- .../test/java/{be => common}/utils/RandomUtils.java | 11 +++++------ .../karate/src/test/java/fe/utils/mock_client.feature | 2 +- 16 files changed, 28 insertions(+), 27 deletions(-) rename tests/karate/src/test/java/{be => common}/model/Election.java (98%) rename tests/karate/src/test/java/{be => common}/model/ElectionQuestion.java (98%) rename tests/karate/src/test/java/{be => common}/model/KeyPair.java (98%) rename tests/karate/src/test/java/{be => common}/model/Lao.java (97%) rename tests/karate/src/test/java/{be => common}/model/PlainVote.java (96%) rename tests/karate/src/test/java/{be => common}/model/RollCall.java (99%) rename tests/karate/src/test/java/{be => common}/model/Transaction.java (99%) rename tests/karate/src/test/java/{be => common}/utils/Hash.java (98%) rename tests/karate/src/test/java/{be => common}/utils/MockClient.java (99%) rename tests/karate/src/test/java/{be => common}/utils/RandomUtils.java (96%) diff --git a/tests/karate/src/test/java/be/features/utils/constants.feature b/tests/karate/src/test/java/be/features/utils/constants.feature index eec410170d..f9a3a47da6 100644 --- a/tests/karate/src/test/java/be/features/utils/constants.feature +++ b/tests/karate/src/test/java/be/features/utils/constants.feature @@ -11,7 +11,7 @@ Feature: Constants * def ELECTION_RESULTS = {"object": "election", "action": "result"} * def rootChannel = '/root' - * def random = Java.type('be.utils.RandomUtils') + * def random = Java.type('common.utils.RandomUtils') # Paths to util features * def utilsPath = 'classpath:be/features/utils/' diff --git a/tests/karate/src/test/java/be/features/utils/mockClient.feature b/tests/karate/src/test/java/be/features/utils/mockClient.feature index 8926ed4b3a..71badd5520 100644 --- a/tests/karate/src/test/java/be/features/utils/mockClient.feature +++ b/tests/karate/src/test/java/be/features/utils/mockClient.feature @@ -6,7 +6,7 @@ Feature: Mock Client * def createMockFrontend = """ function(){ - var MockClient = Java.type('be.utils.MockClient') + var MockClient = Java.type('common.utils.MockClient') var mockFrontend = new MockClient(frontendWsURL) mockClients.push(mockFrontend) return mockFrontend @@ -15,7 +15,7 @@ Feature: Mock Client * def createMockBackend = """ function(){ - var MockClient = Java.type('be.utils.MockClient') + var MockClient = Java.type('common.utils.MockClient') var mockBackend = new MockClient(backendWsURL) mockClients.push(mockBackend) return mockBackend diff --git a/tests/karate/src/test/java/be/utils/JsonConverter.java b/tests/karate/src/test/java/be/utils/JsonConverter.java index 65eb6d6c11..a2715fb059 100644 --- a/tests/karate/src/test/java/be/utils/JsonConverter.java +++ b/tests/karate/src/test/java/be/utils/JsonConverter.java @@ -4,6 +4,7 @@ import com.google.crypto.tink.subtle.Ed25519Sign; import com.intuit.karate.Json; import common.utils.Base64Utils; +import common.utils.Hash; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; diff --git a/tests/karate/src/test/java/be/utils/JsonConverterTest.java b/tests/karate/src/test/java/be/utils/JsonConverterTest.java index 549d47826d..c84219624f 100644 --- a/tests/karate/src/test/java/be/utils/JsonConverterTest.java +++ b/tests/karate/src/test/java/be/utils/JsonConverterTest.java @@ -2,6 +2,7 @@ import com.intuit.karate.Json; import common.utils.Base64Utils; +import common.utils.Hash; import org.junit.jupiter.api.Test; import java.security.GeneralSecurityException; diff --git a/tests/karate/src/test/java/be/model/Election.java b/tests/karate/src/test/java/common/model/Election.java similarity index 98% rename from tests/karate/src/test/java/be/model/Election.java rename to tests/karate/src/test/java/common/model/Election.java index e9c33aea16..812260d6cb 100644 --- a/tests/karate/src/test/java/be/model/Election.java +++ b/tests/karate/src/test/java/common/model/Election.java @@ -1,7 +1,7 @@ -package be.model; +package common.model; -import be.utils.Hash; -import be.utils.RandomUtils; +import common.utils.Hash; +import common.utils.RandomUtils; import java.time.Instant; import java.util.*; diff --git a/tests/karate/src/test/java/be/model/ElectionQuestion.java b/tests/karate/src/test/java/common/model/ElectionQuestion.java similarity index 98% rename from tests/karate/src/test/java/be/model/ElectionQuestion.java rename to tests/karate/src/test/java/common/model/ElectionQuestion.java index 1fc216f9e5..59fded6562 100644 --- a/tests/karate/src/test/java/be/model/ElectionQuestion.java +++ b/tests/karate/src/test/java/common/model/ElectionQuestion.java @@ -1,4 +1,4 @@ -package be.model; +package common.model; import java.util.List; diff --git a/tests/karate/src/test/java/be/model/KeyPair.java b/tests/karate/src/test/java/common/model/KeyPair.java similarity index 98% rename from tests/karate/src/test/java/be/model/KeyPair.java rename to tests/karate/src/test/java/common/model/KeyPair.java index 76d2b0f4f2..6f14895d68 100644 --- a/tests/karate/src/test/java/be/model/KeyPair.java +++ b/tests/karate/src/test/java/common/model/KeyPair.java @@ -1,4 +1,4 @@ -package be.model; +package common.model; import common.utils.Base64Utils; import karate.com.linecorp.armeria.internal.shaded.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; diff --git a/tests/karate/src/test/java/be/model/Lao.java b/tests/karate/src/test/java/common/model/Lao.java similarity index 97% rename from tests/karate/src/test/java/be/model/Lao.java rename to tests/karate/src/test/java/common/model/Lao.java index 1dbaf10fb5..625de7ca2b 100644 --- a/tests/karate/src/test/java/be/model/Lao.java +++ b/tests/karate/src/test/java/common/model/Lao.java @@ -1,6 +1,6 @@ -package be.model; +package common.model; -import be.utils.Hash; +import common.utils.Hash; import java.util.ArrayList; import java.util.List; diff --git a/tests/karate/src/test/java/be/model/PlainVote.java b/tests/karate/src/test/java/common/model/PlainVote.java similarity index 96% rename from tests/karate/src/test/java/be/model/PlainVote.java rename to tests/karate/src/test/java/common/model/PlainVote.java index 12df731f1e..07a20c4647 100644 --- a/tests/karate/src/test/java/be/model/PlainVote.java +++ b/tests/karate/src/test/java/common/model/PlainVote.java @@ -1,4 +1,4 @@ -package be.model; +package common.model; /** Simplified version of a non-encrypted vote for one question, used to generate valid vote data. */ public class PlainVote { diff --git a/tests/karate/src/test/java/be/model/RollCall.java b/tests/karate/src/test/java/common/model/RollCall.java similarity index 99% rename from tests/karate/src/test/java/be/model/RollCall.java rename to tests/karate/src/test/java/common/model/RollCall.java index 0875ad7f2c..b7a1812e97 100644 --- a/tests/karate/src/test/java/be/model/RollCall.java +++ b/tests/karate/src/test/java/common/model/RollCall.java @@ -1,6 +1,6 @@ -package be.model; +package common.model; -import be.utils.Hash; +import common.utils.Hash; import java.time.Instant; import java.util.ArrayList; diff --git a/tests/karate/src/test/java/be/model/Transaction.java b/tests/karate/src/test/java/common/model/Transaction.java similarity index 99% rename from tests/karate/src/test/java/be/model/Transaction.java rename to tests/karate/src/test/java/common/model/Transaction.java index d2ff17d37d..a2a0981efa 100644 --- a/tests/karate/src/test/java/be/model/Transaction.java +++ b/tests/karate/src/test/java/common/model/Transaction.java @@ -1,6 +1,6 @@ -package be.model; +package common.model; -import be.utils.Hash; +import common.utils.Hash; import com.google.crypto.tink.PublicKeySign; import com.google.crypto.tink.subtle.Ed25519Sign; import common.utils.Base64Utils; diff --git a/tests/karate/src/test/java/common/net/MultiMsgWebSocketClient.java b/tests/karate/src/test/java/common/net/MultiMsgWebSocketClient.java index 2a649ef688..a69df37257 100644 --- a/tests/karate/src/test/java/common/net/MultiMsgWebSocketClient.java +++ b/tests/karate/src/test/java/common/net/MultiMsgWebSocketClient.java @@ -1,8 +1,8 @@ package common.net; import be.utils.JsonConverter; -import be.model.KeyPair; -import be.utils.RandomUtils; +import common.model.KeyPair; +import common.utils.RandomUtils; import com.intuit.karate.Json; import com.intuit.karate.Logger; import com.intuit.karate.http.WebSocketClient; diff --git a/tests/karate/src/test/java/be/utils/Hash.java b/tests/karate/src/test/java/common/utils/Hash.java similarity index 98% rename from tests/karate/src/test/java/be/utils/Hash.java rename to tests/karate/src/test/java/common/utils/Hash.java index 001c5fa5d9..46b73dd8e2 100644 --- a/tests/karate/src/test/java/be/utils/Hash.java +++ b/tests/karate/src/test/java/common/utils/Hash.java @@ -1,4 +1,4 @@ -package be.utils; +package common.utils; import common.utils.Base64Utils; diff --git a/tests/karate/src/test/java/be/utils/MockClient.java b/tests/karate/src/test/java/common/utils/MockClient.java similarity index 99% rename from tests/karate/src/test/java/be/utils/MockClient.java rename to tests/karate/src/test/java/common/utils/MockClient.java index ddce2a1d97..247c7a7c3f 100644 --- a/tests/karate/src/test/java/be/utils/MockClient.java +++ b/tests/karate/src/test/java/common/utils/MockClient.java @@ -1,6 +1,6 @@ -package be.utils; +package common.utils; -import be.model.*; +import common.model.*; import com.intuit.karate.http.WebSocketOptions; import com.intuit.karate.Logger; import common.net.MessageQueue; diff --git a/tests/karate/src/test/java/be/utils/RandomUtils.java b/tests/karate/src/test/java/common/utils/RandomUtils.java similarity index 96% rename from tests/karate/src/test/java/be/utils/RandomUtils.java rename to tests/karate/src/test/java/common/utils/RandomUtils.java index e869ab6ef4..6eca0ac72d 100644 --- a/tests/karate/src/test/java/be/utils/RandomUtils.java +++ b/tests/karate/src/test/java/common/utils/RandomUtils.java @@ -1,10 +1,9 @@ -package be.utils; +package common.utils; -import be.model.Election; -import be.model.KeyPair; -import be.model.Lao; -import be.model.RollCall; -import common.utils.Base64Utils; +import common.model.Election; +import common.model.KeyPair; +import common.model.Lao; +import common.model.RollCall; import java.time.Instant; diff --git a/tests/karate/src/test/java/fe/utils/mock_client.feature b/tests/karate/src/test/java/fe/utils/mock_client.feature index f40ed7935b..8925b73db9 100644 --- a/tests/karate/src/test/java/fe/utils/mock_client.feature +++ b/tests/karate/src/test/java/fe/utils/mock_client.feature @@ -6,7 +6,7 @@ Feature: Mock Client * def createMockClient = """ function(){ - var MockClient = Java.type('be.utils.MockClient') + var MockClient = Java.type('common.utils.MockClient') var mockFrontend = new MockClient(serverURL) return mockFrontend } From bbac93f7509ff4646d472b4c3632f319652ce7e5 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Mon, 15 Apr 2024 01:59:36 +0200 Subject: [PATCH 09/11] Update karate README --- tests/karate/docs/README.md | 80 +++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/tests/karate/docs/README.md b/tests/karate/docs/README.md index 2a11c65822..1a2d720827 100644 --- a/tests/karate/docs/README.md +++ b/tests/karate/docs/README.md @@ -11,8 +11,7 @@ To create test cases, we handcraft messages with either valid or invalid message The mock components then send these messages to the component being tested. We then check that the responses the mock components receive are as expected. -## Architecture -### Features and Scenarios +## Features and Scenarios Karate test cases are called scenarios and they are grouped within different feature files. Each feature file tests a different message type (i.e. electionOpen, createRollCall etc.). @@ -24,7 +23,7 @@ For instance, `publish` creates a message of type publish that contains some hig - **Then**: Asserts that the action taken in the 'When' step has the expected outcome. - **And**: Connector that can be used after any of the other keywords. -### Background section +## Background section Code defined in the background section of a feature file runs before each scenario. This is especially useful for: - **Sharing scopes with other features**: The call to `read(classpath: "path/to/feature")` is used to make the current feature share the same scope as the feature that is called. @@ -35,6 +34,7 @@ For instance, reading `mockClient.feature` exposes functions like `createMockFro - **Setting up previous steps necessary for a test**: For instance, before roll call messages can be tested, a LAO needs to be created first. `simpleScenarios.feature` contains many such useful setup steps. +## Backend tests architecture ### Data model To generate valid message data for JSON payloads dynamically, a simplified version of the model is implemented in Java code. Mock components can create valid objects (for instance LAO, RollCall, Elections etc.), that can be used to handcraft messages. @@ -94,6 +94,37 @@ Feature: Create a Roll Call And match organizer.receiveNoMoreResponses() == true ``` +## Frontend tests architecture +### Files +* `utils` + * `constants.feature`: Contains all the necessary constants. Usually called at the beginning of any feature. + * `android.feature` and `web.feature`: Contain platform specific scenarios that will be used by the actual tests. Both files should implement the same scenarios. + * `platform.feature`: A simple wrapper around `android.feature` and `web.feature` that allows you to call the right scenario depending on the current env you are testing for. (i.e. if you set `karate.env=web`, if will call scenarios from `web.feature`) + * `mock_client.feature`: Allows you to create a mock client via `createMockClient`. Automatically stops all clients after each scenario. +* `features`: The actual tests + +### Example: Lao join +```gherkin +Feature: LAO + Background: + # Get the needed utils + * call read('classpath:fe/utils/constants.feature') + * call read(MOCK_CLIENT_FEATURE) + + @name=lao_join + Scenario: Manually connect to an existing LAO + # Use a mock client to create a random lao + Given def organizer = createMockClient() + And def lao = organizer.createLao() + # Call platform specific code with some parameters + # i.e. if karate.env=web, equals to call('classpath:fe/utils/web.feature@name=lao_join') { params: { lao: "#(lao)" } } + When call read(PLATFORM_FEATURE) { name: "#(JOIN_LAO)", params: { lao: "#(lao)" } } + # Actual test: The user should not have access to the button + Then assert !exists(event_create_button) + And screenshot() +``` + + ## First Setup ### All @@ -173,36 +204,15 @@ mvn test -Dkarate.options="--tags @scenarioTagName" With the Karate plugin for IntelliJ, the full tests can also be run directly from inside IDE in the `BackEndTest` class. - -### Android Front-end -Build the application by running `./gradlew assembleDebug` in the corresponding directory. - -Then, launch the Appium server (using the command `appium`) as well as a backend server. - -Finally run the tests. -``` -mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -``` - -In case you have multiple emulators running, you may specify one by avd id. To find the avd id of some emulator, go to the Device Manager (`Tools -> Device Manager`) and follow the steps in the image below. - -![Find avd id Android Studio](./images/android_studio_find_avd_id.png) - -Once you have the avd id of your emulator, you can use the command below to run the tests on this specific emulator. -```shell -mvn test -Dkarate.env=android -Davd= -Dtest=FrontEndTest#fullTest -#e.g. mvn test -Dkarate.env=android -Davd=Galaxy_Note_9_API_29 -Dtest=FrontEndTest#fullTest -``` - ### Web Front-end Build the app with `npm run build-web` in the corresponding directory. Launch the Appium server (with `appium`). -Run the tests. -``` -mvn test -Dkarate.env=web -Dtest=FrontEndTest#fullTest -``` +Finally run the tests: +* All tests: `mvn test -Dkarate.env=web -Dtest=FrontEndTest#fullTest` +* One feature: `mvn test -Dkarate.env=web -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature"` +* One scenario: `mvn test -Dkarate.env=web -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature --tags=@name="` The following options are available (option names must be prefixed by `-D`). | Name | Description | Default | @@ -213,8 +223,8 @@ The following options are available (option names must be prefixed by `-D`). | screenHeight | Height of the browser | 1080 | | serverURL | Client URL of the backend server | 'ws://localhost:9000/client' for the web and 'ws://10.0.2.2:9000/client' for android | -### Web Front-end -Build the app with `npm run build-web` in the corresponding directory. +### Android Front-end +Build the application by running `./gradlew assembleDebug` in the corresponding directory. Launch the Appium server (with `appium`). @@ -223,6 +233,16 @@ Finally run the tests: * One feature: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature"` * One scenario: `mvn test -Dkarate.env=android -Dtest=FrontEndTest#fullTest -Dkarate.options="classpath:fe/features/.feature --tags=@name="` +In case you have multiple emulators running, you may specify one by avd id. To find the avd id of some emulator, go to the Device Manager (`Tools -> Device Manager`) and follow the steps in the image below. + +![Find avd id Android Studio](./images/android_studio_find_avd_id.png) + +Once you have the avd id of your emulator, you can use the command below to run the tests on this specific emulator. +```shell +mvn test -Dkarate.env=android -Davd= -Dtest=FrontEndTest#fullTest +#e.g. mvn test -Dkarate.env=android -Davd=Galaxy_Note_9_API_29 -Dtest=FrontEndTest#fullTest +``` + The following options are available (option names must be prefixed by `-D`). | Name | Description | Default | |--------------|------------------------------------------------|-------------------------------------------| From 166d80974ef352e695ee1e9d67ffeb59b3fc4cb4 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Tue, 16 Apr 2024 16:53:15 +0200 Subject: [PATCH 10/11] Fix karate readme typo --- tests/karate/docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/karate/docs/README.md b/tests/karate/docs/README.md index 1a2d720827..c9bed4f0ca 100644 --- a/tests/karate/docs/README.md +++ b/tests/karate/docs/README.md @@ -99,7 +99,7 @@ Feature: Create a Roll Call * `utils` * `constants.feature`: Contains all the necessary constants. Usually called at the beginning of any feature. * `android.feature` and `web.feature`: Contain platform specific scenarios that will be used by the actual tests. Both files should implement the same scenarios. - * `platform.feature`: A simple wrapper around `android.feature` and `web.feature` that allows you to call the right scenario depending on the current env you are testing for. (i.e. if you set `karate.env=web`, if will call scenarios from `web.feature`) + * `platform.feature`: A simple wrapper around `android.feature` and `web.feature` that allows you to call the right scenario depending on the current env you are testing for. (i.e. if you set `karate.env=web`, it will call scenarios from `web.feature`) * `mock_client.feature`: Allows you to create a mock client via `createMockClient`. Automatically stops all clients after each scenario. * `features`: The actual tests From 3475bb794739c8ef1348c1f32568f5bd89d55127 Mon Sep 17 00:00:00 2001 From: Brice Theurillat Date: Tue, 16 Apr 2024 16:53:55 +0200 Subject: [PATCH 11/11] Update karate readme gherkin bloc of codes --- tests/karate/docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/karate/docs/README.md b/tests/karate/docs/README.md index c9bed4f0ca..2d0b417ce0 100644 --- a/tests/karate/docs/README.md +++ b/tests/karate/docs/README.md @@ -59,7 +59,7 @@ This class provides the functions to create model data for LAOs, roll calls, ele For instance, here the created organizer and LAO are passed to the `createLaoScenario`. - The name tag `@createRollCall1` is used to call individual scenarios on the command line, see [Running the Tests](#running-the-tests) -``` +```gherkin Feature: Create a Roll Call Background: