Skip to content
4 changes: 3 additions & 1 deletion extension/chrome/dev/ci_unit_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ApiErr } from '../../js/common/api/shared/api-error.js';
import { WellKnownHostMeta } from '../../js/common/api/account-servers/well-known-host-meta.js';
import { Mime } from '../../js/common/core/mime.js';
import { Att } from '../../js/common/core/att.js';
import { Wkd } from '../../js/common/api/key-server/wkd.js';

/**
* importing all libs that are tested in ci tests
Expand All @@ -21,7 +22,8 @@ const libs: any[] = [
AttUI,
Buf,
KeyUtil,
Mime
Mime,
Wkd
];

// add them to global scope so ci can use them
Expand Down
74 changes: 52 additions & 22 deletions extension/js/common/api/key-server/wkd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,50 +19,80 @@ export class Wkd extends Api {
// https://www.sektioneins.de/en/blog/18-11-23-gnupg-wkd.html
// https://metacode.biz/openpgp/web-key-directory

constructor(private myOwnDomain: string) {
public port: number | undefined;
private protocol: string;

constructor(private myOwnDomain: string, protocol = 'https') {
super();
this.protocol = protocol;
}

public lookupEmail = async (email: string): Promise<PubkeySearchResult> => {
const parts = email.toLowerCase().split('@');
if (parts.length > 2) {
const parts = email.split('@');
if (parts.length !== 2) {
return { pubkey: null, pgpClient: null };
}
const [user, recipientDomain] = parts;
if (!user || !recipientDomain) {
return { pubkey: null, pgpClient: null };
}
if (!opgp) {
// pgp_block.htm does not have openpgp loaded
// the particular usecase (auto-loading pubkeys to verify signatures) is not that important,
// the user typically gets the key loaded from composing anyway
// the proper fix would be to run encodeZBase32 through background scripts
return { pubkey: null, pgpClient: null };
}
const hu = opgp.util.encodeZBase32(await opgp.crypto.hash.digest(opgp.enums.hash.sha1, Buf.fromUtfStr(user)));
// todo - could also search on `https://openpgpkey.{domain}/.well-known/openpgpkey/{domain}/hu/{hu}?l={user}`
const url = `https://${recipientDomain}/.well-known/openpgpkey/hu/${hu}?l=${encodeURIComponent(user)}`;
let binary: Buf;
const directDomain = recipientDomain.toLowerCase();
const advancedDomainPrefix = (directDomain === 'localhost') ? '' : 'openpgpkey.';
const hu = opgp.util.encodeZBase32(await opgp.crypto.hash.digest(opgp.enums.hash.sha1, Buf.fromUtfStr(user.toLowerCase())));
const directHost = (typeof this.port === 'undefined') ? directDomain : `${directDomain}:${this.port}`;
const advancedHost = `${advancedDomainPrefix}${directHost}`;
const userPart = `hu/${hu}?l=${encodeURIComponent(user)}`;
const advancedUrl = `${this.protocol}://${advancedHost}/.well-known/openpgpkey/${directDomain}`;
const directUrl = `${this.protocol}://${directHost}/.well-known/openpgpkey`;
let response = await this.urlLookup(advancedUrl, userPart);
if (!response.buf && response.hasPolicy) {
return { pubkey: null, pgpClient: null }; // do not retry direct if advanced had a policy file
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rrrooommmaaa I think the error was here: if I'm reading it correctly, it was possible for the for loop to finish and validUrl would remain undefined. Then the lines below would continue calling that URL like undefined/hu/... causing the error reports.

I recommend to try to avoid for loops that do accounting in this manner unless one really cannot avoid them. It can be hard to spot bugs. I've rewritten it as a method that gets called two times explicitly with two different parameters (advanced vs direct url), which I think will make for an easier to debug structure.

if (!response.buf) {
response = await this.urlLookup(directUrl, userPart);
}
if (!response.buf) {
return { pubkey: null, pgpClient: null }; // do not retry direct if advanced had a policy file
}
const { keys: [key], errs } = await KeyUtil.readMany(response.buf);
if (errs.length || !key || !key.emails.some(x => x.toLowerCase() === email.toLowerCase())) {
return { pubkey: null, pgpClient: null };
}
// if recipient uses same domain, we assume they use flowcrypt
const pgpClient = this.myOwnDomain === recipientDomain ? 'flowcrypt' : 'pgp-other';
try {
binary = await Wkd.download(url, undefined, 4);
const pubkey = KeyUtil.armor(key);
return { pubkey, pgpClient };
} catch (e) {
if (ApiErr.isNotFound(e) || ApiErr.isNetErr(e)) {
return { pubkey: null, pgpClient: null };
}
Catch.report(`Wkd.lookupEmail err: ${String(e)}`);
return { pubkey: null, pgpClient: null };
}
const { keys: [key], errs } = await KeyUtil.readMany(binary);
if (errs.length || !key) {
return { pubkey: null, pgpClient: null };
}

private urlLookup = async (methodUrlBase: string, userPart: string): Promise<{ hasPolicy: boolean, buf?: Buf }> => {
try {
await Wkd.download(`${methodUrlBase}/policy`, undefined, 4);
} catch (e) {
return { hasPolicy: false };
}
console.info(`Loaded Public Key from WKD for ${email}: ${url}`);
let pubkey: string;
try {
pubkey = KeyUtil.armor(key);
const buf = await Wkd.download(`${methodUrlBase}/${userPart}`, undefined, 4);
if (buf.length) {
console.info(`Loaded WKD url ${methodUrlBase}/${userPart} and will try to extract Public Keys`);
}
return { hasPolicy: true, buf };
} catch (e) {
return { pubkey: null, pgpClient: null };
if (!ApiErr.isNotFound(e)) {
Catch.report(`Wkd.lookupEmail error retrieving key ${methodUrlBase}/${userPart}: ${String(e)}`);
}
return { hasPolicy: true };
}
// if recipient uses same domain, we assume they use flowcrypt
const pgpClient = this.myOwnDomain === recipientDomain ? 'flowcrypt' : 'pgp-other';
return { pubkey, pgpClient };
}

}
16 changes: 9 additions & 7 deletions test/source/browser/browser-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,19 +124,19 @@ export class BrowserPool {
});
}

public withNewBrowserTimeoutAndRetry = async (cb: (t: AvaContext, browser: BrowserHandle) => void, t: AvaContext, consts: Consts) => {
public withNewBrowserTimeoutAndRetry = async (cb: (t: AvaContext, browser: BrowserHandle) => void, t: AvaContext, consts: Consts, flag?: 'FAILING') => {
const withTimeouts = newWithTimeoutsFunc(consts);
const attemptDebugHtmls: string[] = [];
t.totalAttempts = consts.ATTEMPTS;
for (let attemptNumber = 1; attemptNumber <= consts.ATTEMPTS; attemptNumber++) {
t.totalAttempts = flag === 'FAILING' ? 1 : consts.ATTEMPTS;
for (let attemptNumber = 1; attemptNumber <= t.totalAttempts; attemptNumber++) {
t.attemptNumber = attemptNumber;
t.attemptText = `(attempt ${t.attemptNumber} of ${t.totalAttempts})`;
try {
const browser = await withTimeouts(this.newBrowserHandle(t));
try {
await withTimeouts(this.cbWithTimeout(async () => await cb(t, browser), consts.TIMEOUT_EACH_RETRY));
await this.throwOnRetryFlagAndReset(t);
if (attemptDebugHtmls.length) {
if (attemptDebugHtmls.length && flag !== 'FAILING') { // don't debug known failures
addDebugHtml(`<h1>Test (later succeeded): ${Util.htmlEscape(t.title)}</h1>${attemptDebugHtmls.join('')}`);
}
return;
Expand All @@ -148,17 +148,19 @@ export class BrowserPool {
await browser.close();
}
} catch (err) {
this.processTestError(err, t, attemptDebugHtmls);
this.processTestError(err, t, attemptDebugHtmls, flag);
}
}
}

private processTestError = (err: any, t: AvaContext, attemptHtmls: string[]) => {
private processTestError = (err: any, t: AvaContext, attemptHtmls: string[], flag?: 'FAILING') => {
t.retry = undefined;
if (t.attemptNumber! < t.totalAttempts!) {
t.log(`${t.attemptText} Retrying: ${String(err)}`);
} else {
addDebugHtml(`<h1>Test: ${Util.htmlEscape(t.title)}</h1>${attemptHtmls.join('')}`);
if (flag !== 'FAILING') { // don't debug known failures
addDebugHtml(`<h1>Test: ${Util.htmlEscape(t.title)}</h1>${attemptHtmls.join('')}`);
}
t.log(`${t.attemptText} Failed: ${err instanceof Error ? err.stack : String(err)}`);
t.fail(`[ALL RETRIES FAILED for ${t.title}]`);
}
Expand Down
2 changes: 2 additions & 0 deletions test/source/mock/all-apis-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { mockBackendEndpoints } from './backend/backend-endpoints';
import { mockGoogleEndpoints } from './google/google-endpoints';
import { mockKeyManagerEndpoints } from './key-manager/key-manager-endpoints';
import { mockWellKnownHostMetaEndpoints } from './host-meta/host-meta-endpoints';
import { mockWkdEndpoints } from './wkd/wkd-endpoints';

export type HandlersDefinition = Handlers<{ query: { [k: string]: string; }; body?: unknown; }, unknown>;

Expand All @@ -29,6 +30,7 @@ export const startAllApisMock = async (logger: (line: string) => void) => {
...mockAttesterEndpoints,
...mockKeyManagerEndpoints,
...mockWellKnownHostMetaEndpoints,
...mockWkdEndpoints,
'/favicon.ico': async () => '',
});
await api.listen(8001);
Expand Down
129 changes: 129 additions & 0 deletions test/source/mock/wkd/wkd-endpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/* ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com */

