typescriptwebdriver-ioavaspectron

How do I implement Typescript webdriverio for the SpectronClient?


Spectron is a node.js framework for automating Electron apps. I'm using Spectron along with AVA and Typescript to do automated Integration Testing. I'm using AVA's suggest method for making the test's context typesafe but I'm not able to figure out how to get typesafety on the Spectron's client property which is a webdriverio client. I'm only able to see a few properties which the Spectron typescript definition file has provided and this is causing typescript transpile errors.

These are the errors I'm getting:

src/pages/drive-shell.ts(7,34): error TS2339: Property 'waitForVisible' does not exist on type 'SpectronClient'.
src/pages/login.ts(7,34): error TS2339: Property 'waitForVisible' does not exist on type 'SpectronClient'.
src/pages/login.ts(11,21): error TS2339: Property 'setValue' does not exist on type 'SpectronClient'.
src/pages/login.ts(12,21): error TS2339: Property 'setValue' does not exist on type 'SpectronClient'.
src/pages/login.ts(13,21): error TS2339: Property 'click' does not exist on type 'SpectronClient'.

Solution

  • I actually solved this as I was typing up the question but figured since I did some searching and couldn't find any solutions I thought I might answer my own question in order to help others.

    I needed to get the typings for webdriver io

    npm i -S @types/webdriverio
    

    and then I imported that type into my login.ts script and use that as the SpectronClient

    import * as WebdriverIO from 'webdriverio';
    export class Login {
        constructor(private client: WebdriverIO.Client<void>) { }
    
        public async waitForPageToLoad() {
            return await this.client.waitForVisible('#username');
        }
    
        public login(username: string, password: string) {
            this.client.setValue('#username', username);
            this.client.setValue('#Password', password);
            this.client.click('#login');
        }
    }
    

    and here is my full test.ts test script

    import * as ava from 'ava';
    import { Application } from 'spectron';
    import { Login } from './pages/login';
    import { Settings } from './settings';
    
    function contextualize<T>(getContext: () => Promise<T>): ava.RegisterContextual<T> {
        ava.test.beforeEach(async (t) => {
            Object.assign(t.context, await getContext());
        });
        return ava.test;
    }
    const test = contextualize(async () => {
        const app = new Application({
            path: '../electron.exe',
            args: ['../app/index.html'],
        });
        await app.start();
        return { app };
    });
    
    test.afterEach.always(async (t) => await t.context.app.stop());
    
    test('can login', async (t) => {
        const login = new Login(t.context.app.client);
        await login.waitForPageToLoad();
        login.login(Settings.username, Settings.password);
    });