@empiricalrun/playwright-utils 0.13.13 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +2 -61
- package/dist/auth/index.d.ts +17 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +35 -0
- package/docs/auth.md +50 -0
- package/docs/email.md +45 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @empiricalrun/playwright-utils
|
|
2
2
|
|
|
3
|
+
## 0.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d4d123a: feat: auth utils for user repos to do conditional logins
|
|
8
|
+
|
|
9
|
+
## 0.13.14
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [fcacf06]
|
|
14
|
+
- @empiricalrun/llm@0.9.4
|
|
15
|
+
|
|
3
16
|
## 0.13.13
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -11,64 +11,5 @@ Playwright utils for test code repos of our customers
|
|
|
11
11
|
- Vision capabilities
|
|
12
12
|
- `locator.query` API
|
|
13
13
|
- Captcha
|
|
14
|
-
- Email automation
|
|
15
|
-
|
|
16
|
-
## Email automation
|
|
17
|
-
|
|
18
|
-
### Example usage
|
|
19
|
-
|
|
20
|
-
#### Dynamic email
|
|
21
|
-
|
|
22
|
-
This dynamically generates a random email address that can
|
|
23
|
-
be used for the test (e.g. invite a new user).
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
import { EmailClient } from "@empiricalrun/playwright-utils";
|
|
27
|
-
|
|
28
|
-
const client = new EmailClient();
|
|
29
|
-
const address = client.getAddress();
|
|
30
|
-
|
|
31
|
-
// Input the `address` in the application
|
|
32
|
-
// that sends the email.
|
|
33
|
-
|
|
34
|
-
// Get email received on the `address`
|
|
35
|
-
const email = await client.waitForEmail();
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
#### Static email
|
|
39
|
-
|
|
40
|
-
This uses a known (static) email that can be used to login
|
|
41
|
-
into an application.
|
|
42
|
-
|
|
43
|
-
This needs an email id (e.g. `test-login-user`). The email id
|
|
44
|
-
is appended with the domain (managed internally) to get the full
|
|
45
|
-
email address.
|
|
46
|
-
|
|
47
|
-
```ts
|
|
48
|
-
import { EmailClient } from "@empiricalrun/playwright-utils";
|
|
49
|
-
|
|
50
|
-
const emailId = `test-login-user`;
|
|
51
|
-
|
|
52
|
-
const client = new EmailClient({ emailId });
|
|
53
|
-
const address = client.getAddress(); // Returns full address with domain
|
|
54
|
-
|
|
55
|
-
// Get email received on the `address`
|
|
56
|
-
const email = await client.waitForEmail();
|
|
57
|
-
|
|
58
|
-
// Get login OTP
|
|
59
|
-
const loginCode = email.codes[0];
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
#### Add reporter
|
|
63
|
-
|
|
64
|
-
To use the custom HTML reporter, add the following to your Playwright config:
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
import { defineConfig } from "@playwright/test";
|
|
68
|
-
import { baseConfig } from "@empiricalrun/playwright-utils";
|
|
69
|
-
|
|
70
|
-
export default defineConfig({
|
|
71
|
-
...baseConfig,
|
|
72
|
-
...
|
|
73
|
-
});
|
|
74
|
-
```
|
|
14
|
+
- [Email automation](./docs/email.md)
|
|
15
|
+
- [Authentication](./docs/auth.md)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Page } from "playwright-core";
|
|
2
|
+
type WithKey<T> = T & {
|
|
3
|
+
key: string;
|
|
4
|
+
};
|
|
5
|
+
export declare class AuthStore<T extends WithKey<{}>> {
|
|
6
|
+
private page;
|
|
7
|
+
private userContext;
|
|
8
|
+
private loginFunc;
|
|
9
|
+
private checkLoggedInFunc;
|
|
10
|
+
constructor(page: Page, userContext: T, loginFunc: (page: Page, userContext: T) => Promise<void>, checkLoggedInFunc: (page: Page, userContext: T) => Promise<boolean>);
|
|
11
|
+
loginIfRequired(): Promise<void>;
|
|
12
|
+
static location(userContext: {
|
|
13
|
+
key: string;
|
|
14
|
+
}): string;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,qBAAa,SAAS,CAAC,CAAC,SAAS,OAAO,CAAC,EAAE,CAAC;IAExC,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,iBAAiB;gBAHjB,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,CAAC,EACd,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACxD,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC;IAGvE,eAAe;IAoBrB,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;CAGtD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthStore = void 0;
|
|
4
|
+
class AuthStore {
|
|
5
|
+
page;
|
|
6
|
+
userContext;
|
|
7
|
+
loginFunc;
|
|
8
|
+
checkLoggedInFunc;
|
|
9
|
+
constructor(page, userContext, loginFunc, checkLoggedInFunc) {
|
|
10
|
+
this.page = page;
|
|
11
|
+
this.userContext = userContext;
|
|
12
|
+
this.loginFunc = loginFunc;
|
|
13
|
+
this.checkLoggedInFunc = checkLoggedInFunc;
|
|
14
|
+
}
|
|
15
|
+
async loginIfRequired() {
|
|
16
|
+
let shouldDoLogin = false;
|
|
17
|
+
try {
|
|
18
|
+
const hasLoggedIn = await this.checkLoggedInFunc(this.page, this.userContext);
|
|
19
|
+
shouldDoLogin = !hasLoggedIn;
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
shouldDoLogin = true;
|
|
23
|
+
}
|
|
24
|
+
if (shouldDoLogin) {
|
|
25
|
+
await this.loginFunc(this.page, this.userContext);
|
|
26
|
+
const storagePath = AuthStore.location(this.userContext);
|
|
27
|
+
await this.page.context().storageState({ path: storagePath });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// TODO: make this async
|
|
31
|
+
static location(userContext) {
|
|
32
|
+
return `auth/${userContext.key}.json`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.AuthStore = AuthStore;
|
package/docs/auth.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Authentication utilities
|
|
2
|
+
|
|
3
|
+
This builds around playwright's `storageState` primitive which is used to cache
|
|
4
|
+
auth related state (in a json file on disk).
|
|
5
|
+
|
|
6
|
+
This requires an object of `UserContext` type, which has a `key: string`. The
|
|
7
|
+
rest of the object can be custom.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
### Login if required
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { login } from "../pages/login";
|
|
15
|
+
import { test as setup } from "./fixtures";
|
|
16
|
+
import { AuthStore } from "@empiricalrun/playwright-utils";
|
|
17
|
+
|
|
18
|
+
setup("login to application", async ({ page, userContext }) => {
|
|
19
|
+
const auth = new AuthStore(
|
|
20
|
+
page,
|
|
21
|
+
userContext,
|
|
22
|
+
// Pass login method
|
|
23
|
+
login,
|
|
24
|
+
// Pass login checker method
|
|
25
|
+
(page, userContext) => {
|
|
26
|
+
const postLoginElement = page.getByRole("button", { name: "Search" });
|
|
27
|
+
await postLoginElement.waitFor();
|
|
28
|
+
return postLoginElement.isVisible();
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
await auth.loginIfRequired();
|
|
33
|
+
await page.context().storageState({ path: authFile });
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Get auth state location
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
// in your playwright.config.ts
|
|
41
|
+
import { AuthStore } from "@empiricalrun/playwright-utils";
|
|
42
|
+
|
|
43
|
+
projects: [
|
|
44
|
+
name: "chromium",
|
|
45
|
+
use: {
|
|
46
|
+
storageState: AuthStore.location(userContext)
|
|
47
|
+
// ...
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
```
|
package/docs/email.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
## Email automation
|
|
2
|
+
|
|
3
|
+
### Example usage
|
|
4
|
+
|
|
5
|
+
#### Dynamic email
|
|
6
|
+
|
|
7
|
+
This dynamically generates a random email address that can
|
|
8
|
+
be used for the test (e.g. invite a new user).
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { EmailClient } from "@empiricalrun/playwright-utils";
|
|
12
|
+
|
|
13
|
+
const client = new EmailClient();
|
|
14
|
+
const address = client.getAddress();
|
|
15
|
+
|
|
16
|
+
// Input the `address` in the application
|
|
17
|
+
// that sends the email.
|
|
18
|
+
|
|
19
|
+
// Get email received on the `address`
|
|
20
|
+
const email = await client.waitForEmail();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Static email
|
|
24
|
+
|
|
25
|
+
This uses a known (static) email that can be used to login
|
|
26
|
+
into an application.
|
|
27
|
+
|
|
28
|
+
This needs an email id (e.g. `test-login-user`). The email id
|
|
29
|
+
is appended with the domain (managed internally) to get the full
|
|
30
|
+
email address.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { EmailClient } from "@empiricalrun/playwright-utils";
|
|
34
|
+
|
|
35
|
+
const emailId = `test-login-user`;
|
|
36
|
+
|
|
37
|
+
const client = new EmailClient({ emailId });
|
|
38
|
+
const address = client.getAddress(); // Returns full address with domain
|
|
39
|
+
|
|
40
|
+
// Get email received on the `address`
|
|
41
|
+
const email = await client.waitForEmail();
|
|
42
|
+
|
|
43
|
+
// Get login OTP
|
|
44
|
+
const loginCode = email.codes[0];
|
|
45
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/playwright-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"playwright-core": "^1.46.1",
|
|
39
39
|
"playwright-extra": "^4.3.6",
|
|
40
40
|
"puppeteer-extra-plugin-recaptcha": "^3.6.8",
|
|
41
|
-
"@empiricalrun/llm": "^0.9.
|
|
41
|
+
"@empiricalrun/llm": "^0.9.4",
|
|
42
42
|
"@empiricalrun/r2-uploader": "^0.3.3"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|