import { HandlersDefinition } from '../all-apis-mock';

const alice = `-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEXgS/LxYJKwYBBAHaRw8BAQdAJ/BnDcmcOCED/rW3y1zPHSX6lABI7G19R6mP
hgfIgj+0EUFsaWNlIDxhbGljZUBybnA+iJAEExYIADgWIQRz7cyRGa/I4tu9zeUE
UUCWaf/ePAUCXgS/LwIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAEUUCW
af/ePCSdAP9OWq8uOk5B5LUtPvFnxqGkrZlAHt+tgR271QSggRV3MAEAvtL/ru5o
ss9jx26EqYj2GUgHGtsYqsz8j1y97S5lMQo=
=H16D
-----END PGP PUBLIC KEY BLOCK-----`;

const johnDoe = `-----BEGIN PGP PUBLIC KEY BLOCK-----

xsBNBF+IiY4BCADiCm145EEu8QALcex4OY+K7AEof4w2ZFW0Xj9wRodRj5WMEk0h5TOXlCr9Fzah
N75pl7W7jkYJUSUWucSga2tiIphR3JkPVDod6QUgwKSw/ZbXef9IY10bg4k+jobWToy4FmhOxUoZ
MfYGRMJKAwWBXajygbFp3XLV08BTToK4VRzA5/jZqjTmBnQ4Dut+F+TtdEve4WII/vtKYdpt7uSp
C3beifG0GD+bwoHit1hlsawN7iHGNjvszSGm9gXSRvF2dBskSgR2mtMC2HkgkhxR8Xrc5lBJAqPd
V05wvzjg26BXBEhe8AhJbqmnwUuEt40MleWuQPUMM0MBHtWfDIMxABEBAAHNEmpvaG4uZG9lQGxv
Y2FsaG9zdMLAiQQTAQgAMxYhBMsbekG6fBy6oIphZrkCy2XGlNa0BQJfiImUAhsDBQsJCAcCBhUI
CQoLAgUWAgMBAAAKCRC5AstlxpTWtCOMCACS/BgBU+/11SCzKcyjXHECPoJC2zxjBHZELaA8YRAP
CX9SIdWiaP06F7HTRrvBUqFuPtebA62GmF6PCyWv3wM7iY8HWrNNWnRgclfn203s6LpkIO8myzPi
itH15+2+CoKRD9QnGbkLZqOe+20ZG8AalciSnQm2QNMMd5RXyUhI8YxWFwzmd9rw18yA5r+P2g2y
uwC0PHbJDeRPzVsX5ZPVty00MCCOtJxcjTMszEVrndae78i2X7lI4WllGXvouw5nYJ4QCJxnE7IN
trwEW2/oqt1deeKAzDqtBlaz5eKameQhzCfIQ9yIvIxmS4GS25FScIBCqQktncKhujI2HfPbzsBN
BF+IiZQBCADAyDpTiMghfyWWqdqM09afztzzePk02xJJYRO/p09wgmqPaWgxfe//NqiFPDfiTyvc
nDLCDKuFktU5uD+I6UGVj7511r9veDh9Q+YB81qria0NONJtYN+bJ0T+depUAlOfNRSf9U79iuck
EHQR0j+4WLXHfqNR+CP9uobXZeAuyU47/KGXLvpO0GV1f8oDIxHW/ZnArFjXFHCbEwFg2Gbdedd6
7gFMc18Q4brfhA4XbMyN0rybipmuylWGIXM30O7cJDBg7+wM3CGRU/aiPCuFkGyknJvRMcjd2XnK
JxqRhvtIF4ZFoXMTi3U2ZqBjkrInECEIVxo0ImNmugzPFyCHABEBAAHCwHYEGAEIACAWIQTLG3pB
unwcuqCKYWa5AstlxpTWtAUCX4iJmQIbDAAKCRC5AstlxpTWtBJiB/9HkI+URaTsMYA+Jh98Ia9J
U57naEB/iugXGiStORK/QQfa3/aSnVeCI/NU2Ja0QKwb/QkjeTA8J6pSXjz5BqQs6Ydgww/cTHfZ
eqx9TuETieW/vzdBtkEHPNAWk4h6uB3KlE+WiaErLqMp/ibp3XlDizDzIanxBGwJH3n0xbsII2c4
Sk0/2pKhkHZeombiFhL4Ius6Ym82DsaHg/ngq0Alm9lUrZd2bhKWuOlUXF/kl1BtFuxQSNhAD13r
GOcKZI9WfvN8IV5P8oh/ldHcF8WUumQEFIAR3WGk8P9v1XfHtBFeDQ70ZoE+KV7Uy7UKAzcVni4O
AwMwBxWpyLaH6xjb
=mswb
-----END PGP PUBLIC KEY BLOCK-----`;

