Adding MacOS E2E Testing (#1233)
* Yarn * Merge * Fixing repo * Update package * Merge * Removing change file * Tests are running and succeeding, but the import still isn't working. I need to figure out how to import Platform from RN to choose the selector in BasePage * Can't get WDIO to compile TS * Updating WDIO to 6.5.0 * Updating Babel to 6.5.0 and integrating babel config. This should work, but it doesn't * Making mac specific files * Adding macos specific testing specs+page objects * Fixing FocusZone spec for MacOS * Reverting babel files back to original. The change did not work as I expected. * Removing babel dependencies, not needed anymore * Updating babel * Nit changes * Nit comments and removing unnecessary properties * Nit comment * Updating file name+import * Nit changes to WebDriver macos config * Adding MacOS E2E testing to CI pipeline * Change files * Updating file extensions of Windows specific files * Removing Mac2 driver dependency from Win32/Windows package * Removing unneeded package-locl files * Fixing Appium logs * Removing unnecessary dep from webdriver config * Removing dep * Removing dep * Publishing MacOS build artifacts for CI * testing ci * Removing unnecessary step in CI Pipeline * Updating Mac webdriver config file to take screenshots when test fails * Testing CI * Nit fix * Reverting previous change * Macos doesn't have browser.maximize funtionality * Adding create a file functionality for reports * Testing CI Pipeline - Seeing what directories are in /macos/ after E2E Test runs * List contents of errorShots * Reading contents of CI * Testing CI * Testing CI * Finding applications folder * Tesing CI for correct path * Testing * Test * Testing CI * Download tccutil command line tool * Adding xcode to accessibility app permissions * Updating download * Attempting to disable SIP * Removing unnecessary commands from CI * Removing CI changes * Nit styling * Updating MacOS E2E Testubg documentation - How to run the tests locally * Updating yarn.lock * Nit: Spelling
This commit is contained in:
Родитель
f7f98071b2
Коммит
f293bf1103
|
@ -7,16 +7,16 @@ steps:
|
|||
# Copy Appium reports to FluentTesterDump
|
||||
- task: CopyFiles@2
|
||||
inputs:
|
||||
sourceFolder: $(Build.SourcesDirectory)\apps\${{parameters.platform}}\reports\
|
||||
targetFolder: $(Build.StagingDirectory)\E2E_${{parameters.applicationType}}_Dump
|
||||
sourceFolder: $(Build.SourcesDirectory)/apps/${{parameters.platform}}/reports/
|
||||
targetFolder: $(Build.StagingDirectory)/E2E_${{parameters.applicationType}}_Dump
|
||||
displayName: "Copy Reports"
|
||||
condition: and (succeededOrFailed(), eq(${{parameters.buildArtifacts}}, 'success'))
|
||||
|
||||
# Copy errorShots to FluentTesterDump
|
||||
- task: CopyFiles@2
|
||||
inputs:
|
||||
sourceFolder: $(Build.SourcesDirectory)\apps\${{parameters.platform}}\errorShots\
|
||||
targetFolder: $(Build.StagingDirectory)\E2E_${{parameters.applicationType}}_Dump
|
||||
sourceFolder: $(Build.SourcesDirectory)/apps/${{parameters.platform}}/errorShots/
|
||||
targetFolder: $(Build.StagingDirectory)/E2E_${{parameters.applicationType}}_Dump
|
||||
displayName: "Copy tree dump screenshots"
|
||||
condition: and (succeededOrFailed(), eq(${{parameters.buildArtifacts}}, 'success'))
|
||||
|
||||
|
@ -24,6 +24,6 @@ steps:
|
|||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
artifactName: E2E_${{parameters.applicationType}}_Dump
|
||||
pathtoPublish: $(Build.StagingDirectory)\E2E_${{parameters.applicationType}}_Dump
|
||||
pathtoPublish: $(Build.StagingDirectory)/E2E_${{parameters.applicationType}}_Dump
|
||||
displayName: "Publish Artifact:E2E_${{parameters.applicationType}}_Dump"
|
||||
condition: and (succeededOrFailed(), eq(${{parameters.buildArtifacts}}, 'success'))
|
||||
|
|
|
@ -62,13 +62,14 @@
|
|||
"@types/react": "^17.0.2",
|
||||
"@types/react-native": "^0.64.0",
|
||||
"@uifabricshared/build-native": "^0.1.1",
|
||||
"@wdio/appium-service": "5.18.2",
|
||||
"@wdio/cli": "5.23.0",
|
||||
"@wdio/jasmine-framework": "5.18.6",
|
||||
"@wdio/local-runner": "5.23.0",
|
||||
"@wdio/spec-reporter": "5.22.4",
|
||||
"@wdio/sync": "5.20.1",
|
||||
"appium": "1.17.1",
|
||||
"@wdio/appium-service": "^6.5.0",
|
||||
"@wdio/cli": "^6.5.0",
|
||||
"@wdio/jasmine-framework": "^6.5.0",
|
||||
"@wdio/local-runner": "^6.5.0",
|
||||
"@wdio/spec-reporter": "^6.5.0",
|
||||
"@wdio/sync": "^6.5.0",
|
||||
"appium": "1.20.0",
|
||||
"appium-mac2-driver": "0.14.1",
|
||||
"metro-react-native-babel-preset": "^0.66.2",
|
||||
"react": "17.0.1",
|
||||
"react-native": "^0.64.3",
|
||||
|
@ -81,7 +82,7 @@
|
|||
"ts-node": "^8.10.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"typescript": "3.8.3",
|
||||
"webdriverio": "5.22.4"
|
||||
"webdriverio": "^6.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@office-iss/react-native-win32": "^0.64.8",
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import {
|
||||
BUTTON_TESTPAGE,
|
||||
BUTTON_TEST_COMPONENT,
|
||||
BUTTON_NO_A11Y_LABEL_COMPONENT,
|
||||
HOMEPAGE_BUTTON_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Button/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class ButtonPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(BUTTON_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return BUTTON_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(BUTTON_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _secondaryComponent() {
|
||||
return By(BUTTON_NO_A11Y_LABEL_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_BUTTON_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ButtonPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
BUTTON_NO_A11Y_LABEL_COMPONENT,
|
||||
HOMEPAGE_BUTTON_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Button/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class ButtonPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import ButtonPageObject from '../pages/ButtonPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Button Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Button test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
ButtonPageObject.scrollToComponentButton();
|
||||
ButtonPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToButtonPage();
|
||||
ButtonPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(ButtonPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import ButtonPageObject from '../pages/ButtonPageObject';
|
||||
import { ComponentSelector } from '../../common/BasePage';
|
||||
import { ComponentSelector } from '../../common/BasePage.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT, BUTTON_A11Y_ROLE } from '../../common/consts';
|
||||
import { BUTTON_ACCESSIBILITY_LABEL, BUTTON_TEST_COMPONENT_LABEL } from '../../../FluentTester/TestComponents/Button/consts';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
BUTTONEXPERIMENTAL_NO_A11Y_LABEL_COMPONENT,
|
||||
HOMEPAGE_BUTTON_BUTTONEXPERIMENTAL,
|
||||
} from '../../../FluentTester/TestComponents/ButtonExperimental/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class ButtonExperimentalPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import ButtonExperimentalPageObject from '../pages/ButtonExperimentalPageObject';
|
||||
import { ComponentSelector } from '../../common/BasePage';
|
||||
import { ComponentSelector } from '../../common/BasePage.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT, BUTTON_A11Y_ROLE } from '../../common/consts';
|
||||
import {
|
||||
BUTTONEXPERIMENTAL_ACCESSIBILITY_LABEL,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import {
|
||||
CALLOUT_TESTPAGE,
|
||||
CALLOUT_TEST_COMPONENT,
|
||||
HOMEPAGE_CALLOUT_BUTTON,
|
||||
BUTTON_TO_OPEN_CALLOUT,
|
||||
} from '../../../FluentTester/TestComponents/Callout/consts';
|
||||
import { BasePage, By, COMPONENT_SCROLL_COORDINATES } from '../../common/BasePage.macos';
|
||||
|
||||
class CalloutPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
/**************** UI Element Interaction Methods ******************/
|
||||
/******************************************************************/
|
||||
didCalloutLoad(): boolean {
|
||||
return this._primaryComponent.isDisplayed();
|
||||
}
|
||||
|
||||
/* OVERRIDE: This must scroll to the button that opens the callout, not the callout (since it's not visible on load.) */
|
||||
scrollToTestElement(): void {
|
||||
while (!this._buttonToOpenCallout.isDisplayed()) {
|
||||
driver.touchScroll(COMPONENT_SCROLL_COORDINATES.x, COMPONENT_SCROLL_COORDINATES.y, this._testPage.elementId);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(CALLOUT_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return CALLOUT_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(CALLOUT_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_CALLOUT_BUTTON);
|
||||
}
|
||||
|
||||
get _buttonToOpenCallout() {
|
||||
return By(BUTTON_TO_OPEN_CALLOUT);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CalloutPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
HOMEPAGE_CALLOUT_BUTTON,
|
||||
BUTTON_TO_OPEN_CALLOUT,
|
||||
} from '../../../FluentTester/TestComponents/Callout/consts';
|
||||
import { BasePage, By, COMPONENT_SCROLL_COORDINATES } from '../../common/BasePage';
|
||||
import { BasePage, By, COMPONENT_SCROLL_COORDINATES } from '../../common/BasePage.win';
|
||||
|
||||
class CalloutPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import CalloutPageObject from '../pages/CalloutPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import {
|
||||
CHECKBOX_TESTPAGE,
|
||||
CHECKBOX_TEST_COMPONENT,
|
||||
CHECKBOX_NO_A11Y_LABEL_COMPONENT,
|
||||
HOMEPAGE_CHECKBOX_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Checkbox/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class CheckboxPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
/**************** UI Element Interaction Methods ******************/
|
||||
/******************************************************************/
|
||||
isCheckboxChecked(): boolean {
|
||||
return this._primaryComponent.isSelected();
|
||||
}
|
||||
|
||||
waitForCheckboxUnchecked(timeout?: number): void {
|
||||
browser.waitUntil(
|
||||
() => {
|
||||
return !this.isCheckboxChecked();
|
||||
},
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: 'The onPress() callback for ' + this._pageName + ' did not fire correctly.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(CHECKBOX_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return CHECKBOX_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(CHECKBOX_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _secondaryComponent() {
|
||||
return By(CHECKBOX_NO_A11Y_LABEL_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_CHECKBOX_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new CheckboxPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
CHECKBOX_NO_A11Y_LABEL_COMPONENT,
|
||||
HOMEPAGE_CHECKBOX_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Checkbox/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class CheckboxPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
|
@ -19,9 +19,11 @@ class CheckboxPageObject extends BasePage {
|
|||
() => {
|
||||
return !this.isCheckboxChecked();
|
||||
},
|
||||
timeout ?? this.waitForPageTimeout,
|
||||
'The onPress() callback for ' + this._pageName + ' did not fire correctly.',
|
||||
2000,
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: 'The onPress() callback for ' + this._pageName + ' did not fire correctly.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import CheckboxPageObject from '../pages/CheckboxPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
describe('Checkbox Testing Initialization', () => {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Checkbox test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
CheckboxPageObject.scrollToComponentButton();
|
||||
CheckboxPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToCheckboxPage();
|
||||
CheckboxPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(CheckboxPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import CheckboxPageObject from '../pages/CheckboxPageObject';
|
||||
import { ComponentSelector } from '../../common/BasePage';
|
||||
import { ComponentSelector } from '../../common/BasePage.win';
|
||||
import { CHECKBOX_TEST_COMPONENT_LABEL, CHECKBOX_ACCESSIBILITY_LABEL } from '../../../FluentTester/TestComponents/Checkbox/consts';
|
||||
import { CHECKBOX_A11Y_ROLE, PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
CONTEXTUALMENU_TEST_COMPONENT,
|
||||
HOMEPAGE_CONTEXTUALMENU_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/ContextualMenu/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class ContextualMenuPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import ContextualMenuPageObjectObject from '../pages/ContextualMenuPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
FOCUSTRAPZONE_TEST_COMPONENT,
|
||||
HOMEPAGE_FOCUSTRAPZONE_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/FocusTrapZone/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class FocusTrapZonePageObject extends BasePage {
|
||||
// OVERRIDE: We use isExisting() here instead of isDisplayed() because FocusTrapZone does not have any UI to it, it's simply
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import FocusTrapZonePageObject from '../pages/FocusTrapZonePageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import {
|
||||
FOCUSZONE_TESTPAGE,
|
||||
FOCUSZONE_TEST_COMPONENT,
|
||||
HOMEPAGE_FOCUSZONE_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/FocusZone/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class FocusZonePageObject extends BasePage {
|
||||
// OVERRIDE: We use isExisting() here instead of isDisplayed() because FocusZone does not have any UI to it, it's simply
|
||||
// a wrapper that adds keyboard focus functionality
|
||||
waitForPrimaryElementDisplayed(timeout?: number): void {
|
||||
const errorMsg = 'The FocusZone UI Element did not load correctly. Please see logs.';
|
||||
this.waitForCondition(() => this._primaryComponent.isExisting(), errorMsg, timeout);
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(FOCUSZONE_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return FOCUSZONE_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(FOCUSZONE_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_FOCUSZONE_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new FocusZonePageObject();
|
|
@ -3,7 +3,7 @@ import {
|
|||
FOCUSZONE_TEST_COMPONENT,
|
||||
HOMEPAGE_FOCUSZONE_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/FocusZone/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class FocusZonePageObject extends BasePage {
|
||||
// OVERRIDE: We use isExisting() here instead of isDisplayed() because FocusZone does not have any UI to it, it's simply
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import FocusZonePageObject from '../pages/FocusZonePageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('FocusZone Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to FocusZone test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
FocusZonePageObject.scrollToComponentButton();
|
||||
FocusZonePageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToFocusZonePage();
|
||||
FocusZonePageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(FocusZonePageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import FocusZonePageObject from '../pages/FocusZonePageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import {
|
||||
ICON_TESTPAGE,
|
||||
ICON_TEST_COMPONENT,
|
||||
HOMEPAGE_ICON_BUTTON,
|
||||
ICON_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/Icon/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class IconPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(ICON_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return ICON_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(ICON_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _secondaryComponent() {
|
||||
return By(ICON_NO_A11Y_LABEL_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_ICON_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new IconPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
HOMEPAGE_ICON_BUTTON,
|
||||
ICON_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/Icon/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class IconPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import IconPageObject from '../pages/IconPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Icon Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Icon test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
IconPageObject.scrollToComponentButton();
|
||||
IconPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToIconPage();
|
||||
IconPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(IconPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import IconPageObject from '../pages/IconPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import {
|
||||
LINK_TESTPAGE,
|
||||
LINK_TEST_COMPONENT,
|
||||
HOMEPAGE_LINK_BUTTON,
|
||||
LINK_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/Link/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class LinkPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(LINK_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return LINK_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(LINK_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _secondaryComponent() {
|
||||
return By(LINK_NO_A11Y_LABEL_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_LINK_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new LinkPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
HOMEPAGE_LINK_BUTTON,
|
||||
LINK_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/Link/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class LinkPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import LinkPageObject from '../pages/LinkPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Link Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Link test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
LinkPageObject.scrollToComponentButton();
|
||||
LinkPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToLinkPage();
|
||||
LinkPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(LinkPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import LinkPageObject from '../pages/LinkPageObject';
|
||||
import { ComponentSelector } from '../../common/BasePage';
|
||||
import { ComponentSelector } from '../../common/BasePage.win';
|
||||
import { LINK_ACCESSIBILITY_LABEL } from '../../../FluentTester/TestComponents/Link/consts';
|
||||
import { LINK_A11Y_ROLE, PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
HOMEPAGE_MENU_BUTTON,
|
||||
MENU_BUTTON_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/MenuButton/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class MenuButtonPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import MenuButtonPageObject from '../pages/MenuButtonPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT, MENUBUTTON_A11Y_ROLE } from '../../common/consts';
|
||||
import { MENU_BUTTON_ACCESSIBILITY_LABEL, MENU_BUTTON_TEST_COMPONENT_LABEL } from '../../../FluentTester/TestComponents/MenuButton/consts';
|
||||
import { ComponentSelector } from '../../common/BasePage';
|
||||
import { ComponentSelector } from '../../common/BasePage.win';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('MenuButton Testing Initialization', function () {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { PERSONA_TESTPAGE, PERSONA_TEST_COMPONENT, HOMEPAGE_PERSONA_BUTTON } from '../../../FluentTester/TestComponents/Persona/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class PersonaPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(PERSONA_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return PERSONA_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(PERSONA_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_PERSONA_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new PersonaPageObject();
|
|
@ -1,5 +1,5 @@
|
|||
import { PERSONA_TESTPAGE, PERSONA_TEST_COMPONENT, HOMEPAGE_PERSONA_BUTTON } from '../../../FluentTester/TestComponents/Persona/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class PersonaPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import PersonaPageObject from '../pages/PersonaPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Persona Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Persona test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
PersonaPageObject.scrollToComponentButton();
|
||||
PersonaPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToPersonaPage();
|
||||
PersonaPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(PersonaPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import PersonaPageObject from '../pages/PersonaPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import {
|
||||
PERSONACOIN_TESTPAGE,
|
||||
PERSONACOIN_TEST_COMPONENT,
|
||||
HOMEPAGE_PERSONACOIN_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/PersonaCoin/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class PersonaCoinPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(PERSONACOIN_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return PERSONACOIN_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(PERSONACOIN_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_PERSONACOIN_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new PersonaCoinPageObject();
|
|
@ -3,7 +3,7 @@ import {
|
|||
PERSONACOIN_TEST_COMPONENT,
|
||||
HOMEPAGE_PERSONACOIN_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/PersonaCoin/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class PersonaCoinPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import PersonaCoinPageObject from '../pages/PersonaCoinPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('PersonaCoin Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to PersonaCoin test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
PersonaCoinPageObject.scrollToComponentButton();
|
||||
PersonaCoinPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToPersonaCoinPage();
|
||||
PersonaCoinPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(PersonaCoinPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import PersonaCoinPageObject from '../pages/PersonaCoinPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import {
|
||||
PRESSABLE_TESTPAGE,
|
||||
PRESSABLE_TEST_COMPONENT,
|
||||
HOMEPAGE_PRESSABLE_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Pressable/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class PressablePageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(PRESSABLE_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return PRESSABLE_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(PRESSABLE_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_PRESSABLE_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new PressablePageObject();
|
|
@ -3,7 +3,7 @@ import {
|
|||
PRESSABLE_TEST_COMPONENT,
|
||||
HOMEPAGE_PRESSABLE_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Pressable/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class PressablePageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import PressablePageObject from '../pages/PressablePageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Pressable Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Pressable test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
PressablePageObject.scrollToComponentButton();
|
||||
PressablePageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToPressablePage();
|
||||
PressablePageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(PressablePageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import PressablePageObject from '../pages/PressablePageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
# E2E Testing Overview
|
||||
|
||||
## Prerequisites
|
||||
## Win32/UWP Prerequisites
|
||||
|
||||
- [Node.js](https://nodejs.org/en/download/) - Version 10.19 or higher.
|
||||
- [React Native Windows Development Dependencies](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies)
|
||||
- **NOTE:** Please make sure you grab all of the items listed there and the appropriate versions.
|
||||
- [WinAppDriver](https://github.com/microsoft/WinAppDriver) - Version 1.1
|
||||
- Enable [_Developer Mode_](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) in Windows settings
|
||||
- [Java 1.8](https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html) (Optional) - Used for generating in-depth after-action reports. More information in "Debugging E2E Failures" section below.
|
||||
- [Allure Command-Line](https://www.npmjs.com/package/allure-commandline) (Optional) - Used for creating in-depth reporting.
|
||||
- `npm install -g allure-commandline`
|
||||
|
||||
### UWP Additional Prerequisites
|
||||
|
||||
- [UWP Prerequisites](https://github.com/microsoft/fluentui-react-native/blob/master/apps/windows/README.md)
|
||||
|
||||
## MacOS Prerequisites
|
||||
|
||||
- MacOS 10.15 or later
|
||||
- XCode 12 or later should be installed
|
||||
- XCode Helper app should be enabled for Accessibility access. The app itself is usually found at: _/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/Xcode Helper.app_.
|
||||
|
||||
In order to enable Accessibility access, simply open the parent folder in finder:
|
||||
_open /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/_
|
||||
and drag & drop the **XCode Helper** app to **Security & Privacy -> Privacy -> Accessibility** list of your **System Preferences**. This action must only be done once.
|
||||
|
||||
## E2E Project Structure
|
||||
|
||||
- E2E - The root E2E testing folder containing test components and their respective platform-specific page objects and spec documents.
|
||||
|
@ -46,6 +53,20 @@
|
|||
|
||||
_Note: It could take up to a minute to load the test app with WebDriverIO, don't panic, the tests will run :)_
|
||||
|
||||
## MacOS Steps
|
||||
|
||||
1. Follow step #1 from "Win32 Steps" section above.
|
||||
2. POD Install
|
||||
- C:\repo\fluentui-react-native> `cd apps\macos\src`
|
||||
- C:\repo\fluentui-react-native\apps\macos\src> `pod install`
|
||||
3. Start the server
|
||||
- C:\repo\fluentui-react-native> `cd apps\macos`
|
||||
- C:\repo\fluentui-react-native\apps\macos> `yarn start`
|
||||
4. Open a new command prompt and run the E2E tests
|
||||
- C:\repo\fluentui-react-native\apps\macos> `yarn e2etest`
|
||||
|
||||
_Note: It could take up to a minute to load the test app with WebDriverIO, don't panic, the tests will run :)_
|
||||
|
||||
# Authoring E2E Test
|
||||
|
||||
Testing is split-up on a **per-component** basis. Each component's testing story is made up of two parts - a **Page Object** and a **Spec Document**.
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
import {
|
||||
RADIOGROUP_TESTPAGE,
|
||||
RADIOGROUP_TEST_COMPONENT,
|
||||
RADIOGROUP_NO_A11Y_LABEL_COMPONENT,
|
||||
RADIOBUTTON_TEST_COMPONENT,
|
||||
HOMEPAGE_RADIOGROUP_BUTTON,
|
||||
RADIOBUTTON_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/RadioGroup/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
export const enum RadioButtonSelector {
|
||||
Primary = 0, // this._primaryComponent
|
||||
Secondary, // this._secondaryComponent
|
||||
}
|
||||
|
||||
class RadioGroupPage extends BasePage {
|
||||
/******************************************************************/
|
||||
/**************** UI Element Interaction Methods ******************/
|
||||
/******************************************************************/
|
||||
// Get RadioButton's accessibilityLabel
|
||||
getRBAccessibilityLabel(radioButtonSelector: RadioButtonSelector): string {
|
||||
switch (radioButtonSelector) {
|
||||
case RadioButtonSelector.Primary:
|
||||
return this._radioButton.getAttribute('Name');
|
||||
|
||||
case RadioButtonSelector.Secondary:
|
||||
return this._secondRadioButton.getAttribute('Name');
|
||||
}
|
||||
}
|
||||
|
||||
getRadioButtonAccesibilityRole(): string {
|
||||
return this._radioButton.getAttribute('ControlType');
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(RADIOGROUP_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return RADIOGROUP_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(RADIOGROUP_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _secondaryComponent() {
|
||||
return By(RADIOGROUP_NO_A11Y_LABEL_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_RADIOGROUP_BUTTON);
|
||||
}
|
||||
|
||||
/***************/
|
||||
/* RadioButton *
|
||||
/**************/
|
||||
get _radioButton() {
|
||||
return By(RADIOBUTTON_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _secondRadioButton() {
|
||||
return By(RADIOBUTTON_NO_A11Y_LABEL_COMPONENT);
|
||||
}
|
||||
}
|
||||
|
||||
export default new RadioGroupPage();
|
|
@ -6,7 +6,7 @@ import {
|
|||
HOMEPAGE_RADIOGROUP_BUTTON,
|
||||
RADIOBUTTON_NO_A11Y_LABEL_COMPONENT,
|
||||
} from '../../../FluentTester/TestComponents/RadioGroup/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
export const enum RadioButtonSelector {
|
||||
Primary = 0, // this._primaryComponent
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import RadioGroupPageObject from '../pages/RadioGroupPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('RadioGroup/RadioButton Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to RadioGroup test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
RadioGroupPageObject.scrollToComponentButton();
|
||||
RadioGroupPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToRadioGroupPage();
|
||||
RadioGroupPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(RadioGroupPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import RadioGroupPageObject, { RadioButtonSelector } from '../pages/RadioGroupPageObject.win';
|
||||
import { ComponentSelector } from '../../common/BasePage';
|
||||
import { ComponentSelector } from '../../common/BasePage.win';
|
||||
import { RADIOBUTTON_A11Y_ROLE, RADIOGROUP_A11Y_ROLE, PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
import {
|
||||
RADIOGROUP_ACCESSIBILITY_LABEL,
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import {
|
||||
SEPARATOR_TESTPAGE,
|
||||
SEPARATOR_TEST_COMPONENT,
|
||||
HOMEPAGE_SEPARATOR_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Separator/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class SeparatorPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(SEPARATOR_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return SEPARATOR_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(SEPARATOR_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_SEPARATOR_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new SeparatorPageObject();
|
|
@ -3,7 +3,7 @@ import {
|
|||
SEPARATOR_TEST_COMPONENT,
|
||||
HOMEPAGE_SEPARATOR_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Separator/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class SeparatorPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import SeparatorPageObject from '../pages/SeparatorPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Separator Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Separator test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
SeparatorPageObject.scrollToComponentButton();
|
||||
SeparatorPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToSeparatorPage();
|
||||
SeparatorPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(SeparatorPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import SeparatorPageObject from '../pages/SeparatorPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { SVG_TESTPAGE, SVG_TEST_COMPONENT, HOMEPAGE_SVG_BUTTON } from '../../../FluentTester/TestComponents/Svg/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class SvgPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(SVG_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return SVG_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(SVG_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_SVG_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new SvgPageObject();
|
|
@ -1,5 +1,5 @@
|
|||
import { SVG_TESTPAGE, SVG_TEST_COMPONENT, HOMEPAGE_SVG_BUTTON } from '../../../FluentTester/TestComponents/Svg/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class SvgPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import SvgPageObject from '../pages/SvgPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Svg Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Svg test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
SvgPageObject.scrollToComponentButton();
|
||||
SvgPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToSvgPage();
|
||||
SvgPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(SvgPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import SvgPageObject from '../pages/SvgPageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import {
|
||||
TABS_TESTPAGE,
|
||||
TABS_TEST_COMPONENT,
|
||||
TABS_ITEM_TEST_COMPONENT,
|
||||
HOMEPAGE_TABS_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Tabs/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class TabsPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
/**************** UI Element Interaction Methods ******************/
|
||||
/******************************************************************/
|
||||
getTabItemAccesibilityRole(): string {
|
||||
return this._tabItem.getAttribute('ControlType');
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(TABS_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return TABS_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(TABS_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_TABS_BUTTON);
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* TabItem *
|
||||
/***********/
|
||||
get _tabItem() {
|
||||
return By(TABS_ITEM_TEST_COMPONENT);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TabsPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
TABS_ITEM_TEST_COMPONENT,
|
||||
HOMEPAGE_TABS_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/Tabs/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class TabsPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import TabsPageObject from '../pages/TabsPageObject.macos';
|
||||
import { BOOT_APP_TIMEOUT, PAGE_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Tabs Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Tabs test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
TabsPageObject.scrollToComponentButton();
|
||||
TabsPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToTabsPage();
|
||||
TabsPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(TabsPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import TabsPageObject from '../pages/TabsPageObject.win';
|
||||
import { TAB_A11Y_ROLE, BOOT_APP_TIMEOUT, PAGE_TIMEOUT, TABITEM_A11Y_ROLE } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import {
|
||||
EXPERIMENTAL_TABS_ITEM_TEST_COMPONENT,
|
||||
EXPERIMENTAL_TABS_TESTPAGE,
|
||||
EXPERIMENTAL_TABS_TEST_COMPONENT,
|
||||
HOMEPAGE_EXPERIMENTAL_TABS_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/TabsExperimental/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class ExperimentalTabsPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
/**************** UI Element Interaction Methods ******************/
|
||||
/******************************************************************/
|
||||
getTabItemAccesibilityRole(): string {
|
||||
return this._tabItem.getAttribute('ControlType');
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(EXPERIMENTAL_TABS_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return EXPERIMENTAL_TABS_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(EXPERIMENTAL_TABS_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_EXPERIMENTAL_TABS_BUTTON);
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* TabItem *
|
||||
/***********/
|
||||
get _tabItem() {
|
||||
return By(EXPERIMENTAL_TABS_ITEM_TEST_COMPONENT);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ExperimentalTabsPageObject();
|
|
@ -4,7 +4,7 @@ import {
|
|||
EXPERIMENTAL_TABS_TEST_COMPONENT,
|
||||
HOMEPAGE_EXPERIMENTAL_TABS_BUTTON,
|
||||
} from '../../../FluentTester/TestComponents/TabsExperimental/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class ExperimentalTabsPageObject extends BasePage {
|
||||
/******************************************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import ExperimentalTabsPageObject from '../pages/ExperimentalTabsPageObject.macos';
|
||||
import { BOOT_APP_TIMEOUT, PAGE_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Experimental Tabs Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Experimental Tabs test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
ExperimentalTabsPageObject.scrollToComponentButton();
|
||||
ExperimentalTabsPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToExperimentalTabsPage();
|
||||
ExperimentalTabsPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(ExperimentalTabsPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import ExperimentalTabsPageObject from '../pages/ExperimentalTabsPageObject.win';
|
||||
import { TAB_A11Y_ROLE, TABITEM_A11Y_ROLE, BOOT_APP_TIMEOUT, PAGE_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { TEXT_TESTPAGE, TEXT_TEST_COMPONENT, HOMEPAGE_TEXT_BUTTON } from '../../../FluentTester/TestComponents/Text/consts';
|
||||
import { BasePage, By } from '../../common/BasePage.macos';
|
||||
|
||||
class TextPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
get _testPage() {
|
||||
return By(TEXT_TESTPAGE);
|
||||
}
|
||||
|
||||
get _pageName() {
|
||||
return TEXT_TESTPAGE;
|
||||
}
|
||||
|
||||
get _primaryComponent() {
|
||||
return By(TEXT_TEST_COMPONENT);
|
||||
}
|
||||
|
||||
get _pageButton() {
|
||||
return By(HOMEPAGE_TEXT_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TextPageObject();
|
|
@ -1,5 +1,5 @@
|
|||
import { TEXT_TESTPAGE, TEXT_TEST_COMPONENT, HOMEPAGE_TEXT_BUTTON } from '../../../FluentTester/TestComponents/Text/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class TextPageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage.macos';
|
||||
import TextPageObject from '../pages/TextPageObject.macos';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
// Before testing begins, allow up to 60 seconds for app to open
|
||||
describe('Text Testing Initialization', function () {
|
||||
it('Wait for app load', () => {
|
||||
NavigateAppPage.waitForPageDisplayed(BOOT_APP_TIMEOUT);
|
||||
expect(NavigateAppPage.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Click and navigate to Text test page', () => {
|
||||
/* Scroll to component test page button in scrollview if not already visible*/
|
||||
TextPageObject.scrollToComponentButton();
|
||||
TextPageObject.waitForButtonDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
/* Click on component button to navigate to test page */
|
||||
NavigateAppPage.clickAndGoToTextPage();
|
||||
TextPageObject.waitForPageDisplayed(PAGE_TIMEOUT);
|
||||
|
||||
expect(TextPageObject.isPageLoaded()).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import TextPageObject from '../pages/TextPageObject.win';
|
||||
import { TEXT_A11Y_ROLE, PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { THEME_TESTPAGE, THEME_TEST_COMPONENT, HOMEPAGE_THEME_BUTTON } from '../../../FluentTester/TestComponents/Theme/consts';
|
||||
import { BasePage, By } from '../../common/BasePage';
|
||||
import { BasePage, By } from '../../common/BasePage.win';
|
||||
|
||||
class ThemePageObject extends BasePage {
|
||||
/*****************************************/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NavigateAppPage from '../../common/NavigateAppPage';
|
||||
import NavigateAppPage from '../../common/NavigateAppPage.win';
|
||||
import ThemePageObject from '../pages/ThemePageObject.win';
|
||||
import { PAGE_TIMEOUT, BOOT_APP_TIMEOUT } from '../../common/consts';
|
||||
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
const DUMMY_CHAR = '';
|
||||
export const COMPONENT_SCROLL_COORDINATES = { x: -0, y: -100 }; // These are the offsets. Y is negative because we want the touch to move up (and thus it scrolls down)
|
||||
|
||||
/* Mac-Specific Selector. We use this to get elements on the test page */
|
||||
export function By(identifier: string): WebdriverIO.Element {
|
||||
return $('//*[@identifier="' + identifier + '"]');
|
||||
}
|
||||
|
||||
/* The values in this enum map to the UI components we want to test in our app. We use this to
|
||||
make the communication from our spec document to our page object easier. Please read below to
|
||||
see why we have Primary/Secondary components. */
|
||||
export const enum ComponentSelector {
|
||||
Primary = 0, // this._primaryComponent
|
||||
Secondary, // this._secondaryComponent
|
||||
}
|
||||
|
||||
/****************************** IMPORTANT! PLEASE READ! **************************************************
|
||||
* Every component's page object extends this. We can assume each test page will interact with at least
|
||||
* two UI elements, so we'll add integration for two UI elements in this file (See *Getters* section below).
|
||||
* Every additional UI element that a test page wants to interact with should be handled in that respective
|
||||
* component's page object.
|
||||
*********************************************************************************************************/
|
||||
|
||||
export class BasePage {
|
||||
/******************************************************************/
|
||||
/**************** UI Element Interaction Methods ******************/
|
||||
/******************************************************************/
|
||||
getAccessibilityRole(): string {
|
||||
return this._primaryComponent.getAttribute('ControlType');
|
||||
}
|
||||
|
||||
/* Gets the accessibility label of an UI element given the selector */
|
||||
getAccessibilityLabel(componentSelector: ComponentSelector): string {
|
||||
switch (componentSelector) {
|
||||
case ComponentSelector.Primary:
|
||||
return this._primaryComponent.getAttribute('Name');
|
||||
|
||||
case ComponentSelector.Secondary:
|
||||
return this._secondaryComponent.getAttribute('Name');
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if the test page has loaded. To determine if it's loaded, each test page has a specific UI element we attempt to locate.
|
||||
* If this UI element is located, we know the page as loaded correctly. The UI element we look for is a Text component that contains
|
||||
* the title of the page (this._testPage returns that UI element) */
|
||||
isPageLoaded(): boolean {
|
||||
return this._testPage.isDisplayed();
|
||||
}
|
||||
|
||||
/* Returns true if the test page's button is displayed (the button that navigates to each test page) */
|
||||
isButtonInView(): boolean {
|
||||
return this._pageButton.isDisplayed();
|
||||
}
|
||||
|
||||
/* Scrolls until the desired test page's button is displayed. We use the scroll viewer UI element as the point to start scrolling.
|
||||
* We use a negative number as the Y-coordinate because that enables us to scroll downwards */
|
||||
scrollToComponentButton(): void {
|
||||
if (!this.isButtonInView()) {
|
||||
const scrollViewElement = $('~SCROLLVIEW_TEST_ID');
|
||||
driver.touchScroll(COMPONENT_SCROLL_COORDINATES.x, COMPONENT_SCROLL_COORDINATES.y, scrollViewElement.elementId);
|
||||
}
|
||||
}
|
||||
|
||||
/* Waits for the test page to load. If the test page doesn't load before the timeout, it causes the test to fail. */
|
||||
waitForPageDisplayed(timeout?: number): void {
|
||||
browser.waitUntil(
|
||||
() => {
|
||||
return this.isPageLoaded();
|
||||
},
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: this._pageName + ' did not render correctly. Please see /errorShots for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/* Waits for the test page's button to be displayed. If the button doesn't load before the timeout, it causes the test to fail. */
|
||||
waitForButtonDisplayed(timeout?: number): void {
|
||||
browser.waitUntil(
|
||||
() => {
|
||||
return this.isButtonInView();
|
||||
},
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: 'Could not find the button to navigate to ' + this._pageName + '. Please see /errorShots for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/* Waits for the primary UI test element to be displayed. If the element doesn't load before the timeout, it causes the test to fail. */
|
||||
waitForPrimaryElementDisplayed(timeout?: number): void {
|
||||
browser.waitUntil(
|
||||
() => {
|
||||
return this._primaryComponent.isDisplayed();
|
||||
},
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg:
|
||||
'The primary UI element for testing did not display correctly. Please see /errorShots of the first failed test for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/* Scrolls to the primary UI test element until it is displayed. It uses the ScrollView that encapsulates each test page. */
|
||||
scrollToTestElement(): void {
|
||||
while (!this._primaryComponent.isDisplayed()) {
|
||||
driver.touchScroll(COMPONENT_SCROLL_COORDINATES.x, COMPONENT_SCROLL_COORDINATES.y, $('~ScrollViewAreaForComponents').elementId);
|
||||
}
|
||||
}
|
||||
|
||||
/* A method that allows the caller to pass in a condition. A wrapper for waitUntil(). Once testing becomes more extensive,
|
||||
* this will allow cleaner code within all the Page Objects. */
|
||||
waitForCondition(condition?: () => boolean, errorMsg?: string, timeout?: number): void {
|
||||
browser.waitUntil(
|
||||
() => {
|
||||
return condition();
|
||||
},
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: errorMsg ?? 'Error. Please see /errorShots and logs for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/**************** Getters ****************/
|
||||
/*****************************************/
|
||||
|
||||
/* IMPORTANT:
|
||||
* Each PageObject class that extends this class is expected to override these values.
|
||||
* This is necessary because each page will have different IDs for their respective UI elements.
|
||||
* DUMMY_CHAR is just a placeholder.
|
||||
*/
|
||||
|
||||
// Returns: UI Element
|
||||
// The Text component on each test page containing the title of that page. We can use this to determine if a test page has loaded correctly.
|
||||
get _testPage(): WebdriverIO.Element {
|
||||
return By(DUMMY_CHAR);
|
||||
}
|
||||
|
||||
// Returns: UI Element
|
||||
// The primary UI element used for testing on the given test page.
|
||||
get _primaryComponent(): WebdriverIO.Element {
|
||||
return By(DUMMY_CHAR);
|
||||
}
|
||||
|
||||
// Returns: UI Element
|
||||
// The secondary UI element used for testing on the given test page. Often times, we'll want to set a
|
||||
// prop on one component, and not set it on another to verify certain behaviors. This is why we have this secondary component.
|
||||
get _secondaryComponent(): WebdriverIO.Element {
|
||||
return By(DUMMY_CHAR);
|
||||
}
|
||||
|
||||
// Returns: UI Element
|
||||
// The button that navigates you to the component's test page.
|
||||
get _pageButton(): WebdriverIO.Element {
|
||||
return By(DUMMY_CHAR);
|
||||
}
|
||||
|
||||
// Returns: String
|
||||
// Returns the name of the test page. Useful for error messages (see above).
|
||||
get _pageName(): string {
|
||||
return DUMMY_CHAR;
|
||||
}
|
||||
|
||||
// Default timeout to wait until page is displayed (10s)
|
||||
waitForPageTimeout: number = 15000;
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
const DUMMY_CHAR = '';
|
||||
export const COMPONENT_SCROLL_COORDINATES = { x: -0, y: -100 }; // These are the offsets. Y is negative because we want the touch to move up (and thus it scrolls down)
|
||||
|
||||
export function By(testId: string): WebdriverIO.Element {
|
||||
return $('~' + testId);
|
||||
/* Win32/UWP-Specific Selector. We use this to get elements on the test page */
|
||||
export function By(identifier: string): WebdriverIO.Element {
|
||||
return $('~' + identifier);
|
||||
}
|
||||
|
||||
/* The values in this enum map to the UI components we want to test in our app. We use this to
|
||||
|
@ -66,9 +67,11 @@ export class BasePage {
|
|||
() => {
|
||||
return this.isPageLoaded();
|
||||
},
|
||||
timeout ?? this.waitForPageTimeout,
|
||||
this._pageName + ' did not render correctly. Please see /errorShots of the first failed test for more information.',
|
||||
1000,
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: this._pageName + ' did not render correctly. Please see /errorShots for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -78,11 +81,11 @@ export class BasePage {
|
|||
() => {
|
||||
return this.isButtonInView();
|
||||
},
|
||||
timeout ?? this.waitForPageTimeout,
|
||||
'The button to navigate to the ' +
|
||||
this._pageName +
|
||||
' was not displayed correctly. Please see /errorShots of the first failed test for more information.',
|
||||
1000,
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: 'Could not find the button to navigate to ' + this._pageName + '. Please see /errorShots for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -92,9 +95,12 @@ export class BasePage {
|
|||
() => {
|
||||
return this._primaryComponent.isDisplayed();
|
||||
},
|
||||
timeout ?? this.waitForPageTimeout,
|
||||
'The primary UI element for testing did not display correctly. Please see /errorShots of the first failed test for more information.',
|
||||
1000,
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg:
|
||||
'The primary UI element for testing did not display correctly. Please see /errorShots of the first failed test for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -112,9 +118,11 @@ export class BasePage {
|
|||
() => {
|
||||
return condition();
|
||||
},
|
||||
timeout ?? this.waitForPageTimeout,
|
||||
errorMsg ?? 'Error. Please see /errorShots and logs for more information.',
|
||||
1000,
|
||||
{
|
||||
timeout: timeout ?? this.waitForPageTimeout,
|
||||
timeoutMsg: errorMsg ?? 'Error. Please see /errorShots and logs for more information.',
|
||||
interval: 1000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
import { HOMEPAGE_CHECKBOX_BUTTON } from '../../FluentTester/TestComponents/Checkbox/consts';
|
||||
import { HOMEPAGE_BUTTON_BUTTON } from '../../FluentTester/TestComponents/Button/consts';
|
||||
import { HOMEPAGE_CALLOUT_BUTTON } from '../../FluentTester/TestComponents/Callout/consts';
|
||||
import { HOMEPAGE_CONTEXTUALMENU_BUTTON } from '../../FluentTester/TestComponents/ContextualMenu/consts';
|
||||
import { HOMEPAGE_EXPERIMENTAL_TABS_BUTTON } from '../../FluentTester/TestComponents/TabsExperimental/consts';
|
||||
import { HOMEPAGE_FOCUSTRAPZONE_BUTTON } from '../../FluentTester/TestComponents/FocusTrapZone/consts';
|
||||
import { HOMEPAGE_FOCUSZONE_BUTTON } from '../../FluentTester/TestComponents/FocusZone/consts';
|
||||
import { HOMEPAGE_ICON_BUTTON } from '../../FluentTester/TestComponents/Icon/consts';
|
||||
import { HOMEPAGE_LINK_BUTTON } from '../../FluentTester/TestComponents/Link/consts';
|
||||
import { HOMEPAGE_MENU_BUTTON } from '../../FluentTester/TestComponents/MenuButton/consts';
|
||||
import { HOMEPAGE_PERSONA_BUTTON } from '../../FluentTester/TestComponents/Persona/consts';
|
||||
import { HOMEPAGE_PERSONACOIN_BUTTON } from '../../FluentTester/TestComponents/PersonaCoin/consts';
|
||||
import { HOMEPAGE_PRESSABLE_BUTTON } from '../../FluentTester/TestComponents/Pressable/consts';
|
||||
import { HOMEPAGE_RADIOGROUP_BUTTON } from '../../FluentTester/TestComponents/RadioGroup/consts';
|
||||
import { HOMEPAGE_SEPARATOR_BUTTON } from '../../FluentTester/TestComponents/Separator/consts';
|
||||
import { HOMEPAGE_SVG_BUTTON } from '../../FluentTester/TestComponents/Svg/consts';
|
||||
import { HOMEPAGE_TEXT_BUTTON } from '../../FluentTester/TestComponents/Text/consts';
|
||||
import { HOMEPAGE_TABS_BUTTON } from '../../FluentTester/TestComponents/Tabs/consts';
|
||||
import { HOMEPAGE_THEME_BUTTON } from '../../FluentTester/TestComponents/Theme/consts';
|
||||
import { BASE_TESTPAGE } from '../../FluentTester/TestComponents/Common/consts';
|
||||
import { By, BasePage } from './BasePage.macos';
|
||||
|
||||
class NavigateAppPage extends BasePage {
|
||||
clickAndGoToButtonPage() {
|
||||
this.buttonPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToCalloutPage() {
|
||||
this.calloutPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToCheckboxPage() {
|
||||
this.checkboxPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToContextualMenuPage() {
|
||||
this.contextualMenuPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToFocusTrapZonePage() {
|
||||
this.focusTrapZonePage.click();
|
||||
}
|
||||
|
||||
clickAndGoToFocusZonePage() {
|
||||
this.focusZonePage.click();
|
||||
}
|
||||
|
||||
clickAndGoToIconPage() {
|
||||
this.iconPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToLinkPage() {
|
||||
this.linkPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToMenuButtonPage() {
|
||||
this.menuButtonPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToPersonaPage() {
|
||||
this.personaPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToPersonaCoinPage() {
|
||||
this.personaCoinPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToPressablePage() {
|
||||
this.pressablePage.click();
|
||||
}
|
||||
|
||||
clickAndGoToRadioGroupPage() {
|
||||
this.radioGroupPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToSeparatorPage() {
|
||||
this.separatorPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToSvgPage() {
|
||||
this.svgPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToTextPage() {
|
||||
this.textPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToTabsPage() {
|
||||
this.tabsPage.click();
|
||||
}
|
||||
|
||||
clickAndGoToThemePage() {
|
||||
this.themePage.click();
|
||||
}
|
||||
|
||||
clickAndGoToExperimentalTabsPage() {
|
||||
this.experimentalTabsPage.click();
|
||||
}
|
||||
|
||||
/*
|
||||
** Returns the StealthButton element on the left-hand column that navigates to each page
|
||||
*/
|
||||
|
||||
get _testPage() {
|
||||
return By(BASE_TESTPAGE);
|
||||
}
|
||||
|
||||
private get buttonPage() {
|
||||
return By(HOMEPAGE_BUTTON_BUTTON);
|
||||
}
|
||||
|
||||
private get calloutPage() {
|
||||
return By(HOMEPAGE_CALLOUT_BUTTON);
|
||||
}
|
||||
|
||||
private get checkboxPage() {
|
||||
return By(HOMEPAGE_CHECKBOX_BUTTON);
|
||||
}
|
||||
|
||||
private get contextualMenuPage() {
|
||||
return By(HOMEPAGE_CONTEXTUALMENU_BUTTON);
|
||||
}
|
||||
|
||||
private get focusTrapZonePage() {
|
||||
return By(HOMEPAGE_FOCUSTRAPZONE_BUTTON);
|
||||
}
|
||||
|
||||
private get focusZonePage() {
|
||||
return By(HOMEPAGE_FOCUSZONE_BUTTON);
|
||||
}
|
||||
|
||||
private get iconPage() {
|
||||
return By(HOMEPAGE_ICON_BUTTON);
|
||||
}
|
||||
|
||||
private get linkPage() {
|
||||
return By(HOMEPAGE_LINK_BUTTON);
|
||||
}
|
||||
|
||||
private get menuButtonPage() {
|
||||
return By(HOMEPAGE_MENU_BUTTON);
|
||||
}
|
||||
|
||||
private get personaPage() {
|
||||
return By(HOMEPAGE_PERSONA_BUTTON);
|
||||
}
|
||||
|
||||
private get personaCoinPage() {
|
||||
return By(HOMEPAGE_PERSONACOIN_BUTTON);
|
||||
}
|
||||
|
||||
private get pressablePage() {
|
||||
return By(HOMEPAGE_PRESSABLE_BUTTON);
|
||||
}
|
||||
|
||||
private get radioGroupPage() {
|
||||
return By(HOMEPAGE_RADIOGROUP_BUTTON);
|
||||
}
|
||||
|
||||
private get separatorPage() {
|
||||
return By(HOMEPAGE_SEPARATOR_BUTTON);
|
||||
}
|
||||
|
||||
private get svgPage() {
|
||||
return By(HOMEPAGE_SVG_BUTTON);
|
||||
}
|
||||
|
||||
private get textPage() {
|
||||
return By(HOMEPAGE_TEXT_BUTTON);
|
||||
}
|
||||
|
||||
private get tabsPage() {
|
||||
return By(HOMEPAGE_TABS_BUTTON);
|
||||
}
|
||||
|
||||
private get themePage() {
|
||||
return By(HOMEPAGE_THEME_BUTTON);
|
||||
}
|
||||
|
||||
private get experimentalTabsPage() {
|
||||
return By(HOMEPAGE_EXPERIMENTAL_TABS_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
export default new NavigateAppPage();
|
|
@ -19,7 +19,7 @@ import { HOMEPAGE_TEXT_BUTTON } from '../../FluentTester/TestComponents/Text/con
|
|||
import { HOMEPAGE_TABS_BUTTON } from '../../FluentTester/TestComponents/Tabs/consts';
|
||||
import { HOMEPAGE_THEME_BUTTON } from '../../FluentTester/TestComponents/Theme/consts';
|
||||
import { BASE_TESTPAGE } from '../../FluentTester/TestComponents/Common/consts';
|
||||
import { By, BasePage } from './BasePage';
|
||||
import { By, BasePage } from './BasePage.win';
|
||||
|
||||
class NavigateAppPage extends BasePage {
|
||||
clickAndGoToButtonPage() {
|
|
@ -17,7 +17,8 @@
|
|||
"test": "fluentui-scripts jest",
|
||||
"macos": "react-native run-macos --scheme FluentTester --project-path src",
|
||||
"prettier": "fluentui-scripts prettier",
|
||||
"prettier-fix": "fluentui-scripts prettier --fix true"
|
||||
"prettier-fix": "fluentui-scripts prettier --fix true",
|
||||
"e2etest": "wdio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluentui-react-native/tester": "^0.49.0",
|
||||
|
@ -33,11 +34,22 @@
|
|||
"@rnx-kit/cli": "^0.5.27",
|
||||
"@rnx-kit/metro-config": "^1.2.3",
|
||||
"@uifabricshared/build-native": "^0.1.1",
|
||||
"@wdio/appium-service": "^6.5.0",
|
||||
"@wdio/cli": "^6.5.0",
|
||||
"@wdio/jasmine-framework": "^6.5.0",
|
||||
"@wdio/local-runner": "^6.5.0",
|
||||
"@wdio/spec-reporter": "^6.5.0",
|
||||
"@wdio/sync": "^6.5.0",
|
||||
"appium-mac2-driver": "0.14.1",
|
||||
"metro-config": "^0.66.2",
|
||||
"metro-react-native-babel-preset": "^0.66.2",
|
||||
"react-native-svg-transformer": "^0.14.3",
|
||||
"react-native-test-app": "^0.9.13",
|
||||
"react-test-renderer": "17.0.1"
|
||||
"react-test-renderer": "17.0.1",
|
||||
"ts-node": "^8.10.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"typescript": "3.8.3",
|
||||
"webdriverio": "^6.5.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"*": ["*"],
|
||||
"src/*": ["./src/*"]
|
||||
},
|
||||
"types": ["@wdio/sync", "@wdio/jasmine-framework", "node", "@types/jasmine"]
|
||||
},
|
||||
"include": ["src", "../fluent-tester/src"]
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
const fs = require('fs');
|
||||
|
||||
const defaultWaitForTimeout = 20000;
|
||||
const defaultConnectionRetryTimeout = 20000;
|
||||
const jasmineDefaultTimeout = 45000; // 45 seconds for Jasmine test timeout
|
||||
|
||||
exports.config = {
|
||||
runner: 'local', // Where should your test be launched
|
||||
specs: ['../fluent-tester/src/E2E/Button/specs/*.macos.ts'],
|
||||
exclude: [
|
||||
/* 'path/to/excluded/files' */
|
||||
],
|
||||
|
||||
maxInstances: 30,
|
||||
capabilities: [
|
||||
{
|
||||
maxInstances: 1, // Maximum number of total parallel running workers.
|
||||
platformName: 'mac',
|
||||
automationName: 'Mac2',
|
||||
bundleId: 'com.microsoft.ReactTestApp',
|
||||
},
|
||||
],
|
||||
|
||||
/*
|
||||
** ===================
|
||||
** Test Configurations
|
||||
** ===================
|
||||
** Define all options that are relevant for the WebdriverIO instance here
|
||||
*/
|
||||
|
||||
logLevel: 'info', // Level of logging verbosity: trace | debug | info | warn | error | silent
|
||||
|
||||
// If you only want to run your tests until a specific amount of tests have failed use bail (default is 0 - don't bail, run all tests).
|
||||
bail: 0,
|
||||
waitforTimeout: defaultWaitForTimeout, // Default timeout for all waitForXXX commands.
|
||||
connectionRetryTimeout: defaultConnectionRetryTimeout, // Timeout for any WebDriver request to a driver or grid.
|
||||
connectionRetryCount: 3, // Maximum count of request retries to the Selenium server.
|
||||
|
||||
port: 4723, // default appium port
|
||||
services: [
|
||||
[
|
||||
'appium',
|
||||
{
|
||||
logPath: './reports/',
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
defaultTimeoutInterval: jasmineDefaultTimeout,
|
||||
},
|
||||
|
||||
// The number of times to retry the entire specfile when it fails as a whole.
|
||||
// Adding an extra retry will hopefully reduce the risk of engineers seeing a false-negative
|
||||
specFileRetries: 3,
|
||||
|
||||
reporters: ['spec'],
|
||||
|
||||
/*
|
||||
** ===================
|
||||
** Hooks
|
||||
** ===================
|
||||
** WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
|
||||
** it and to build services around it. You can either apply a single function or an array of
|
||||
** methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
|
||||
** resolved to continue.
|
||||
*/
|
||||
/**
|
||||
* Gets executed once before all workers get launched.
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
*/
|
||||
//onPrepare: function (config, capabilities) {},
|
||||
/**
|
||||
* Gets executed before a worker process is spawned and can be used to initialise specific service
|
||||
* for that worker as well as modify runtime environments in an async fashion.
|
||||
* @param {String} cid capability id (e.g 0-0)
|
||||
* @param {[type]} caps object containing capabilities for session that will be spawn in the worker
|
||||
* @param {[type]} specs specs to be run in the worker process
|
||||
* @param {[type]} args object that will be merged with the main configuration once worker is initialised
|
||||
* @param {[type]} execArgv list of string arguments passed to the worker process
|
||||
*/
|
||||
// onWorkerStart: function (cid, caps, specs, args, execArgv) {
|
||||
// },
|
||||
/**
|
||||
* Gets executed just before initialising the webdriver session and test framework. It allows you
|
||||
* to manipulate configurations depending on the capability or spec.
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that are to be run
|
||||
*/
|
||||
beforeSession: function (/*config, capabilities, specs*/) {
|
||||
fs.mkdirSync('./errorShots', {recursive: true});
|
||||
},
|
||||
/**
|
||||
* Gets executed before test execution begins. At this point you can access to all global
|
||||
* variables like `browser`. It is the perfect place to define custom commands.
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that are to be run
|
||||
*/
|
||||
before: function () {
|
||||
require('ts-node').register({files: true});
|
||||
},
|
||||
/**
|
||||
* Runs before a WebdriverIO command gets executed.
|
||||
* @param {String} commandName hook command name
|
||||
* @param {Array} args arguments that command would receive
|
||||
*/
|
||||
// beforeCommand: function (commandName, args) {
|
||||
// },
|
||||
/**
|
||||
* Hook that gets executed before the suite starts
|
||||
* @param {Object} suite suite details
|
||||
*/
|
||||
// beforeSuite: function (suite) {
|
||||
// },
|
||||
/**
|
||||
* Function to be executed before a test (in Mocha/Jasmine) starts.
|
||||
*/
|
||||
// beforeTest: function (test, context) {
|
||||
// },
|
||||
/**
|
||||
* Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
|
||||
* beforeEach in Mocha)
|
||||
*/
|
||||
// beforeHook: function (test, context) {
|
||||
// },
|
||||
/**
|
||||
* Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
|
||||
* afterEach in Mocha)
|
||||
*/
|
||||
// afterHook: function (test, context, { error, result, duration, passed, retries }) {
|
||||
// },
|
||||
/**
|
||||
* Function to be executed after a test (in Mocha/Jasmine).
|
||||
*/
|
||||
afterTest: function (test, context, results) {
|
||||
// if test passed, ignore, else take and save screenshot. Unless it's the first test that boots the app,
|
||||
// it may be useful to have a screenshot of the app on load.
|
||||
if (results.passed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get current test title and clean it, to use it as file name
|
||||
const fileName = encodeURIComponent(test.description.replace(/\s+/g, '-'));
|
||||
|
||||
// build file path
|
||||
const filePath = './errorShots/' + fileName + '.png';
|
||||
|
||||
// save screenshot
|
||||
browser.saveScreenshot(filePath);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hook that gets executed after the suite has ended
|
||||
* @param {Object} suite suite details
|
||||
*/
|
||||
// afterSuite: function (suite) {
|
||||
// },
|
||||
/**
|
||||
* Runs after a WebdriverIO command gets executed
|
||||
* @param {String} commandName hook command name
|
||||
* @param {Array} args arguments that command would receive
|
||||
* @param {Number} result 0 - command success, 1 - command error
|
||||
* @param {Object} error error object if any
|
||||
*/
|
||||
// afterCommand: function (commandName, args, result, error) {
|
||||
// },
|
||||
/**
|
||||
* Gets executed after all tests are done. You still have access to all global variables from
|
||||
* the test.
|
||||
* @param {Number} result 0 - test pass, 1 - test fail
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that ran
|
||||
*/
|
||||
// after: function (result, capabilities, specs) {
|
||||
// },
|
||||
/**
|
||||
* Gets executed right after terminating the webdriver session.
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {Array.<String>} specs List of spec file paths that ran
|
||||
*/
|
||||
// afterSession: function (config, capabilities, specs) {
|
||||
// },
|
||||
/**
|
||||
* Gets executed after all workers got shut down and the process is about to exit. An error
|
||||
* thrown in the onComplete hook will result in the test run failing.
|
||||
* @param {Object} exitCode 0 - success, 1 - fail
|
||||
* @param {Object} config wdio configuration object
|
||||
* @param {Array.<Object>} capabilities list of capabilities details
|
||||
* @param {<Object>} results object containing test results
|
||||
*/
|
||||
onComplete: function (exitCode, config, capabilities, results) {
|
||||
//console.log('<<< TESTING FINISHED >>>');
|
||||
},
|
||||
/**
|
||||
* Gets executed when a refresh happens.
|
||||
* @param {String} oldSessionId session ID of the old session
|
||||
* @param {String} newSessionId session ID of the new session
|
||||
*/
|
||||
//onReload: function(oldSessionId, newSessionId) {
|
||||
//}
|
||||
};
|
|
@ -45,14 +45,8 @@
|
|||
"@uifabricshared/build-native": "^0.1.1",
|
||||
"@fluentui-react-native/eslint-config-rules": "^0.1.1",
|
||||
"@wdio/allure-reporter": "5.22.4",
|
||||
"@wdio/appium-service": "5.18.2",
|
||||
"@wdio/cli": "5.23.0",
|
||||
"@wdio/jasmine-framework": "5.18.6",
|
||||
"@wdio/local-runner": "5.23.0",
|
||||
"@wdio/spec-reporter": "5.22.4",
|
||||
"@wdio/sync": "5.20.1",
|
||||
"allure-commandline": "2.13.0",
|
||||
"appium": "1.17.1",
|
||||
"appium": "1.20.0",
|
||||
"metro-config": "^0.66.2",
|
||||
"metro-react-native-babel-preset": "^0.66.2",
|
||||
"react-native-svg-transformer": "^0.14.3",
|
||||
|
@ -60,7 +54,13 @@
|
|||
"ts-node": "^8.10.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"typescript": "3.8.3",
|
||||
"webdriverio": "5.22.4"
|
||||
"webdriverio": "^6.5.0",
|
||||
"@wdio/appium-service": "^6.5.0",
|
||||
"@wdio/cli": "^6.5.0",
|
||||
"@wdio/jasmine-framework": "^6.5.0",
|
||||
"@wdio/local-runner": "^6.5.0",
|
||||
"@wdio/spec-reporter": "^6.5.0",
|
||||
"@wdio/sync": "^6.5.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native"
|
||||
|
|
|
@ -45,13 +45,14 @@ exports.config = {
|
|||
connectionRetryCount: 3, // Maximum count of request retries to the Selenium server.
|
||||
|
||||
port: 4723, // default appium port
|
||||
services: ['appium'],
|
||||
appium: {
|
||||
logPath: './reports/',
|
||||
args: {
|
||||
port: '4723',
|
||||
},
|
||||
},
|
||||
services: [
|
||||
[
|
||||
'appium',
|
||||
{
|
||||
logPath: './reports/',
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
|
@ -113,6 +114,7 @@ exports.config = {
|
|||
before: function () {
|
||||
// not needed for Cucumber
|
||||
require('ts-node').register({ files: true });
|
||||
|
||||
browser.maximizeWindow();
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -32,14 +32,8 @@
|
|||
"@types/jasmine": "3.5.10",
|
||||
"@uifabricshared/build-native": "0.1.1",
|
||||
"@wdio/allure-reporter": "5.22.4",
|
||||
"@wdio/appium-service": "5.18.2",
|
||||
"@wdio/cli": "5.23.0",
|
||||
"@wdio/jasmine-framework": "5.18.6",
|
||||
"@wdio/local-runner": "5.23.0",
|
||||
"@wdio/spec-reporter": "5.22.4",
|
||||
"@wdio/sync": "5.20.1",
|
||||
"allure-commandline": "2.13.0",
|
||||
"appium": "1.17.1",
|
||||
"appium": "1.20.0",
|
||||
"metro-config": "^0.66.2",
|
||||
"metro-react-native-babel-preset": "^0.66.2",
|
||||
"react-native-test-app": "^0.9.13",
|
||||
|
@ -48,7 +42,13 @@
|
|||
"ts-node": "^8.10.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"typescript": "3.8.3",
|
||||
"webdriverio": "5.22.4"
|
||||
"webdriverio": "^6.5.0",
|
||||
"@wdio/appium-service": "^6.5.0",
|
||||
"@wdio/cli": "^6.5.0",
|
||||
"@wdio/jasmine-framework": "^6.5.0",
|
||||
"@wdio/local-runner": "^6.5.0",
|
||||
"@wdio/spec-reporter": "^6.5.0",
|
||||
"@wdio/sync": "^6.5.0"
|
||||
},
|
||||
"workspaces": {
|
||||
"nohoist": [
|
||||
|
|
|
@ -50,13 +50,14 @@ exports.config = {
|
|||
connectionRetryCount: 3, // Maximum count of request retries to the Selenium server.
|
||||
|
||||
port: 4723, // default appium port
|
||||
services: ['appium'],
|
||||
appium: {
|
||||
logPath: './reports/',
|
||||
args: {
|
||||
port: '4723',
|
||||
},
|
||||
},
|
||||
services: [
|
||||
[
|
||||
'appium',
|
||||
{
|
||||
logPath: './reports/',
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
|
@ -118,6 +119,7 @@ exports.config = {
|
|||
before: function () {
|
||||
// not needed for Cucumber
|
||||
require('ts-node').register({files: true});
|
||||
|
||||
browser.maximizeWindow();
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "minor",
|
||||
"comment": "Adding MacOS E2E testing to CI pipeline",
|
||||
"packageName": "@fluentui-react-native/tester",
|
||||
"email": "safreibe@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "minor",
|
||||
"comment": "Adding MacOS E2E testing to CI pipeline",
|
||||
"packageName": "@fluentui-react-native/tester-win32",
|
||||
"email": "safreibe@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
1479
yarn.lock
1479
yarn.lock
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче