@empiricalrun/playwright-utils 0.14.26 → 0.14.27

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @empiricalrun/playwright-utils
2
2
 
3
+ ## 0.14.27
4
+
5
+ ### Patch Changes
6
+
7
+ - 714eb31: feat: support chrome extensions in AuthStore
8
+
3
9
  ## 0.14.26
4
10
 
5
11
  ### Patch Changes
@@ -1,22 +1,28 @@
1
- import { Page } from "playwright-core";
1
+ import { BrowserContext, Page } from "playwright-core";
2
2
  type WithKey<T> = T & {
3
3
  key: string;
4
4
  };
5
+ type AppType = "web-app" | "chrome-extension";
5
6
  export declare class AuthStore<T extends WithKey<{}>> {
7
+ appType: AppType;
6
8
  page: Page;
7
9
  userContext: T;
8
10
  loginFunc: (page: Page, userContext: T) => Promise<void>;
9
11
  checkLoggedInFunc: (page: Page, userContext: T) => Promise<boolean>;
10
- constructor({ page, userContext, loginFunc, checkLoggedInFunc, }: {
12
+ constructor({ page, userContext, loginFunc, checkLoggedInFunc, appType, }: {
11
13
  page: Page;
12
14
  userContext: T;
13
15
  loginFunc: (page: Page, userContext: T) => Promise<void>;
14
16
  checkLoggedInFunc: (page: Page, userContext: T) => Promise<boolean>;
17
+ appType?: AppType;
15
18
  });
16
19
  loginIfRequired(): Promise<void>;
20
+ private pageWithAuthState;
21
+ private saveAuthState;
17
22
  static location(userContext: {
18
23
  key: string;
19
24
  }): string;
25
+ static loadStateForCrx(context: BrowserContext, userContext: WithKey<any>): Promise<void>;
20
26
  }
21
27
  export {};
22
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE/C,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,qBAAa,SAAS,CAAC,CAAC,SAAS,OAAO,CAAC,EAAE,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,CAAC,CAAC;IACf,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxD,EACV,IAAI,EACJ,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,EAAE;QACD,IAAI,EAAE,IAAI,CAAC;QACX,WAAW,EAAE,CAAC,CAAC;QACf,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KACrE;IAOK,eAAe;IAgCrB,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;CAGtD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAU,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE/D,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,KAAK,OAAO,GAAG,SAAS,GAAG,kBAAkB,CAAC;AAE9C,qBAAa,SAAS,CAAC,CAAC,SAAS,OAAO,CAAC,EAAE,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,CAAC,CAAC;IACf,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxD,EACV,IAAI,EACJ,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,OAAmB,GACpB,EAAE;QACD,IAAI,EAAE,IAAI,CAAC;QACX,WAAW,EAAE,CAAC,CAAC;QACf,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACpE,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB;IAQK,eAAe;YA4BP,iBAAiB;YAsBjB,aAAa;IAyB3B,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;WAIxC,eAAe,CAC1B,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC;CAoB5B"}
@@ -7,11 +7,13 @@ exports.AuthStore = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const playwright_core_1 = require("playwright-core");
9
9
  class AuthStore {
10
+ appType;
10
11
  page;
11
12
  userContext;
12
13
  loginFunc;
13
14
  checkLoggedInFunc;
14
- constructor({ page, userContext, loginFunc, checkLoggedInFunc, }) {
15
+ constructor({ page, userContext, loginFunc, checkLoggedInFunc, appType = "web-app", }) {
16
+ this.appType = appType;
15
17
  this.page = page;
16
18
  this.userContext = userContext;
17
19
  this.loginFunc = loginFunc;
@@ -24,11 +26,7 @@ class AuthStore {
24
26
  shouldDoLogin = true;
25
27
  }
26
28
  else {
27
- const browser = this.page.context().browser();
28
- const newContext = await browser.newContext({
29
- storageState: storagePath,
30
- });
31
- const page = await newContext.newPage();
29
+ const page = await this.pageWithAuthState(this.page, storagePath);
32
30
  try {
33
31
  const hasLoggedIn = await this.checkLoggedInFunc(page, this.userContext);
34
32
  shouldDoLogin = !hasLoggedIn;
@@ -44,12 +42,72 @@ class AuthStore {
44
42
  }
45
43
  if (shouldDoLogin) {
46
44
  await this.loginFunc(this.page, this.userContext);
45
+ await this.saveAuthState(storagePath);
46
+ }
47
+ }
48
+ async pageWithAuthState(page, storagePath) {
49
+ if (this.appType === "web-app") {
50
+ // Load state from the file in a new context
51
+ // We create a new context because of Playwright APIs
52
+ const browser = page.context().browser();
53
+ const newContext = await browser.newContext({
54
+ storageState: storagePath,
55
+ });
56
+ return await newContext.newPage();
57
+ }
58
+ else if (this.appType === "chrome-extension") {
59
+ // Load state from chrome.storage.local into the
60
+ // existing browser context
61
+ const context = page.context();
62
+ await AuthStore.loadStateForCrx(context, this.userContext);
63
+ return await context.newPage();
64
+ }
65
+ throw new Error(`unable to load auth state for app type: ${this.appType}`);
66
+ }
67
+ async saveAuthState(storagePath) {
68
+ if (this.appType === "web-app") {
69
+ // Use playwright API to export state to a file
47
70
  await this.page.context().storageState({ path: storagePath });
48
71
  }
72
+ else if (this.appType === "chrome-extension") {
73
+ // Fetch and store state from chrome.storage.local
74
+ const context = this.page.context();
75
+ let [background] = context.serviceWorkers();
76
+ if (!background) {
77
+ background = await context.waitForEvent("serviceworker");
78
+ }
79
+ const storageData = await background.evaluate(() => {
80
+ return new Promise((resolve) => {
81
+ // @ts-ignore
82
+ // eslint-disable-next-line no-undef
83
+ chrome.storage.local.get((items) => {
84
+ resolve(JSON.stringify(items));
85
+ });
86
+ });
87
+ });
88
+ fs_1.default.writeFileSync(storagePath, storageData);
89
+ }
49
90
  }
50
91
  // TODO: make this async
51
92
  static location(userContext) {
52
93
  return `auth/${userContext.key}.json`;
53
94
  }
95
+ static async loadStateForCrx(context, userContext) {
96
+ const storagePath = AuthStore.location(userContext);
97
+ let [background] = context.serviceWorkers();
98
+ if (!background) {
99
+ background = await context.waitForEvent("serviceworker");
100
+ }
101
+ const contents = JSON.parse(fs_1.default.readFileSync(storagePath, { encoding: "utf-8" }));
102
+ await background.evaluate((contents) => {
103
+ return new Promise((resolve) => {
104
+ // @ts-ignore
105
+ // eslint-disable-next-line no-undef
106
+ chrome.storage.local.set(contents, () => {
107
+ resolve("done");
108
+ });
109
+ });
110
+ }, contents);
111
+ }
54
112
  }
55
113
  exports.AuthStore = AuthStore;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/playwright-utils",
3
- "version": "0.14.26",
3
+ "version": "0.14.27",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"