Automated Functional Testing (AFT) package supporting UI testing in browsers with support for BrowserStack, Sauce Labs and Local Selenium Grid
npm install aft-ui-browsersBrowserFacet extends UUiFacet Plugins and BrowserStack, Sauce Labs and Selenium Grid UiSession Plugins extending the aft-ui package. This enables testing using BrowserStack, Sauce Labs or a Local Selenium Grid for any Browser application tests.
> npm i aft-ui-browsers
UiSession and is responsible for managing the UI container (browser, mobile view, etc.)and the _Facet_ is an object extending from UUiFacet and is responsible for managing logical collections of sub-facets and elements in the UI. For example:
BrowserSession
BrowserFacet
WebElement
BrowserFacet
WebElement[]
WebElement
BrowserFacet
WebElement[]
BrowserFacet
BrowserFacet
BrowserFacet
BrowserFacet
WebElement[]
WebElement[]
BrowserFacet
WebElement
typescript
/**
* represents the login page object containing widgets encapsulating
* the functionality of the website
*/
export class HerokuLoginPage extends BrowserFacet {
/ the locator can also be specified in options /
readonly locator: Locator = By.css('html');
/ facets contained in this page /
private content(): Promise {
return this.getFacet(HerokuContentFacet);
}
private messages(): Promise {
return this.getFacet(HerokuMessagesFacet, {maxWaitMs: 20000});
}
async navigateTo(): Promise {
await this.session.goTo('https://the-internet.herokuapp.com/login');
}
/ action functions /
async login(user: string, pass: string): Promise {
await this.content().then((c) => c.login(user, pass));
}
async hasMessage(): Promise {
return await this.messages().then((m) => m.hasMessage());
}
async getMessage(): Promise {
return await this.messages().then((m) => m.getMessage());
}
}
`
$3
`typescript
/**
* represents the content of the login page including the
* username and password fields and the login button
*/
export class HerokuContentFacet extends BrowserFacet {
readonly locator: Locator = By.id("content");
/**
* function will get the Facet's root element using
* the Facet.locator (By.id("content")) and then will
* call {findElement(By.id("username"))} from that
* `
*
* ...
*
*
*
* ...
*
* `
*/
private async usernameInput(): Promise {
return await this.getElement({locator: By.id("username")});
}
private async passwordInput(): Promise {
return await this.getElement({locator: By.id("password")});
}
private async loginButton(): Promise {
return await this.getElement({locator: By.css("button.radius")});
}
/ action functions /
async login(user: string, pass: string): Promise {
await this.usernameInput().then(input => input.sendKeys(user));
await this.passwordInput().then(input => input.sendKeys(pass));
return await this.clickLoginButton();
}
async clickLoginButton(): Promise {
await this.loginButton().then(button => button.click());
}
}
`
`typescript
/**
* represents the results message content shown on successful
* or failed login.
*/
export class HerokuMessagesFacet extends BrowserFacet {
readonly locator: Locator = By.id("flash-messages");
private async message(): Promise {
return this.getElement({locator: By.id("flash")});
}
/ action functions /
async hasMessage(): Promise {
return await this.message()
.then((message) => {
return message !== undefined;
}).catch((err: Error) => {
return false;
});
}
async getMessage(): Promise {
if (await this.hasMessage()) {
return await this.message().then(m => m.getText());
}
return null;
}
}
`
$3
`typescript
await verifyWithBrowser(async (bv: BrowserVerifier) => {
let loginPage: HerokuLoginPage = await bv.session.getFacet(HerokuLoginPage);
await bv.logMgr.step('navigate to LoginPage...');
await loginPage.navigateTo();
await bv.logMgr.step('login');
await loginPage.login("tomsmith", "SuperSecretPassword!");
await bv.logMgr.step('wait for message to appear...')
await wait.untilTrue(() => loginPage.hasMessage(), 20000);
await bv.logMgr.step('get message...');
return await loginPage.getMessage();
}).withDescription('can access websites using AFT and Page Widgets and Facets')
.and.withTestId('C3456').and.withTestId('C2345').and.withTestId('C1234')
.returns("You logged into a secure area!");
`
aftconfig.json keys and values supported by aft-ui-selenium package
`
{
"BrowserSessionGeneratorManager": {
"uiplatform": "windows_10_chrome",
"plugins": [{
"name": "browserstack-browser-session-generator-plugin",
"searchDirectory": "../node_modules",
"options": {
"user": "%browserstack_user%",
"key": "%browserstack_key%",
"debug": true,
"resolution": "640x480",
"local": false,
"localIdentifier": "abcdefg"
}
}, {
"name": "sauce-labs-browser-session-generator-plugin",
"searchDirectory": "../node_modules",
"options": {
"enabled": false,
"uiplatform": "ios_10_safari_80_iPhone 11",
"username": "%saucelabs_username%",
"accessKey": "%saucelabs_accesskey%",
"resolution": "1024x768",
"tunnel": false,
"tunnelIdentifier": "abcdefgh"
}
}, {
"name": "selenium-grid-session-generator-plugin",
"searchDirectory": "../node_modules",
"options": {
"enabled": false,
"url": "http://127.0.0.1:4444/wd/hub",
"additionalCapabilities": {
"your-custom-key": "your-custom-value"
}
}
}]
}
}
`
- browserstack-browser-session-generator-plugin
- options
- uiplatform - a UiPlatform string used to define what OS and Browser combination is to be generated _(defaults to value specified on BrowserSessionGeneratorManager.uiplatform)_
- url - an alternative url for the grid hub _(only the Selenium Grid plugin requires this value)_
- additionalCapabilities - an object containing keys and values to be used when creating your BrowserStack Session. this can be used to override default capabilities or to add additional ones _(defaults to none)_
- user - [REQUIRED] the BrowserStack username for the account to be used
- key - [REQUIRED] the BrowserStack accesskey for the account to be used
- resolution - a string containing a valid resolution for your BrowserStack session like: 1024x768 _(defaults to no value so BrowserStack will choose)_
- local - a boolean value indicating if sessions should connect via an already running BrowserStack _Local_ VPN _(defaults to false)_
- localIdentifier - a string containing the BrowserStack _Local_ localIdentifier to use when connecting to a _Local_ VPN instance. only required if local is set to true and your _Local_ VPN instance is using a localIdentifier
- debug - a boolean indicating if debug logging is enabled at BrowserStack _(defaults to false)_
- sauce-labs-browser-session-generator-plugin
- options
- uiplatform - a UiPlatform string used to define what OS and Browser combination is to be generated _(defaults to value specified on BrowserSessionGeneratorManager.uiplatform)_
- url - an alternative url for the grid hub _(only the Selenium Grid plugin requires this value)_
- additionalCapabilities - an object containing keys and values to be used when creating your BrowserStack Session. this can be used to override default capabilities or to add additional ones _(defaults to none)_
- username - [REQUIRED] the Sauce Labs username for the account to be used
- accesskey - [REQUIRED] the Sauce Labs accesskey for the account to be used
- resolution - a string containing a valid resolution for your Sauce Labs session like: 1024x768 _(defaults to no value so Sauce Labs will choose)_
- tunnel - a boolean value indicating if sessions should connect via an already running Sauce Labs tunnel VPN _(defaults to false)_
- tunnelIdentifier - a string containing the Sauce Labs tunnelIdentifier to use when connecting to a tunnel VPN instance. only required if tunnel is set to true and your tunnel VPN instance is using a tunnelIdentifier
- selenium-grid-session-generator-plugin
- options
- uiplatform - a UiPlatform string used to define what OS and Browser combination is to be generated _(defaults to value specified on BrowserSessionGeneratorManager.uiplatform)_
- url - an alternative url for the grid hub _(only the Selenium Grid plugin requires this value)_
- additionalCapabilities - an object` containing keys and values to be used when creating your BrowserStack Session. this can be used to override default capabilities or to add additional ones _(defaults to none)_