projects/guix·blob java-team · refs

257 lines · 11.0 KiB

1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2025 Danny Milosavljevic <[email protected]>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu packages playwright)
20 #:use-module ((guix licenses) #:prefix license:)
21 #:use-module (guix packages)
22 #:use-module (guix gexp)
23 #:use-module (guix git-download)
24 #:use-module (guix build-system node)
25 #:use-module (guix utils)
26 #:use-module (gnu packages)
27 #:use-module (gnu packages chromium)
28 #:use-module (gnu packages node)
29 #:use-module (gnu packages node-xyz)
30 #:use-module (gnu packages python)
31 #:use-module (gnu packages web))
32
33;; Playwright is a browser automation framework. Upstream provides patched
34;; versions of Firefox and WebKit browsers, but those require building
35;; custom browser forks. This package only supports Chromium-based browsers
36;; (using the system ungoogled-chromium) since Chromium's DevTools Protocol
37;; is sufficient for automation without patches.
38;;
39;; Firefox support would require Playwright's "Juggler" protocol patches.
40;; WebKit support would require Playwright's WebKit automation patches.
41;; Both are invasive changes to browser source code.
42;;
43;; In the future, WebDriver BiDi (a W3C standard) may allow Playwright to
44;; work with unpatched browsers.
45
46(define-public node-playwright-core
47 (package
48 (name "node-playwright-core")
49 (version "1.50.0")
50 (source
51 (origin
52 (method git-fetch)
53 (uri (git-reference
54 (url "https://github.com/microsoft/playwright")
55 (commit (string-append "v" version))))
56 (file-name (git-file-name name version))
57 (sha256
58 (base32 "0xymivpn2c4srbaqdix3qx2zcr6cx5zgs2a20drvi4dmkspn4jz6"))
59 (modules '((guix build utils)))
60 (snippet
61 '(delete-file-recursively "packages/playwright-core/bundles"))))
62 (build-system node-build-system)
63 (arguments
64 (list
65 #:tests? #f ; Tests require browser binaries.
66 #:phases
67 #~(modify-phases %standard-phases
68 (add-after 'unpack 'break-monorepo-structure
69 (lambda _
70 ;; This is a monorepo with npm workspaces. Delete root package.json
71 ;; and lock files to prevent npm from reading workspace config.
72 (delete-file "package.json")
73 (for-each delete-file
74 (find-files "." "package-lock\\.json$"))))
75 (add-after 'break-monorepo-structure 'change-to-package-directory
76 (lambda _
77 (chdir "packages/playwright-core")))
78 (add-after 'unpack 'skip-browser-download
79 (lambda _
80 (setenv "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD" "1")))
81 (add-after 'unpack 'unbundle-dependencies
82 (lambda _
83 (substitute* "packages/playwright-core/src/zipBundle.ts"
84 (("require\\('./zipBundleImpl'\\)\\.yazl")
85 "require('yazl')")
86 (("require\\('./zipBundleImpl'\\)\\.yauzl")
87 "require('yauzl')")
88 (("require\\('./zipBundleImpl'\\)\\.extract")
89 "require('extract-zip')"))
90 (substitute* "packages/playwright-core/src/utilsBundle.ts"
91 (("require\\('./utilsBundleImpl'\\)\\.colors")
92 "require('colors/safe')")
93 (("require\\('./utilsBundleImpl'\\)\\.debug")
94 "require('debug')")
95 (("require\\('./utilsBundleImpl'\\)\\.diff")
96 "require('diff')")
97 (("require\\('./utilsBundleImpl'\\)\\.dotenv")
98 "require('dotenv')")
99 (("require\\('./utilsBundleImpl'\\)\\.getProxyForUrl")
100 "require('proxy-from-env').getProxyForUrl")
101 (("require\\('./utilsBundleImpl'\\)\\.HttpsProxyAgent")
102 "require('https-proxy-agent').HttpsProxyAgent")
103 (("require\\('./utilsBundleImpl'\\)\\.jpegjs")
104 "require('jpeg-js')")
105 (("require\\('./utilsBundleImpl'\\)\\.lockfile")
106 "require('proper-lockfile')")
107 (("require\\('./utilsBundleImpl'\\)\\.mime")
108 "require('mime')")
109 (("require\\('./utilsBundleImpl'\\)\\.minimatch")
110 "require('minimatch')")
111 (("require\\('./utilsBundleImpl'\\)\\.open")
112 "require('open')")
113 (("require\\('./utilsBundleImpl'\\)\\.PNG")
114 "require('pngjs').PNG")
115 (("require\\('./utilsBundleImpl'\\)\\.program")
116 "require('commander').program")
117 (("require\\('./utilsBundleImpl'\\)\\.progress")
118 "require('progress')")
119 (("require\\('./utilsBundleImpl'\\)\\.SocksProxyAgent")
120 "require('socks-proxy-agent').SocksProxyAgent")
121 (("require\\('./utilsBundleImpl'\\)\\.yaml")
122 "require('yaml')")
123 (("require\\('./utilsBundleImpl'\\)\\.wsServer")
124 "require('ws').WebSocketServer")
125 (("require\\('./utilsBundleImpl'\\)\\.wsReceiver")
126 "require('ws').Receiver")
127 (("require\\('./utilsBundleImpl'\\)\\.wsSender")
128 "require('ws').Sender")
129 (("require\\('./utilsBundleImpl'\\)\\.ws\\b")
130 "require('ws')")
131 (("require\\('./utilsBundleImpl'\\)\\.StackUtils")
132 "require('stack-utils')"))))
133 (add-after 'unbundle-dependencies 'add-unbundled-dependencies
134 (lambda _
135 ;; Add dependencies that were unbundled from utilsBundle/zipBundle.
136 ;; Must run before patch-dependencies which minifies package.json.
137 (modify-json
138 #:file "packages/playwright-core/package.json"
139 (lambda (pkg)
140 (acons "dependencies"
141 '(("colors" . "*")
142 ("commander" . "*")
143 ("debug" . "*")
144 ("diff" . "*")
145 ("dotenv" . "*")
146 ("extract-zip" . "*")
147 ("https-proxy-agent" . "*")
148 ("jpeg-js" . "*")
149 ("mime" . "*")
150 ("minimatch" . "*")
151 ("open" . "*")
152 ("pngjs" . "*")
153 ("progress" . "*")
154 ("proper-lockfile" . "*")
155 ("proxy-from-env" . "*")
156 ("socks-proxy-agent" . "*")
157 ("stack-utils" . "*")
158 ("ws" . "*")
159 ("yaml" . "*")
160 ("yazl" . "*")
161 ("yauzl" . "*"))
162 pkg)))))
163 (add-before 'build 'generate-injected-scripts
164 (lambda _
165 ;; Run generate_injected.js to create src/generated/*.ts files.
166 (invoke "node" "../../utils/generate_injected.js")))
167 (add-after 'generate-injected-scripts 'add-build-script
168 (lambda _
169 ;; Upstream uses Babel, but Babel isn't packaged. Use esbuild.
170 ;; Compile TypeScript and copy non-TS files (JS, JSON, PNG).
171 (modify-json
172 (lambda (pkg)
173 (acons "scripts"
174 '(("build" . "find src -name '*.ts' | xargs esbuild --outdir=lib --format=cjs --platform=node && cp -r src/third_party lib/ && find src \\( -name '*.json' -o -name '*.png' \\) -exec sh -c 'mkdir -p lib/$(dirname ${0#src/}) && cp $0 lib/${0#src/}' {} \\;"))
175 pkg)))))
176 (add-before 'install 'set-cc
177 (lambda _
178 (setenv "CC" #$(cc-for-target))))
179 (add-after 'install 'wrap-playwright-cli
180 (lambda* (#:key inputs outputs #:allow-other-keys)
181 (let* ((out (assoc-ref outputs "out"))
182 (cli (string-append out "/lib/node_modules/playwright-core/cli.js")))
183 (wrap-program cli
184 ;; Avoid vite dependency.
185 `("PW_CODEGEN_NO_INSPECTOR" = ("1"))
186 `("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD" = ("1")))))))))
187 (inputs
188 (list node-esbuild
189 ;; Dependencies (unbundled from utilsBundle).
190 node-colors
191 node-commander
192 node-debug
193 node-diff
194 node-dotenv
195 node-graceful-fs
196 node-https-proxy-agent
197 node-jpeg-js
198 node-mime
199 node-minimatch-3
200 node-ms
201 node-open
202 node-pngjs
203 node-progress
204 node-proper-lockfile
205 node-proxy-from-env
206 node-retry
207 node-signal-exit
208 node-socks-proxy-agent
209 node-stack-utils
210 node-ws
211 node-yaml
212 ;; Dependencies (unbundled from zipBundle).
213 node-yazl
214 node-yauzl
215 node-extract-zip))
216 (native-inputs
217 (list esbuild python))
218 (native-search-paths
219 (list
220 (search-path-specification
221 (variable "PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH")
222 (file-type 'regular)
223 (separator #f) ;single entry
224 (files '("bin/chromium")))
225 (search-path-specification
226 (variable "PWTEST_CLI_EXECUTABLE_PATH")
227 (file-type 'regular)
228 (separator #f) ;single entry
229 (files '("bin/chromium")))))
230 (home-page "https://playwright.dev/")
231 (synopsis "Browser automation library (Chromium-only)")
232 (description
233 "Playwright is a framework for browser automation and end-to-end testing.
234This package provides @code{playwright-core}, the library without bundled
235browsers.
236
237@strong{Important}: This package only supports Chromium-based browsers.
238Firefox and WebKit are not supported because Playwright requires custom-patched
239versions of those browsers that are not packaged for Guix.
240
241To use Playwright with the system Chromium, either:
242@enumerate
243@item
244Set the environment variable @env{PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH} to the
245Chromium binary path, or
246@item
247Use the @code{executablePath} option in your Playwright code:
248@example
249const browser = await chromium.launch(@{
250 executablePath: '/run/current-system/profile/bin/chromium'
251@});
252@end example
253
254For the command line variant $code{playwright-core}, set the environment
255variable $env{PWTEST_CLI_EXECUTABLE_PATH} to the Chromium binary path.
256@end enumerate")
257 (license license:asl2.0)))