Skip to content

Commit

Permalink
Merge pull request #462 from angrykoala/dev
Browse files Browse the repository at this point in the history
2.13.1
  • Loading branch information
angrykoala authored Aug 8, 2020
2 parents 60760cf + b20cc41 commit 2067195
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 27 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2.13.1 / 2020-08-08
===================

* Fixes Dockerfile
* Error messages improved for timeout errors
* Updates dependencies

2.13.0 / 2020-07-24
===================

Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ RUN apt-get update && apt-get install -y -q --no-install-recommends\
&& rm -rf /var/lib/apt/lists/*

ENV NO_SANDBOX=true
ENV PUPPETEER_SKIP_DOWNLOAD='true'
RUN npm install wendigo && npm cache clean --force
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2078,8 +2078,6 @@ FROM angrykoala/wendigo
WORKDIR /app
COPY package*.json ./
# Copies Puppeteer and Wendigo from the base image
RUN mv /node_modules .
# Installs your up (it must have Wendigo as a dependency)
RUN npm install
# Copies the rest of your app
Expand Down
73 changes: 57 additions & 16 deletions lib/browser/mixins/browser_wait.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { WendigoSelector } from '../../types';
import { createFindTextXPath, delay, isNumber } from '../../utils/utils';
import FailIfNotLoaded from '../../decorators/fail_if_not_loaded';
import OverrideError from '../../decorators/override_error';
import { EvaluateFn } from '../../puppeteer_wrapper/puppeteer_types';
import { EvaluateFn, PuppeteerErrors } from '../../puppeteer_wrapper/puppeteer_types';

export default abstract class BrowserWait extends BrowserNavigation {

Expand All @@ -14,6 +14,7 @@ export default abstract class BrowserWait extends BrowserNavigation {
}

@FailIfNotLoaded
@OverrideError()
public async waitFor(selector: EvaluateFn, timeout?: number, ...args: Array<any>): Promise<void> {
timeout = this._getTimeout(timeout);
args = args.map((e) => {
Expand All @@ -25,19 +26,20 @@ export default abstract class BrowserWait extends BrowserNavigation {
timeout: timeout,
visible: true
}, ...args);
} catch (err) {
if (err instanceof Error && err.message.match(/DOMException\:/)) { // TODO: move to a helper/wrapper
throw new QueryError("waitFor", `Invalid selector "${selector}".`);
} else {
let errMsg;
if (typeof selector === 'function') errMsg = `Waiting for function to return true`;
else errMsg = `Waiting for element "${selector}"`;
throw new TimeoutError("waitFor", errMsg, timeout);
}
} catch (error) {
let errMsg;
if (typeof selector === 'function') errMsg = `Waiting for function to return true`;
else errMsg = `Waiting for element "${selector}"`;
throw this._overrideWaitError(error, {
timeoutMessage: errMsg,
selector: `${selector}`,
timeout
});
}
}

@FailIfNotLoaded
@OverrideError()
public async waitUntilNotVisible(selector: WendigoSelector, timeout?: number): Promise<void> {
timeout = this._getTimeout(timeout);
try {
Expand All @@ -46,11 +48,16 @@ export default abstract class BrowserWait extends BrowserNavigation {
return !WendigoUtils.isVisible(element);
}, timeout, selector);
} catch (err) {
throw new TimeoutError("waitUntilNotVisible", `Waiting for element "${selector}" to not be visible`, timeout);
throw this._overrideWaitError(err, {
timeoutMessage: `Waiting for element "${selector}" to not be visible`,
selector: `${selector}`,
timeout
});
}
}

@FailIfNotLoaded
@OverrideError()
public async waitForUrl(url: string | RegExp, timeout?: number): Promise<void> {
timeout = this._getTimeout(timeout);
if (!url) return Promise.reject(new WendigoError("waitForUrl", `Invalid parameter url.`));
Expand All @@ -73,11 +80,15 @@ export default abstract class BrowserWait extends BrowserNavigation {
}
}, timeout, parsedUrl);
} catch (err) {
throw new TimeoutError("waitForUrl", `Waiting for url "${url}"`, timeout);
throw this._overrideWaitError(err, {
timeoutMessage: `Waiting for url "${url}"`,
timeout
});
}
}

@FailIfNotLoaded
@OverrideError()
public async waitForNavigation(timeout?: number): Promise<void> {
timeout = this._getTimeout(timeout);
const t1 = new Date().getTime();
Expand All @@ -94,7 +105,10 @@ export default abstract class BrowserWait extends BrowserNavigation {
return Boolean(w.WendigoUtils);
}, timeout2);
} catch (err) {
throw new TimeoutError("waitForNavigation", "", timeout);
throw this._overrideWaitError(err, {
timeoutMessage: "",
timeout
});
}
}

Expand All @@ -109,6 +123,8 @@ export default abstract class BrowserWait extends BrowserNavigation {
return result[1];
}

@FailIfNotLoaded
@OverrideError()
public async waitForText(text: string, timeout?: number): Promise<void> {
timeout = this._getTimeout(timeout);
try {
Expand All @@ -117,33 +133,45 @@ export default abstract class BrowserWait extends BrowserNavigation {
return Boolean(WendigoUtils.xPathQuery(xp).length > 0);
}, timeout, xPath);
} catch (err) {
throw new TimeoutError("waitForText", `Waiting for text "${text}"`, timeout);
throw this._overrideWaitError(err, {
timeoutMessage: `Waiting for text "${text}"`,
timeout
});
}
}

@FailIfNotLoaded
@OverrideError()
public async waitAndClick(selector: string, timeout?: number): Promise<number> {
timeout = this._getTimeout(timeout);
try {
await this.waitFor(selector, timeout);
return await this.click(selector);
} catch (err) {
throw new TimeoutError("waitAndClick", "", timeout);
throw this._overrideWaitError(err, {
timeoutMessage: "",
timeout
});
}
}

@OverrideError()
@FailIfNotLoaded
public async waitAndType(selector: string, text: string, timeout?: number): Promise<void> {
await this.waitFor(selector, timeout);
return await this.type(selector, text);

}

@OverrideError()
@FailIfNotLoaded
public async waitAndCheck(selector: string, timeout?: number): Promise<void> {
await this.waitFor(selector, timeout);
return await this.check(selector);
}

@OverrideError()
@FailIfNotLoaded
public async waitUntilEnabled(selector: WendigoSelector, timeout?: number): Promise<void> {
timeout = this._getTimeout(timeout);
try {
Expand All @@ -154,12 +182,25 @@ export default abstract class BrowserWait extends BrowserNavigation {
return value === null;
}, timeout, selector);
} catch (err) {
throw new TimeoutError("waitUntilEnabled", `Waiting for element "${selector}" to be enabled`, timeout);
throw this._overrideWaitError(err, {
timeoutMessage: `Waiting for element "${selector}" to be enabled`,
timeout
});
}
}

private _getTimeout(timeout?: number): number {
if (isNumber(timeout)) return timeout;
else return this._settings.defaultTimeout;
}

// TODO: this need to be completely reworked to make a sensible approach to error handling
private _overrideWaitError(error: Error, options: { timeoutMessage: string, timeout: number, selector?: string }): Error {
if (error instanceof PuppeteerErrors.TimeoutError || error instanceof TimeoutError) {
return new TimeoutError("", options.timeoutMessage, options.timeout);
}
if (error instanceof Error && error.message.match(/DOMException\:/) || error instanceof QueryError) {
return new QueryError("", `Invalid selector "${options.selector || ""}".`);
} else return error;
}
}
17 changes: 15 additions & 2 deletions lib/models/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export class FatalError extends WendigoError {
}

export class TimeoutError extends WendigoError {
public readonly timeout: number;
constructor(fn: string, message: string, timeout: number) {
public readonly timeout?: number;
constructor(fn: string, message: string, timeout?: number) {
let msg = message ? `${message}, timeout` : "Timeout";
if (timeout !== undefined) msg = `${msg} of ${timeout}ms exceeded.`;
super(fn, msg);
Expand All @@ -74,3 +74,16 @@ export class InjectScriptError extends FatalError {
this.name = this.constructor.name;
}
}

// export function handleError(error: Error, method: string, options: { timeout?: number, selector?: string } = {}): WendigoError {
// if (error instanceof WendigoError) return error;
// if (error instanceof PuppeteerErrors.TimeoutError) {
// return new TimeoutError(method, error.message, options.timeout);
// }
// if (error instanceof Error && error.message.match(/DOMException\:/)) {
// const selectorMessage = options.selector ? ` "${options.selector}"` : "";
// return new QueryError(method, `Invalid selector${selectorMessage}.`);
// } else {
// return new WendigoError(method, error.message);
// }
// }
2 changes: 1 addition & 1 deletion lib/puppeteer_wrapper/puppeteer_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export {
Page, Frame, Viewport, EvaluateFn, SerializableOrJSHandle, JSHandle, Response, Worker,
ScriptTagOptions, Browser, Base64ScreenShotOptions, Keyboard, Mouse, NavigationOptions, WaitForSelectorOptions, ElementHandle,
Touchscreen, Cookie, SetCookie, DeleteCookie, PageEventObj, Request, Timeoutable, PDFOptions, ConsoleMessage, ConsoleMessageType,
ResourceType, DialogType, Dialog, BrowserContext, Target, BrowserContextEventObj, GeoOptions, Permission, MediaType, MediaFeature
ResourceType, DialogType, Dialog, BrowserContext, Target, BrowserContextEventObj, GeoOptions, Permission, MediaType, MediaFeature, errors as PuppeteerErrors
} from 'puppeteer';
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wendigo",
"version": "2.13.0",
"version": "2.13.1",
"description": "A proper monster for front-end automated testing",
"engines": {
"node": ">=8.0.0"
Expand Down Expand Up @@ -46,16 +46,16 @@
"puppeteer": "~5.2.1"
},
"devDependencies": {
"@types/mocha": "^8.0.0",
"@types/node": "^14.0.25",
"@types/mocha": "^8.0.1",
"@types/node": "^14.0.27",
"@types/puppeteer": "~3.0.1",
"basic-auth": "^2.0.1",
"eslint": "^7.5.0",
"eslint": "^7.6.0",
"express": "^4.17.1",
"markdownlint-cli": "^0.23.2",
"mocha": "^8.0.1",
"mocha": "^8.1.1",
"sinon": "^9.0.2",
"tslint": "^6.1.2",
"tslint": "^6.1.3",
"typescript": "^3.9.7"
}
}
7 changes: 7 additions & 0 deletions tests/browser/wait_until_not_visible.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,11 @@ describe("Wait Until Not Visible", function() {
await browser.assert.not.exists("#switch.off");
await browser.assert.exists("#switch.on");
});

it("Wait Until Not Visible With Invalid Selector Error", async() => {
await browser.open(configUrls.index);
await utils.assertThrowsAsync(async() => {
await browser.waitUntilNotVisible("p[header=");
}, `QueryError: [waitUntilNotVisible] Invalid selector "p[header=".`);
});
});

0 comments on commit 2067195

Please sign in to comment.