const johnDoe1 = `-----BEGIN PGP PUBLIC KEY BLOCK-----

xsBNBF+Jz04BCACYEg0Fkg4NLnTxzuyF3gnz2pMfp+BelG/IHvIg9mls4U8OJcjGyq3bVpPDKDDQ
4ZuhRtrMy5K0ZnyiGsmzMKXvVS3FUPQ5EJD2Laveo5ohtM6t49jlloQvv7aMUBVpjTskaY06lJuV
2f1CCCDteh3G8qNpKvziUc4a8PzeIItktHTCa0MNdDRxq19DUs2eQGGXqBDm/mQjVMZ1Zgt55Ymu
BpPLytJXOjRoDYsTj+OdOv+aQ4Td7JnicTDVQR4Uc9x02lMPsBF3K0N0cnITyiKCV/QdgdSQkL8N
zFVgvt5QPGhlGA0sAl1wiBFeNZrrd+VXg4FmuGrWd9YLS01AyRSJABEBAAHNEmpvaG4uZG9lQDEy
Ny4wLjAuMcLAiQQTAQgAMxYhBGWfN6kiReeNpwCbUy2oGOH1OKOdBQJfic9SAhsDBQsJCAcCBhUI
CQoLAgUWAgMBAAAKCRAtqBjh9TijnU1JB/wPcImnOmo42gu8YBKe18d9HyCQNs4q4pw/bYXshLe7
aMjx+XgUvWHBcoTtz+4g2QjmhmL3ROkGs/vBriZZqhZz4636s7RAlyU0yyzcH4rvNq/ByNm+Ol7x
Bwo3EbaRh46Q4mbctslfQ/jd42cUzwEOnY2HSPH+tgfTjd8xciBL5tH0+YinCuqSi/sAOkBoNAkv
kgiA+cRH4scVsW2KwWuZPOJINO8nJVu0at64sZib8/UJ4Zku5w7i1dnmWu6C9aqz+Ddu/xcDUW8j
2GFXECJX0deXZmhEZ8wLt5P+ke3Wt1gttGCigVzPvpXHkpZpC7zlykcMeE2ywRBqypauZUjPzsBN
BF+Jz1IBCACjRVxKy2aU49H95g8LM1Dsqmc+KCSOl9/kC1pyzKl4xUEYQ+ok5OKHt9tf42a1z9SM
oUicFkSOwBMtjOhWjrghxVBHIc4NtDewFXY6IifG6BvewOiNat2mYzfLF852idBbhnN82p4NWd2g
oUwDcqOvZ3Z5qg4eKiH2l+UzlHuFXmSfFP3g7Pm3UTaYhOWRBwOO/u7JN9rMHBcLxfp7T745C8dT
UmrZEpfTEGgwhmYfBFyMZFxzgtZwt4UUTnyLFtqhROPx6ji4ecSDNAD7yVjd9uJSNbxIRV4SUPCG
/vR39Lm8dXiFEek47DYGPaPyid/zfFkfhLndQ70W2GkhGdLnABEBAAHCwHYEGAEIACAWIQRlnzep
IkXnjacAm1MtqBjh9TijnQUCX4nPVwIbDAAKCRAtqBjh9Tijna+wB/4tsj016eBsQGb3xGs/BBa6
06VLL9tjrTV9TdZj3DfpE9xSPiNC+Jah09uW//VNRzNTDYctGXEGIYm2tx2q8QAX/rWBC/UYi16l
4lHnvlHa4NNA+O22uQpMlwmbTVSPTs4kVUSpNyuOtE6SXY6UyzcyvwTpffXiQkfICW7BXmykUXHx
HZ8Ddq/syp3eBitlmNZHGwRWKD5ihd96o5dCw/Dgpz/p6dxka1627j013wov65p1NbXiV1kM7G7s
ZccLrjYxOL/1Rc1ac9TdfXX7lVeZtbpSVhSl9Z1YMhth+oWVJ79iQQ8OPKEvt471Qwk1LH7k4a9O
nT5+WNnpAkcxrjMd
=fISM
-----END PGP PUBLIC KEY BLOCK-----
`;

