TypeScript icon, indicating that this package has built-in type declarations

10.2.1 • Public • Published


Automated Functional Testing (AFT) package providing Selenium-based SeleniumComponent extends UiComponent class for use with POM-based UI testing strategies as well as UiSessionGeneratorPlugin implementations for connecting to Selenium via a Grid or Locally.


> npm i aft-ui-selenium

Page Object Model (POM)

the POM is a standard design pattern used in UI and layout testing. AFT-UI-SELENIUM supports this model via Components where the Component class is an object extending from SeleniumComponent and is responsible for interacting with the UI in a structured way. For example:


The above would use a POM design like:

Session - Selenium.WebDriver

  • Page Facet - SeleniumComponent
    • logo element - WebElement
    • Breadcrumbs Facet - SeleniumComponent
      • breadcrumb links - WebElement[]
    • avatar element - WebElement
    • Nav Facet - SeleniumComponent
      • nav elements - WebElement[]
    • Tabs Facet - SeleniumComponent
      • Tab Facet 1 - SeleniumComponent
      • Tab Facet 2 - SeleniumComponent
        • Table Facet - SeleniumComponent
          • header elements - WebElement[]
          • cell elements - WebElement[]
      • Tab Facet 3 - SeleniumComponent
    • media element - WebElement


  • grid-session-generator-plugin: a Selenium Grid plugin used to initiate UI sessions with an existing Selenium Grid. NOTE: this will not startup a new Grid and instead expects that your Grid is already running
  • local-session-generator-plugin: a Selenium WebDriver plugin used to initiate UI sessions with specific browser drivers (i.e. ChromeDriver, GeckoDriver, etc.). NOTE: if using the LocalSessionGeneratorPlugin you may also need to include npm package references to your Browser Driver package such as ChromeDriver

Creating your own Components for use in testing

Take the following as an example of how one could interact with the following page

Step 1: create the Page Component

 * represents the login page object containing widgets encapsulating
 * the functionality of the website
export class HerokuLoginPage extends SeleniumComponent {
    /* the locator can also be specified in options */
    override get locator(): Locator { return By.css('html'); }
    /* components contained in this page */
    private get content() { return this.getComponent(HerokuContentComponent); }
    private get messages() { return this.getComponent(HerokuMessagesComponent); }
    async navigateTo(): Promise<void> {
        await this.driver.navigate().to('');
    /* action functions */
    async login(user: string, pass: string): Promise<void> {
        await this.content.login(user, pass);
    async hasMessage(): Promise<boolean> {
        return await this.messages.hasMessage();
    async getMessage(): Promise<string> {
        return await this.messages.getMessage();

Step 2: create the content and messages Facets

 * represents the content of the login page including the 
 * username and password fields and the login button
export class HerokuContentComponent extends SeleniumComponent {
    readonly locator: Locator ="content");
     * get Component's root element (`root`) using
     * the Component.locator and then call 
     * `root.findElement("username"))` from that
    private get usernameInput() { return this.getRoot().then(r => r.findElement("username"))); }
    private get passwordInput() { return this.getRoot().then(r => r.findElement("password"))); }
    private get loginButton() { return this.getRoot().then(r => r.findElement(By.css("button.radius"))); }
    /* action functions */
    async login(user: string, pass: string): Promise<void> {
        await this.usernameInput.then(input => input.sendKeys(user));
        await this.passwordInput.then(input => input.sendKeys(pass));
        return await this.clickLoginButton();
    async clickLoginButton(): Promise<void> {
        await this.loginButton.then(button =>;
 * represents the results message content shown on successful 
 * or failed login.
export class HerokuMessagesComponent extends SeleniumComponent {
    readonly locator: Locator ="flash-messages");
    private get message() { return this.getRoot().then(r => r.findElement("flash")); }
    /* action functions */
    async hasMessage(): Promise<boolean> {
        return await this.message
            .then((message) => {
                return message !== undefined;
            }).catch((err: Error) => {
                return false;
    async getMessage(): Promise<string> {
        if (await this.hasMessage()) {
            return await this.message.then(m => m.getText());
        return null;

Step 3: use them to interact with the web application

// jasmine test using `aft-jasmine-reporter` package
describe('SeleniumVerifier', () => {
    it('[C3456][C2345][C1234] can access websites using AFT and UiComponents', async () => {
        const aft = new AftTest();
        await aft.verify(async (v: SeleniumVerifier) => {
            const loginPage: HerokuLoginPage = v.getComponent(HerokuLoginPage);
            await v.reporter.step('navigate to LoginPage...');
            await loginPage.navigateTo();
            await v.reporter.step('login');
            await loginPage.login("tomsmith", "SuperSecretPassword!");
            await v.reporter.step('wait for message to appear...')
            await retry(() => loginPage.hasMessage())
                .until((res) => res === true)
                .withMaxDuration(20000); // 20 seconds
            await v.reporter.step('get message...');
            return await loginPage.getMessage();
        }, SeleniumVerifier).returns("You logged into a secure area!");

aftconfig.json keys and values supported by aft-ui-selenium package

this package does not support any additional configuration. see aft-ui for values relevant in the UiSessionConfig

Package Sidebar


npm i aft-ui-selenium

Weekly Downloads






Unpacked Size

144 kB

Total Files


Last publish


  • bicarbon8