From f52dbfe401b80445c17349569c4cf15823eb2384 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 15:55:09 +0100 Subject: [PATCH 1/9] Updating readme files --- .../rn-tester-e2e/README-addTestAndExecute.md | 11 +++++++++-- .../README-describedAllFoldersAndFiles.md | 16 ++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/rn-tester-e2e/README-addTestAndExecute.md b/packages/rn-tester-e2e/README-addTestAndExecute.md index d18f2eb2075aee..58c74731131e40 100644 --- a/packages/rn-tester-e2e/README-addTestAndExecute.md +++ b/packages/rn-tester-e2e/README-addTestAndExecute.md @@ -2,8 +2,8 @@ 1. Create a feature file `(rn-tester-e2e/test/features)` - GivenWhenThen Gherkin syntax 2. **OPTIONAL -** Create a screen object or extend the existing one (depends on the test scope) - `rn-tester-e2e/test/screenObjects` - map screen elements for iOS and Android -3. Create a step file `(rn-tester-e2e/test/steps)` - import used screen objects, create execution code of GivenWhenThen steps from feature file -4. Create a runner file `(rn-tester-e2e/test/runners)` - import steps from step3 and create test scenarios +3. **OPTIONAL -** Add another common step in `rn-tester-e2e/test/common_steps/common.steps.js` +4. Create a runner file `(rn-tester-e2e/test/runners)` - import steps and screen objects from point 2 and 3. Create test scenarios 5. Update `(rn-tester-e2e/e2e-config.js)` with proper cababilities of your emulator # How to execute a test @@ -16,7 +16,14 @@ or 2. Open second terminal -> navigate to the react-native/packages/rn-tester-e2e -> MAKE SURE YOUR APPIUM HAS UIAUTOMATOR2 AND XCUITEST INSTALLED! type +>npm install appium@2.0.0-beta.40 -g + +>appium driver install uiautomator2 + +>appium driver install xcuitest + >appium --base-path /wd/hub + 3. Open third terminal -> navigate to the react-native/packages/rn-tester-e2e -> run all tests by typing >npm run ios diff --git a/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md b/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md index dc8df2a6fa2727..863264fd99b040 100644 --- a/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md +++ b/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md @@ -1,24 +1,21 @@ # Description of all folders and files in rn-tester-e2e # folders 🗂 -## common_steps 📁 -One function (step) per file. Common, reusable steps should be added there +## common_steps 🪜 +Common steps reusable between different features files ## features 🥒 Cucumber feature files. GivenWhenThen Gherkin syntax. One feature per screen/functionality ## helpers 🧑🏻‍🚒 -Utils file with generic, simple steps +Utils file with generic, simple actions and methods ## runners 🏃🏽‍♀️ -Runner file which combines feature file and steps file. Runner file imports steps file and declares step functions in the same order as in the feature file (FUNCTION STEP LOGIC IS NOT IMPLEMENTED HERE!) +Runner file which combines feature file and steps file. Runner file imports steps file and declares step functions in the same order as in the feature file ## screenObjects 📱 Screen object files based on Page Object Pattern. One file defines all neccessary elements to interact with. These elements are defined as screen class variables, they are used by the steps file -## steps 🪜 -Steps file imports screen object (with the same name). Step files define one screen per one file. Step file defines actions which can be performed on this specific page - # root files 📄 ## e2e-config.js Android and iOS emulator/physical device configuration, process.env.E2E_device global variable is defined there - it can be used across the whole rn-tester-e2e directory @@ -27,4 +24,7 @@ Android and iOS emulator/physical device configuration, process.env.E2E_device g Global jest config setup - such as timeout, test runner path ## jest.setup.js -Jest and wdio setup file \ No newline at end of file +Jest and wdio setup file + +## package.json +all external dependecies and project parameters \ No newline at end of file From 1d6c99b3e772ad5b748c4c703b813844f29d4a82 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 15:55:31 +0100 Subject: [PATCH 2/9] Updating android config --- packages/rn-tester-e2e/e2e-config.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/rn-tester-e2e/e2e-config.js b/packages/rn-tester-e2e/e2e-config.js index 334244960b1d72..f3670a3e649141 100644 --- a/packages/rn-tester-e2e/e2e-config.js +++ b/packages/rn-tester-e2e/e2e-config.js @@ -4,21 +4,21 @@ const path = require('path'); let capabilities; const android = { - platformName: 'Android', - platformVersion: '13.0', - deviceName: 'Pixel 6 API 33', - app: path.join(process.cwd(), '/apps/rn-tester.apk'), - automationName: 'UiAutomator2', - newCommandTimeout: 240, + 'platformName': 'Android', + 'appium:platformVersion': '12.0', + 'appium:deviceName': 'Pixel_3a_API_33_arm64-v8a', + 'appium:app': path.join(process.cwd(), '/apps/RNTester.apk'), + 'appium:automationName': 'uiautomator2', + // 'appium:newCommandTimeout': 240, }; const ios = { 'platformName': 'iOS', - 'appium:platformVersion': '16.0', - 'appium:deviceName': 'iPhone 14 Pro Max', + 'appium:platformVersion': '15.2', + 'appium:deviceName': 'iPhone 13', //bundleId: 'org.reactjs.native.example.TestForE2E', 'appium:automationName': 'XCUITest', - 'appium:app': path.join(process.cwd(), '/apps/rn-tester.app'), + 'appium:app': path.join(process.cwd(), '/apps/RNTester.app'), }; if (!process.env.E2E_DEVICE) { From f9cce01e74dd16e1efe80337c4b9dd7108d894d2 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 15:56:01 +0100 Subject: [PATCH 3/9] Adding common steps file --- .../test/common_steps/common.steps.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 packages/rn-tester-e2e/test/common_steps/common.steps.js diff --git a/packages/rn-tester-e2e/test/common_steps/common.steps.js b/packages/rn-tester-e2e/test/common_steps/common.steps.js new file mode 100644 index 00000000000000..38280d1ccd072b --- /dev/null +++ b/packages/rn-tester-e2e/test/common_steps/common.steps.js @@ -0,0 +1,14 @@ +import { driver } from '../../jest.setup.js'; + +// Common steps reusable between different features +export const userIsOnMainScreen = (given) => { + given('User is on the main screen', async () => { + await driver.pause(2000); + }); +}; + +export const clickOkButton = (given) => { + given('User clicks on the OK button', async () => { + await driver.pause(2000); + }); +}; From f2ef9160403027a73ce1c43ed19a0a3b8cb1bcd3 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 15:56:43 +0100 Subject: [PATCH 4/9] Removing unnecessary files --- .../common_steps/givenUserOnMainPage.steps.js | 7 --- .../test/steps/buttonComponentScreen.steps.js | 52 ------------------- 2 files changed, 59 deletions(-) delete mode 100644 packages/rn-tester-e2e/test/common_steps/givenUserOnMainPage.steps.js delete mode 100644 packages/rn-tester-e2e/test/steps/buttonComponentScreen.steps.js diff --git a/packages/rn-tester-e2e/test/common_steps/givenUserOnMainPage.steps.js b/packages/rn-tester-e2e/test/common_steps/givenUserOnMainPage.steps.js deleted file mode 100644 index dc4d6f9699e79d..00000000000000 --- a/packages/rn-tester-e2e/test/common_steps/givenUserOnMainPage.steps.js +++ /dev/null @@ -1,7 +0,0 @@ -import { driver } from '../../jest.setup.js'; - -export const givenUserOnMainPage = (given) => { - given('User is on the main screen', async () => { - await driver.pause(2000); - }); -}; diff --git a/packages/rn-tester-e2e/test/steps/buttonComponentScreen.steps.js b/packages/rn-tester-e2e/test/steps/buttonComponentScreen.steps.js deleted file mode 100644 index 90e9f2cb8e654c..00000000000000 --- a/packages/rn-tester-e2e/test/steps/buttonComponentScreen.steps.js +++ /dev/null @@ -1,52 +0,0 @@ -import componentsScreen from '../screenObjects/components.screen.js'; -import buttonComponentScreen from '../screenObjects/buttonComponent.screen.js'; -import { expect } from '@jest/globals'; - -export const thenVerifyThatTheButtonComponentIsDisplayed = (then) => { - then('Verify that the Button component is displayed', async () => { - expect(await componentsScreen.checkButtonComponentIsDisplayed()).toBeTruthy(); - }); -}; - -export const whenUserClicksOnTheButtonComponent = (when) => { - when('User clicks on the Button component', async () => { - await componentsScreen.clickButtonComponent(); - }); -}; - -export const thenVerifyThatTheButtonHeaderIsDisplayed = (then) => { - then(/^Verify that the "(.*)" header is displayed$/, async (headerScreenName) => { - expect(await buttonComponentScreen.checkButtonsScreenIsDisplayed()).toContain(headerScreenName); - }); -}; - -export const whenUserClicksOnTheCancelApplicationButton = (when) => { - when('User clicks on the Cancel Application button', async () => { - await buttonComponentScreen.clickCancelApplication(); - }); -}; - -export const thenVerifyAlertBoxHasText = (then) => { - then(/^Verify that the cancel|submit alert box has text: "(.*)"$/, async (alertBoxType, alertBoxText) => { - switch (alertBoxType) { - case 'cancel': - expect(await buttonComponentScreen.getCancelAlertText()).toContain(alertBoxText); - break; - case 'submit': - expect(await buttonComponentScreen.getSubmitAlertText()).toContain(alertBoxText); - break; - } - }); -}; - -export const whenUserClicksOnTheOKButton = (when) => { - when('User clicks on the OK button', async () => { - await buttonComponentScreen.clickOkButton(); - }); -}; - -export const whenUserClicksOnTheSubmitApplicationButton = (when) => { - when('User clicks on the Submit Application button', async () => { - await buttonComponentScreen.clickSubmitApplication(); - }); -}; From 2789ed0857532216be8209fea90073ad4031f09c Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 15:57:04 +0100 Subject: [PATCH 5/9] Updating cucumber tests --- .../features/buttonComponentScreen.feature | 6 +- .../runners/buttonComponentScreenRunner.js | 84 ++++++++++++++----- .../screenObjects/buttonComponent.screen.js | 2 +- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/packages/rn-tester-e2e/test/features/buttonComponentScreen.feature b/packages/rn-tester-e2e/test/features/buttonComponentScreen.feature index 18966c1bcd3e27..66993077062274 100644 --- a/packages/rn-tester-e2e/test/features/buttonComponentScreen.feature +++ b/packages/rn-tester-e2e/test/features/buttonComponentScreen.feature @@ -7,8 +7,7 @@ Feature: Button component screen Then Verify that the "Button" header is displayed When User clicks on the Cancel Application button Then Verify that the cancel alert box has text: "Your application has been cancelled!" - When User clicks on the OK button - Then Verify that the "Button" header is displayed + And User clicks on the OK button Scenario: Submit Button Given User is on the main screen @@ -17,5 +16,4 @@ Feature: Button component screen Then Verify that the "Button" header is displayed When User clicks on the Submit Application button Then Verify that the submit alert box has text: "Your application has been submitted!" - When User clicks on the OK button - Then Verify that the "Button" header is displayed \ No newline at end of file + And User clicks on the OK button \ No newline at end of file diff --git a/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js b/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js index af3e4cca53018f..851e6dad1dfa34 100644 --- a/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js +++ b/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js @@ -1,46 +1,90 @@ import { defineFeature, loadFeature } from 'jest-cucumber'; -import { givenUserOnMainPage } from '../common_steps/givenUserOnMainPage.steps'; -import * as steps from '../steps/buttonComponentScreen.steps'; +import { userIsOnMainScreen, clickOkButton } from '../common_steps/common.steps'; +import componentsScreen from '../screenObjects/components.screen.js'; +import buttonComponentScreen from '../screenObjects/buttonComponent.screen.js'; -Object.entries(steps).forEach(([name, exported]) => window[name] = exported); +// Object.entries(steps).forEach(([name, exported]) => window[name] = exported); const feature = loadFeature('test/features/buttonComponentScreen.feature'); +//Methods used more than once in the feature +const buttonComponentShouldBeDisplayed = (then) => { + then('Verify that the Button component is displayed', async () => { + expect(await componentsScreen.checkButtonComponentIsDisplayed()).toBeTruthy(); + }); +}; + +const clickOnButtonComponent = (when) => { + when('User clicks on the Button component', async () => { + await componentsScreen.clickButtonComponent(); + }); +}; + +const buttonHeaderShouldBeDisplayed = (then) => { + then(/^Verify that the "(.*)" header is displayed$/, async (headerScreenName) => { + switch (headerScreenName) { + case 'Button': + expect(await buttonComponentScreen.checkButtonsScreenIsDisplayed()).toBeTruthy(); + break; + // here you can add more similar assertions + default: throw new Error(`Wrong parameter provided. There is no such case as: ${headerScreenName}`) + } + }); +}; + +const alertBoxShouldHaveText = (then) => { + then(/^Verify that the cancel|submit alert box has text: "(.*)"$/, async (alertBoxType, alertBoxText) => { + switch (alertBoxType) { + case 'cancel': + expect(await buttonComponentScreen.getCancelAlertText()).toContain(alertBoxText); + break; + case 'submit': + expect(await buttonComponentScreen.getSubmitAlertText()).toContain(alertBoxText); + break; + } + }); +}; + defineFeature(feature, (test) => { test('Cancel Button', ({ given, when, then }) => { - givenUserOnMainPage(given); + userIsOnMainScreen(given); - thenVerifyThatTheButtonComponentIsDisplayed(then); + buttonComponentShouldBeDisplayed(then); - whenUserClicksOnTheButtonComponent(when); + clickOnButtonComponent(when); - thenVerifyThatTheButtonHeaderIsDisplayed(then); + buttonHeaderShouldBeDisplayed(then); - whenUserClicksOnTheCancelApplicationButton(when); + //method which is used only once in whole feature + when(/^User clicks on the Cancel Application button$/, async () => { + await buttonComponentScreen.clickCancelApplication(); + }) - thenVerifyAlertBoxHasText(then); + alertBoxShouldHaveText(then); - whenUserClicksOnTheOKButton(when); + clickOkButton(when); - thenVerifyThatTheButtonHeaderIsDisplayed(then); + // buttonHeaderShouldBeDisplayed(then); }); test('Submit Button', ({ given, when, then }) => { - givenUserOnMainPage(given); + userIsOnMainScreen(given); - thenVerifyThatTheButtonComponentIsDisplayed(then); + buttonComponentShouldBeDisplayed(then); - whenUserClicksOnTheButtonComponent(when); + clickOnButtonComponent(when); - thenVerifyThatTheButtonHeaderIsDisplayed(then); + buttonHeaderShouldBeDisplayed(then); - whenUserClicksOnTheSubmitApplicationButton(when); + when(/^User clicks on the Submit Application button$/, async () => { + await buttonComponentScreen.clickCancelApplication(); + }) - thenVerifyAlertBoxHasText(then); + alertBoxShouldHaveText(then); - whenUserClicksOnTheOKButton(when); + clickOkButton(when); - thenVerifyThatTheButtonHeaderIsDisplayed(then); + // buttonHeaderShouldBeDisplayed(then); }); - }); +}); diff --git a/packages/rn-tester-e2e/test/screenObjects/buttonComponent.screen.js b/packages/rn-tester-e2e/test/screenObjects/buttonComponent.screen.js index 3cbce504e2f191..383e5186b988c7 100644 --- a/packages/rn-tester-e2e/test/screenObjects/buttonComponent.screen.js +++ b/packages/rn-tester-e2e/test/screenObjects/buttonComponent.screen.js @@ -40,7 +40,7 @@ class ButtonComponentScreen { async checkButtonsScreenIsDisplayed() { - return await Utils.getElementText(this.buttonScreenElement); + return await Utils.checkElementExistence(this.buttonScreenElement); } async clickSubmitApplication() { From 3ebe2004ba9d8a2de47524ccfe749cfe6880b236 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 16:37:18 +0100 Subject: [PATCH 6/9] github-actions fixes --- .../test/runners/buttonComponentScreenRunner.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js b/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js index 851e6dad1dfa34..d08e8ccc61d0cc 100644 --- a/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js +++ b/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js @@ -26,7 +26,7 @@ const buttonHeaderShouldBeDisplayed = (then) => { expect(await buttonComponentScreen.checkButtonsScreenIsDisplayed()).toBeTruthy(); break; // here you can add more similar assertions - default: throw new Error(`Wrong parameter provided. There is no such case as: ${headerScreenName}`) + default: throw new Error(`Wrong parameter provided. There is no such case as: ${headerScreenName}`); } }); }; @@ -58,7 +58,7 @@ defineFeature(feature, (test) => { //method which is used only once in whole feature when(/^User clicks on the Cancel Application button$/, async () => { await buttonComponentScreen.clickCancelApplication(); - }) + }); alertBoxShouldHaveText(then); @@ -79,7 +79,7 @@ defineFeature(feature, (test) => { when(/^User clicks on the Submit Application button$/, async () => { await buttonComponentScreen.clickCancelApplication(); - }) + }); alertBoxShouldHaveText(then); From de053126cc9ebcb2442954a1915b089c8881acfb Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Tue, 10 Jan 2023 16:45:41 +0100 Subject: [PATCH 7/9] removing commented lines --- .../rn-tester-e2e/test/runners/buttonComponentScreenRunner.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js b/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js index d08e8ccc61d0cc..3da267c415a57c 100644 --- a/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js +++ b/packages/rn-tester-e2e/test/runners/buttonComponentScreenRunner.js @@ -63,8 +63,6 @@ defineFeature(feature, (test) => { alertBoxShouldHaveText(then); clickOkButton(when); - - // buttonHeaderShouldBeDisplayed(then); }); test('Submit Button', ({ given, when, then }) => { @@ -84,7 +82,5 @@ defineFeature(feature, (test) => { alertBoxShouldHaveText(then); clickOkButton(when); - - // buttonHeaderShouldBeDisplayed(then); }); }); From 97d6045f283a4966881124578eb0ce33d1628c18 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Thu, 12 Jan 2023 14:41:37 +0100 Subject: [PATCH 8/9] Removing some user specific values --- packages/rn-tester-e2e/e2e-config.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/rn-tester-e2e/e2e-config.js b/packages/rn-tester-e2e/e2e-config.js index f3670a3e649141..7225d988bafe3c 100644 --- a/packages/rn-tester-e2e/e2e-config.js +++ b/packages/rn-tester-e2e/e2e-config.js @@ -5,17 +5,17 @@ let capabilities; const android = { 'platformName': 'Android', - 'appium:platformVersion': '12.0', - 'appium:deviceName': 'Pixel_3a_API_33_arm64-v8a', + 'appium:platformVersion': '', + 'appium:deviceName': '', 'appium:app': path.join(process.cwd(), '/apps/RNTester.apk'), 'appium:automationName': 'uiautomator2', - // 'appium:newCommandTimeout': 240, + 'appium:newCommandTimeout': 240, }; const ios = { 'platformName': 'iOS', - 'appium:platformVersion': '15.2', - 'appium:deviceName': 'iPhone 13', + 'appium:platformVersion': '', + 'appium:deviceName': '', //bundleId: 'org.reactjs.native.example.TestForE2E', 'appium:automationName': 'XCUITest', 'appium:app': path.join(process.cwd(), '/apps/RNTester.app'), From be4415dfa41cd2fd24dcd86bd14cf8ee225e9182 Mon Sep 17 00:00:00 2001 From: adrianorszulik Date: Thu, 12 Jan 2023 14:52:03 +0100 Subject: [PATCH 9/9] Updating typos in readme --- packages/rn-tester-e2e/README-addTestAndExecute.md | 2 +- packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rn-tester-e2e/README-addTestAndExecute.md b/packages/rn-tester-e2e/README-addTestAndExecute.md index 58c74731131e40..aac2ef3afed6a5 100644 --- a/packages/rn-tester-e2e/README-addTestAndExecute.md +++ b/packages/rn-tester-e2e/README-addTestAndExecute.md @@ -4,7 +4,7 @@ 2. **OPTIONAL -** Create a screen object or extend the existing one (depends on the test scope) - `rn-tester-e2e/test/screenObjects` - map screen elements for iOS and Android 3. **OPTIONAL -** Add another common step in `rn-tester-e2e/test/common_steps/common.steps.js` 4. Create a runner file `(rn-tester-e2e/test/runners)` - import steps and screen objects from point 2 and 3. Create test scenarios -5. Update `(rn-tester-e2e/e2e-config.js)` with proper cababilities of your emulator +5. Update `(rn-tester-e2e/e2e-config.js)` with proper capabilities of your emulator # How to execute a test 1. Open new Terminal -> navigate to the react-native path -> open Metro by typing diff --git a/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md b/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md index 863264fd99b040..d09ce554ae8266 100644 --- a/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md +++ b/packages/rn-tester-e2e/README-describedAllFoldersAndFiles.md @@ -14,7 +14,7 @@ Utils file with generic, simple actions and methods Runner file which combines feature file and steps file. Runner file imports steps file and declares step functions in the same order as in the feature file ## screenObjects 📱 -Screen object files based on Page Object Pattern. One file defines all neccessary elements to interact with. These elements are defined as screen class variables, they are used by the steps file +Screen object files based on Page Object Pattern. One file defines all necessary elements to interact with. These elements are defined as screen class variables, they are used by the steps file # root files 📄 ## e2e-config.js @@ -27,4 +27,4 @@ Global jest config setup - such as timeout, test runner path Jest and wdio setup file ## package.json -all external dependecies and project parameters \ No newline at end of file +all external dependencies and project parameters \ No newline at end of file