const jackAdvanced = `-----BEGIN PGP PUBLIC KEY BLOCK-----

xsBNBF+J56IBCADSvEei1mAEQCEXHxaOKzsxvM8Qvgjj0vr+zHE+hUFg1znRAyjQ9XSDGwJ4+dut
kKh8P2Ibu8hhX01eHiqW85IXO2yvLDo19+8TnRHQGfn895Ptxs150Xcg4gwXPzvY9tIXV4+z+vm2
ek7tM3zI4IXpT/VCasVHHn34C6qupkJSviZwC+SoXPS5flFXNSGktALC9OIpDzW1qqtIpl2niG2I
4Df4yn3iiRVM8Zt4SGxsvcSXbsAAVEev7BQTUgxin5DlWkA7R9zaiBQ/DkO1JCEXJVvqpK1ETxi3
K/3rkmmob3mICp0QXpgpllik6jH5YXGtK0Dbly9IXPH03smrpBS7ABEBAAHNF2phY2suYWR2YW5j
ZWRAbG9jYWxob3N0wsCJBBMBCAAzFiEEFpnGj5ZL0Um8kGZee64HZY9qWHgFAl+J56cCGwMFCwkI
BwIGFQgJCgsCBRYCAwEAAAoJEHuuB2WPalh4frQH/jWdjU1OPy0mMToZFRF81j4v1eyziyBSPjWV
MxvqNMSeBxHBmDWsfcWesvUi24kodiAYnJW8zAN9N99BATgGgvGNkghq4AFneOWBXDwQi8t+5H0v
c9JXSUbE/NH1JuqkPoF6p2flcR3VIhmfOEKMfKcCSyLRykiDQxGjkGwBMo/Dmv6iC0qJu95u/8PG
C8hnLmkORJFs0Ql0lTTqKrZQdhdyS34Ad99YwbNjtZvZcfIRljiMaJlwsj9e/kj9Ppn7PZWgs20X
/reafSKWyPFsgQyNzWnmXggrodvVKrj2NHlFlAqYyKNujbz0NdpwBx4U4WBFIpSZ2HLNT+chHdnr
NlfOwE0EX4nnpwEIALRviWiViluglkUGltBX6rWwYjY8niPbBaXC+xus4uH08IlDO/aDD2t4efkP
t0QMeQE9WYsRk8hHUC+isJRF+jbwVhAW1fkv4R3WWkwXQFsr0wXW4Krp30m9JaOW9EolDwv8/Fik
XmkBhWviByqBDvZ9CPtEt5Nwd6XT49Cf4HycQvrkKC3ytYohs2iyf+T7BLKJr6y3zDlaBtXaoqpA
wIXBduoccL01MyrGxLeLF56W75SZmtE4CK0G6g/zjjwmawKDSfK6DZHARYC/ZguUocnpB3Ui7B8d
sprqB1QmQZJQt7By6EUvhnw1WYAiDD05xryFPNhXYt3+Ypid/N/A2eEAEQEAAcLAdgQYAQgAIBYh
BBaZxo+WS9FJvJBmXnuuB2WPalh4BQJfieetAhsMAAoJEHuuB2WPalh4TvgIAIRkAuvvl+9p8xPg
pfMp5muIpVFjWmMUBIT8MEXZvVSr3YUpDmHxTgbL78Hf9Fk7rAw7tkFFz+cZltnIDITUCyGdIJaF
dow3a+ImNZ/eo6zcftWJiyH1zM5w5aEcWNUnHpy8TDRIFgomt1K1DcAo2zoutpGylCF5ZeL6vqFw
afV6xkjQ9+neZ2LahN5cYNOKAeeI73hvoGFSCYp9Ih8JaEhG6seU9lskg2qQDvVEJaHHp0nPxbU/
mhejIVi+pinqouXEqSb+84n2dNQ7HdgGe1YBM8kvNzq9SLfcYWjpnkchoL+5KGksjgbOvKFDz1Ek
nmusEeYtrrMytL4oUohBVZk=
=bbav
-----END PGP PUBLIC KEY BLOCK-----
`;

