Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(typescript): add types #79

Merged
merged 1 commit into from
Jan 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ describe('tests with webdriver', function() {
})
```

TypeScript
----------

For the typings related to the changes in the global jasmine variables (e.g.
allowing `it()` blocks to return a promise), we publish the package
`@types/jasminewd2`. If you are writing tests using jasminewd (including
Protractor tests), be sure to include `@types/jasminewd2` in your
`devDependencies`, as these global type modifications are ***not*** bundled with
the `jasminewd2` npm module.

jasminewd also exports one function directly: `init`. Unfortunately, we do not
publish typings for this function. If you call this function directly (e.g. you
are a Protractor dev), you should simply do:

```ts
require('jasminewd2').init(controlFlow);
```

`async` functions / `await`
---------------------------

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"selenium-webdriver": "3.0.1"
},
"devDependencies": {
"@types/jasmine": "^2.5.40",
"@types/node": "^6.0.56",
"@types/selenium-webdriver": "^2.53.38",
"jasmine": "2.4.1",
Expand Down
73 changes: 73 additions & 0 deletions spec/@types_jasminewd2.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// This is jasminewd's internal version of @types/jasminewd2. If you need types
// for jasminewd2, please use @types/jasminewd2 instead

// Type definitions for jasminewd2
// Project https://github.com/angular/jasminewd
// Definitions by: Sammy Jelin <https://github.com/sjelin>

declare function it(expectation: string, assertion?: () => Promise<void>, timeout?: number): void;
declare function fit(expectation: string, assertion?: () => Promise<void>, timeout?: number): void;
declare function xit(expectation: string, assertion?: () => Promise<void>, timeout?: number): void;
declare function beforeEach(action: () => Promise<void>, timeout?: number): void;
declare function afterEach(action: () => Promise<void>, timeout?: number): void;
declare function beforeAll(action: () => Promise<void>, timeout?: number): void;
declare function afterAll(action: () => Promise<void>, timeout?: number): void;

declare namespace jasmine {
// The global `Promise` type is too strict and kinda wrong
interface Promise<T> {
then<U>(onFulfill?: (value: T) => U | Promise<U>, onReject?: (error: any) => U | Promise<U>): Promise<U>;
}

interface Matchers {
toBe(expected: any, expectationFailOutput?: any): Promise<void>;
toEqual(expected: any, expectationFailOutput?: any): Promise<void>;
toMatch(expected: string | RegExp | Promise<string | RegExp>, expectationFailOutput?: any): Promise<void>;
toBeDefined(expectationFailOutput?: any): Promise<void>;
toBeUndefined(expectationFailOutput?: any): Promise<void>;
toBeNull(expectationFailOutput?: any): Promise<void>;
toBeNaN(): Promise<void>;
toBeTruthy(expectationFailOutput?: any): Promise<void>;
toBeFalsy(expectationFailOutput?: any): Promise<void>;
toHaveBeenCalled(): Promise<void>;
toHaveBeenCalledWith(...params: any[]): Promise<void>;
toHaveBeenCalledTimes(expected: number | Promise<number>): Promise<void>;
toContain(expected: any, expectationFailOutput?: any): Promise<void>;
toBeLessThan(expected: number | Promise<number>, expectationFailOutput?: any): Promise<void>;
toBeLessThanOrEqual(expected: number | Promise<number>, expectationFailOutput?: any): Promise<void>;
toBeGreaterThan(expected: number | Promise<number>, expectationFailOutput?: any): Promise<void>;
toBeGreaterThanOrEqual(expected: number | Promise<number>, expectationFailOutput?: any): Promise<void>;
toBeCloseTo(expected: number | Promise<number>, precision?: any, expectationFailOutput?: any): Promise<void>;
toThrow(expected?: any): Promise<void>;
toThrowError(message?: string | RegExp | Promise<string | RegExp>): Promise<void>;
toThrowError(expected?: new (...args: any[]) => Error | Promise<new (...args: any[]) => Error>, message?: string | RegExp | Promise<string | RegExp>): Promise<void>;
}

function addMatchers(matchers: AsyncCustomMatcherFactories): void;

interface Env {
addMatchers(matchers: AsyncCustomMatcherFactories): void;
}

interface Spec {
addMatchers(matchers: AsyncCustomMatcherFactories): void;
}

interface AsyncCustomMatcherFactories {
[index: string]: AsyncCustomMatcherFactory;
}

interface AsyncCustomMatcherFactory {
(util: MatchersUtil, customEqualityTesters: Array<CustomEqualityTester>): AsyncCustomMatcher;
}

interface AsyncCustomMatcher {
compare<T>(actual: T, expected: T): AsyncCustomMatcherResult;
compare(actual: any, expected: any): AsyncCustomMatcherResult;
}

interface AsyncCustomMatcherResult {
pass: boolean | Promise<boolean>;
message?: string;
}
}
16 changes: 3 additions & 13 deletions spec/asyncAwaitAdapterSpec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import {promise as wdpromise, WebElement} from 'selenium-webdriver';
const common = require('./common');

declare function expect(actual: any): any;
declare function describe(description: string, tests: Function): void;
declare function it(description: string, test?: Function, timeout?: number): any;
declare function xit(description: string, test?: Function, timeout?: number): any;
declare function beforeEach(setup: Function): void;
declare function beforeAll(setup: Function): void;
declare function afterEach(setup: Function): void;
declare function afterAll(setup: Function): void;
declare var jasmine;
import {getFakeDriver, getMatchers} from './common.js';

/**
* This file is very similar to adapterSpec.ts, but we use async/await instead
* of the WebDriver Control Flow for synchronization. These tests are desgined
* to work regardless of if the WebDriver Control Flow is disabled.
*/

const fakeDriver = common.getFakeDriver();
const fakeDriver = getFakeDriver();

/* jshint esversion: 6 */
describe('webdriverJS Jasmine adapter plain', function() {
Expand Down Expand Up @@ -54,7 +44,7 @@ describe('webdriverJS Jasmine adapter', function() {
let beforeEachMsg: string;

beforeEach(function() {
jasmine.addMatchers(common.getMatchers());
jasmine.addMatchers(getMatchers());
});

beforeEach(async function() {
Expand Down
16 changes: 3 additions & 13 deletions spec/asyncAwaitErrorSpec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
const common = require('./common');

declare function expect(actual: any): any;
declare function describe(description: string, tests: Function): void;
declare function it(description: string, test?: Function, timeout?: number): any;
declare function xit(description: string, test?: Function, timeout?: number): any;
declare function beforeEach(setup: Function): void;
declare function beforeAll(setup: Function): void;
declare function afterEach(setup: Function): void;
declare function afterAll(setup: Function): void;
declare var jasmine;
import {getFakeDriver, getMatchers} from './common.js';

/**
* This file is very similar to errorSpec.ts, but we use async/await instead of
* the WebDriver Control Flow for synchronization. These tests are desgined to
* work regardless of if the WebDriver Control Flow is disabled.
*/

const fakeDriver = common.getFakeDriver();
const fakeDriver = getFakeDriver();

/* jshint esversion: 6 */
describe('Timeout cases', function() {
Expand All @@ -38,7 +28,7 @@ describe('Timeout cases', function() {

describe('things that should fail', function() {
beforeEach(function() {
jasmine.addMatchers(common.getMatchers());
jasmine.addMatchers(getMatchers());
});

it('should pass errors from done callback', function(done) {
Expand Down
75 changes: 43 additions & 32 deletions spec/common.js → spec/common.ts
Original file line number Diff line number Diff line change
@@ -1,110 +1,110 @@
var webdriver = require('selenium-webdriver');
import {promise as wdpromise, WebElement} from 'selenium-webdriver';

var flow = webdriver.promise.controlFlow();
const flow = wdpromise.controlFlow();
require('../index.js').init(flow);

exports.getFakeDriver = function() {
export function getFakeDriver() {
return {
controlFlow: function() {
return flow;
},
sleep: function(ms) {
sleep: function(ms: number) {
return flow.timeout(ms);
},
setUp: function() {
return flow.execute(function() {
return webdriver.promise.when('setup done');
return wdpromise.when('setup done');
}, 'setUp');
},
getValueA: function() {
return flow.execute(function() {
return webdriver.promise.delayed(500).then(function() {
return webdriver.promise.when('a');
return wdpromise.delayed(500).then(function() {
return wdpromise.when('a');
});
}, 'getValueA');
},
getOtherValueA: function() {
return flow.execute(function() {
return webdriver.promise.when('a');
return wdpromise.when('a');
}, 'getOtherValueA');
},
getValueB: function() {
return flow.execute(function() {
return webdriver.promise.when('b');
return wdpromise.when('b');
}, 'getValueB');
},
getBigNumber: function() {
getBigNumber: function(): wdpromise.Promise<number> {
return flow.execute(function() {
return webdriver.promise.when(1111);
return wdpromise.when(1111);
}, 'getBigNumber');
},
getSmallNumber: function() {
getSmallNumber: function(): wdpromise.Promise<number> {
return flow.execute(function() {
return webdriver.promise.when(11);
return wdpromise.when(11);
}, 'getSmallNumber');
},
getDecimalNumber: function() {
getDecimalNumber: function(): wdpromise.Promise<number> {
return flow.execute(function() {
return webdriver.promise.when(3.14159);
return wdpromise.when(3.14159);
}, 'getDecimalNumber');
},
getDisplayedElement: function() {
return flow.execute(function() {
return webdriver.promise.when({
return wdpromise.when({
isDisplayed: function() {
return webdriver.promise.when(true);
return wdpromise.when(true);
}
});
}, 'getDisplayedElement');
},
getHiddenElement: function() {
return flow.execute(function() {
return webdriver.promise.when({
return wdpromise.when({
isDisplayed: function() {
return webdriver.promise.when(false);
return wdpromise.when(false);
}
});
}, 'getHiddenElement');
},
getValueList: function() {
getValueList: function(): wdpromise.Promise<Array<{getText: () => wdpromise.Promise<string>}>> {
return flow.execute(function() {
return webdriver.promise.when([{
return wdpromise.when([{
getText: function() {
return flow.execute(function() { return webdriver.promise.when('a');});
return flow.execute(function() { return wdpromise.when('a');});
}
}, {
getText: function() {
return flow.execute(function() { return webdriver.promise.when('b');});
return flow.execute(function() { return wdpromise.when('b');});
}
}, {
getText: function() {
return flow.execute(function() { return webdriver.promise.when('c');});
return flow.execute(function() { return wdpromise.when('c');});
}
}, {
getText: function() {
return flow.execute(function() { return webdriver.promise.when('d');});
return flow.execute(function() { return wdpromise.when('d');});
}
}]);
}, 'getValueList');
},
displayedElement: {
isDisplayed: function() {
return webdriver.promise.when(true);
return wdpromise.when(true);
}
},
hiddenElement: {
isDisplayed: function() {
return webdriver.promise.when(false);
return wdpromise.when(false);
}
}
};
};

exports.getMatchers = function() {
export function getMatchers() {
return {
toBeLotsMoreThan: function() {
return {
compare: function(actual, expected) {
compare: function(actual: number, expected: number) {
return {
pass: actual > expected + 100
};
Expand All @@ -114,7 +114,7 @@ exports.getMatchers = function() {
// Example custom matcher returning a promise that resolves to true/false.
toBeDisplayed: function() {
return {
compare: function(actual, expected) {
compare: function(actual: WebElement, expected: void) {
return {
pass: actual.isDisplayed()
};
Expand All @@ -124,6 +124,17 @@ exports.getMatchers = function() {
};
};

exports.isPending = function(managedPromise) {
return managedPromise.state_ === 'pending';
// declare custom matcher types
declare global {
namespace jasmine {
interface Matchers {
toBeLotsMoreThan(expected: number | Promise<number>): Promise<void>;
toBeDisplayed(): Promise<void>;
}
}
}


export function isPending(managedPromise: wdpromise.Promise<any>) {
return (managedPromise as any).state_ === 'pending';
};
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"sourceMap": false,
"declaration": false,
"removeComments": false,
"noImplicitAny": false,
"noImplicitAny": true,
"outDir": "built_spec"
},
"include": [
Expand Down