diff options
| author | mo khan <mo@mokhan.ca> | 2025-05-12 16:33:27 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-05-12 16:33:27 -0600 |
| commit | 29b59441a4bbada64d8d07bd2609f15dfde670e5 (patch) | |
| tree | 3b3583edb261279cfcdfd9eed904d118c4bf67b1 /vendor/github.com/playwright-community/playwright-go/run.go | |
| parent | 78ccd9a4312eab7e11da4413733a12953f88a4fe (diff) | |
test: remove UI tests
Diffstat (limited to 'vendor/github.com/playwright-community/playwright-go/run.go')
| -rw-r--r-- | vendor/github.com/playwright-community/playwright-go/run.go | 409 |
1 files changed, 0 insertions, 409 deletions
diff --git a/vendor/github.com/playwright-community/playwright-go/run.go b/vendor/github.com/playwright-community/playwright-go/run.go deleted file mode 100644 index 79ad11e..0000000 --- a/vendor/github.com/playwright-community/playwright-go/run.go +++ /dev/null @@ -1,409 +0,0 @@ -package playwright - -import ( - "archive/zip" - "bytes" - "errors" - "fmt" - "io" - "log" - "log/slog" - "net/http" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" -) - -const playwrightCliVersion = "1.52.0" - -var ( - logger = slog.Default() - playwrightCDNMirrors = []string{ - "https://playwright.azureedge.net", - "https://playwright-akamai.azureedge.net", - "https://playwright-verizon.azureedge.net", - } -) - -// PlaywrightDriver wraps the Playwright CLI of upstream Playwright. -// -// It's required for playwright-go to work. -type PlaywrightDriver struct { - Version string - options *RunOptions -} - -func NewDriver(options ...*RunOptions) (*PlaywrightDriver, error) { - transformed, err := transformRunOptions(options...) // get default values - if err != nil { - return nil, err - } - return &PlaywrightDriver{ - options: transformed, - Version: playwrightCliVersion, - }, nil -} - -func getDefaultCacheDirectory() (string, error) { - userHomeDir, err := os.UserHomeDir() - if err != nil { - return "", fmt.Errorf("could not get user home directory: %w", err) - } - switch runtime.GOOS { - case "windows": - return filepath.Join(userHomeDir, "AppData", "Local"), nil - case "darwin": - return filepath.Join(userHomeDir, "Library", "Caches"), nil - case "linux": - return filepath.Join(userHomeDir, ".cache"), nil - } - return "", errors.New("could not determine cache directory") -} - -func (d *PlaywrightDriver) isUpToDateDriver() (bool, error) { - if _, err := os.Stat(d.options.DriverDirectory); os.IsNotExist(err) { - if err := os.MkdirAll(d.options.DriverDirectory, 0o777); err != nil { - return false, fmt.Errorf("could not create driver directory: %w", err) - } - } - if _, err := os.Stat(getDriverCliJs(d.options.DriverDirectory)); os.IsNotExist(err) { - return false, nil - } else if err != nil { - return false, fmt.Errorf("could not check if driver is up2date: %w", err) - } - cmd := d.Command("--version") - output, err := cmd.Output() - if err != nil { - return false, fmt.Errorf("could not run driver: %w", err) - } - if bytes.Contains(output, []byte(d.Version)) { - return true, nil - } - // avoid triggering downloads and accidentally overwriting files - return false, fmt.Errorf("driver exists but version not %s in : %s", d.Version, d.options.DriverDirectory) -} - -// Command returns an exec.Cmd for the driver. -func (d *PlaywrightDriver) Command(arg ...string) *exec.Cmd { - cmd := exec.Command(getNodeExecutable(d.options.DriverDirectory), append([]string{getDriverCliJs(d.options.DriverDirectory)}, arg...)...) - cmd.SysProcAttr = defaultSysProcAttr - return cmd -} - -// Install downloads the driver and the browsers depending on [RunOptions]. -func (d *PlaywrightDriver) Install() error { - if err := d.DownloadDriver(); err != nil { - return fmt.Errorf("could not install driver: %w", err) - } - if d.options.SkipInstallBrowsers { - return nil - } - - d.log("Downloading browsers...") - if err := d.installBrowsers(); err != nil { - return fmt.Errorf("could not install browsers: %w", err) - } - d.log("Downloaded browsers successfully") - - return nil -} - -// Uninstall removes the driver and the browsers. -func (d *PlaywrightDriver) Uninstall() error { - d.log("Removing browsers...") - if err := d.uninstallBrowsers(); err != nil { - return fmt.Errorf("could not uninstall browsers: %w", err) - } - - d.log("Removing driver...") - if err := os.RemoveAll(d.options.DriverDirectory); err != nil { - return fmt.Errorf("could not remove driver directory: %w", err) - } - - d.log("Uninstall driver successfully") - return nil -} - -// DownloadDriver downloads the driver only -func (d *PlaywrightDriver) DownloadDriver() error { - up2Date, err := d.isUpToDateDriver() - if err != nil { - return err - } - if up2Date { - return nil - } - - d.log("Downloading driver", "path", d.options.DriverDirectory) - - body, err := downloadDriver(d.getDriverURLs()) - if err != nil { - return err - } - zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) - if err != nil { - return fmt.Errorf("could not read zip content: %w", err) - } - - for _, zipFile := range zipReader.File { - zipFileDiskPath := filepath.Join(d.options.DriverDirectory, zipFile.Name) - if zipFile.FileInfo().IsDir() { - if err := os.MkdirAll(zipFileDiskPath, os.ModePerm); err != nil { - return fmt.Errorf("could not create directory: %w", err) - } - continue - } - - outFile, err := os.Create(zipFileDiskPath) - if err != nil { - return fmt.Errorf("could not create driver: %w", err) - } - file, err := zipFile.Open() - if err != nil { - return fmt.Errorf("could not open zip file: %w", err) - } - if _, err = io.Copy(outFile, file); err != nil { - return fmt.Errorf("could not copy response body to file: %w", err) - } - if err := outFile.Close(); err != nil { - return fmt.Errorf("could not close file (driver): %w", err) - } - if err := file.Close(); err != nil { - return fmt.Errorf("could not close file (zip file): %w", err) - } - if zipFile.Mode().Perm()&0o100 != 0 && runtime.GOOS != "windows" { - if err := makeFileExecutable(zipFileDiskPath); err != nil { - return fmt.Errorf("could not make executable: %w", err) - } - } - } - - d.log("Downloaded driver successfully") - - return nil -} - -func (d *PlaywrightDriver) log(msg string, args ...any) { - if d.options.Verbose { - logger.Info(msg, args...) - } -} - -func (d *PlaywrightDriver) run() (*connection, error) { - transport, err := newPipeTransport(d, d.options.Stderr) - if err != nil { - return nil, err - } - connection := newConnection(transport) - return connection, nil -} - -func (d *PlaywrightDriver) installBrowsers() error { - additionalArgs := []string{"install"} - if d.options.Browsers != nil { - additionalArgs = append(additionalArgs, d.options.Browsers...) - } - - if d.options.OnlyInstallShell { - additionalArgs = append(additionalArgs, "--only-shell") - } - - if d.options.DryRun { - additionalArgs = append(additionalArgs, "--dry-run") - } - - cmd := d.Command(additionalArgs...) - cmd.Stdout = d.options.Stdout - cmd.Stderr = d.options.Stderr - return cmd.Run() -} - -func (d *PlaywrightDriver) uninstallBrowsers() error { - cmd := d.Command("uninstall") - cmd.Stdout = d.options.Stdout - cmd.Stderr = d.options.Stderr - return cmd.Run() -} - -// RunOptions are custom options to run the driver -type RunOptions struct { - // DriverDirectory points to the playwright driver directory. - // It should have two subdirectories: node and package. - // You can also specify it using the environment variable PLAYWRIGHT_DRIVER_PATH. - // - // Default is user cache directory + "/ms-playwright-go/x.xx.xx": - // - Windows: %USERPROFILE%\AppData\Local - // - macOS: ~/Library/Caches - // - Linux: ~/.cache - DriverDirectory string - // OnlyInstallShell only downloads the headless shell. (For chromium browsers only) - OnlyInstallShell bool - SkipInstallBrowsers bool - // if not set and SkipInstallBrowsers is false, will download all browsers (chromium, firefox, webkit) - Browsers []string - Verbose bool // default true - Stdout io.Writer - Stderr io.Writer - Logger *slog.Logger - // DryRun does not install browser/dependencies. It will only print information. - DryRun bool -} - -// Install does download the driver and the browsers. -// -// Use this before playwright.Run() or use playwright cli to install the driver and browsers -func Install(options ...*RunOptions) error { - driver, err := NewDriver(options...) - if err != nil { - return fmt.Errorf("could not get driver instance: %w", err) - } - if err := driver.Install(); err != nil { - return fmt.Errorf("could not install driver: %w", err) - } - return nil -} - -// Run starts a Playwright instance. -// -// Requires the driver and the browsers to be installed before. -// Either use Install() or use playwright cli. -func Run(options ...*RunOptions) (*Playwright, error) { - driver, err := NewDriver(options...) - if err != nil { - return nil, fmt.Errorf("could not get driver instance: %w", err) - } - up2date, err := driver.isUpToDateDriver() - if err != nil || !up2date { - return nil, fmt.Errorf("please install the driver (v%s) first: %w", playwrightCliVersion, err) - } - connection, err := driver.run() - if err != nil { - return nil, err - } - playwright, err := connection.Start() - return playwright, err -} - -func transformRunOptions(options ...*RunOptions) (*RunOptions, error) { - option := &RunOptions{ - Verbose: true, - } - if len(options) == 1 { - option = options[0] - } - if option.DriverDirectory == "" { // if user did not set it, try to get it from env - option.DriverDirectory = os.Getenv("PLAYWRIGHT_DRIVER_PATH") - } - if option.DriverDirectory == "" { - cacheDirectory, err := getDefaultCacheDirectory() - if err != nil { - return nil, fmt.Errorf("could not get default cache directory: %w", err) - } - option.DriverDirectory = filepath.Join(cacheDirectory, "ms-playwright-go", playwrightCliVersion) - } - if option.Stdout == nil { - option.Stdout = os.Stdout - } - if option.Stderr == nil { - option.Stderr = os.Stderr - } else if option.Logger == nil { - log.SetOutput(option.Stderr) - } - if option.Logger != nil { - logger = option.Logger - } - return option, nil -} - -func getNodeExecutable(driverDirectory string) string { - envPath := os.Getenv("PLAYWRIGHT_NODEJS_PATH") - if envPath != "" { - return envPath - } - - node := "node" - if runtime.GOOS == "windows" { - node = "node.exe" - } - return filepath.Join(driverDirectory, node) -} - -func getDriverCliJs(driverDirectory string) string { - return filepath.Join(driverDirectory, "package", "cli.js") -} - -func (d *PlaywrightDriver) getDriverURLs() []string { - platform := "" - switch runtime.GOOS { - case "windows": - platform = "win32_x64" - case "darwin": - if runtime.GOARCH == "arm64" { - platform = "mac-arm64" - } else { - platform = "mac" - } - case "linux": - if runtime.GOARCH == "arm64" { - platform = "linux-arm64" - } else { - platform = "linux" - } - } - - baseURLs := []string{} - pattern := "%s/builds/driver/playwright-%s-%s.zip" - if !d.isReleaseVersion() { - pattern = "%s/builds/driver/next/playwright-%s-%s.zip" - } - - if hostEnv := os.Getenv("PLAYWRIGHT_DOWNLOAD_HOST"); hostEnv != "" { - baseURLs = append(baseURLs, fmt.Sprintf(pattern, hostEnv, d.Version, platform)) - } else { - for _, mirror := range playwrightCDNMirrors { - baseURLs = append(baseURLs, fmt.Sprintf(pattern, mirror, d.Version, platform)) - } - } - return baseURLs -} - -// isReleaseVersion checks if the version is not a beta or alpha release -// this helps to determine the url from where to download the driver -func (d *PlaywrightDriver) isReleaseVersion() bool { - return !strings.Contains(d.Version, "beta") && !strings.Contains(d.Version, "alpha") && !strings.Contains(d.Version, "next") -} - -func makeFileExecutable(path string) error { - stats, err := os.Stat(path) - if err != nil { - return fmt.Errorf("could not stat driver: %w", err) - } - if err := os.Chmod(path, stats.Mode()|0x40); err != nil { - return fmt.Errorf("could not set permissions: %w", err) - } - return nil -} - -func downloadDriver(driverURLs []string) (body []byte, e error) { - for _, driverURL := range driverURLs { - resp, err := http.Get(driverURL) - if err != nil { - e = errors.Join(e, fmt.Errorf("could not download driver from %s: %w", driverURL, err)) - continue - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - e = errors.Join(e, fmt.Errorf("error: got non 200 status code: %d (%s) from %s", resp.StatusCode, resp.Status, driverURL)) - continue - } - body, err = io.ReadAll(resp.Body) - if err != nil { - e = errors.Join(e, fmt.Errorf("could not read response body: %w", err)) - continue - } - return body, nil - } - return nil, e -} |