export const mockWkdEndpoints: HandlersDefinition = {
'/.well-known/openpgpkey/hu/ihyath4noz8dsckzjbuyqnh4kbup6h4i?l=john.doe': async () => {
return johnDoe1; // direct for john.doe@127.0.0.1
},
'/.well-known/openpgpkey/hu/ihyath4noz8dsckzjbuyqnh4kbup6h4i?l=John.Doe': async () => {
return johnDoe1; // direct for John.Doe@127.0.0.1
},
'/.well-known/openpgpkey/hu/cb53pfqmbzc8mm3ecbjxyen65fdxos56?l=jack.advanced': async () => {
return jackAdvanced; // direct for jack.advanced@localhost
},
'/.well-known/openpgpkey/127.0.0.1/hu/ihyath4noz8dsckzjbuyqnh4kbup6h4i?l=john.doe': async () => {
return alice; // shouldn't be returned
},
'/.well-known/openpgpkey/127.0.0.1/hu/ihyath4noz8dsckzjbuyqnh4kbup6h4i?l=John.Doe': async () => {
return alice; // shouldn't be returned
},
'/.well-known/openpgpkey/localhost/hu/ihyath4noz8dsckzjbuyqnh4kbup6h4i?l=john.doe': async () => {
return johnDoe; // advanced for john.doe@localhost
},
'/.well-known/openpgpkey/localhost/hu/ihyath4noz8dsckzjbuyqnh4kbup6h4i?l=John.Doe': async () => {
return johnDoe; // advanced for John.Doe@localhost
},
'/.well-known/openpgpkey/localhost/hu/pob4adi8roqdsmtmxikx68pi6ij35oca?l=incorrect': async () => {
return alice; // advanced for incorrect@localhost
},
'/.well-known/openpgpkey/localhost/policy': async () => {
return ''; // allow advanced for localhost
},
'/.well-known/openpgpkey/policy': async () => {
return ''; // allow direct for 127.0.0.1
},
};
4 changes: 2 additions & 2 deletions test/source/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ ava.before('set config and mock api', async t => {
t.pass();
});

const testWithBrowser = (acct: CommonAcct | undefined, cb: (t: AvaContext, browser: BrowserHandle) => Promise<void>): ava.Implementation<{}> => {
const testWithBrowser = (acct: CommonAcct | undefined, cb: (t: AvaContext, browser: BrowserHandle) => Promise<void>, flag?: 'FAILING'): ava.Implementation<{}> => {
return async (t: AvaContext) => {
await browserPool.withNewBrowserTimeoutAndRetry(async (t, browser) => {
if (acct) {
await BrowserRecipe.setUpCommonAcct(t, browser, acct);
}
await cb(t, browser);
}, t, consts);
}, t, consts, flag);
t.pass();
};
};
Expand Down
Loading