github.com/saucelabs/saucectl@v0.175.1/internal/saucecloud/playwright.go (about)

     1  package saucecloud
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/rs/zerolog/log"
     9  	"github.com/saucelabs/saucectl/internal/framework"
    10  	"github.com/saucelabs/saucectl/internal/msg"
    11  
    12  	"github.com/saucelabs/saucectl/internal/job"
    13  	"github.com/saucelabs/saucectl/internal/playwright"
    14  )
    15  
    16  // PlaywrightRunner represents the Sauce Labs cloud implementation for playwright.
    17  type PlaywrightRunner struct {
    18  	CloudRunner
    19  	Project playwright.Project
    20  }
    21  
    22  var PlaywrightBrowserMap = map[string]string{
    23  	"chromium": "playwright-chromium",
    24  	"firefox":  "playwright-firefox",
    25  	"webkit":   "playwright-webkit",
    26  }
    27  
    28  // RunProject runs the tests defined in cypress.Project.
    29  func (r *PlaywrightRunner) RunProject() (int, error) {
    30  	var deprecationMessage string
    31  	exitCode := 1
    32  
    33  	m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, playwright.Kind, r.Project.Playwright.Version)
    34  	if err != nil {
    35  		r.logFrameworkError(err)
    36  		return exitCode, err
    37  	}
    38  	r.Project.Playwright.Version = m.FrameworkVersion
    39  	if r.Project.RunnerVersion == "" {
    40  		r.Project.RunnerVersion = m.CloudRunnerVersion
    41  	}
    42  
    43  	if m.IsDeprecated() && !m.IsFlaggedForRemoval() {
    44  		deprecationMessage = r.deprecationMessage(playwright.Kind, r.Project.Playwright.Version, m.RemovalDate)
    45  		fmt.Print(deprecationMessage)
    46  	}
    47  	if m.IsFlaggedForRemoval() {
    48  		deprecationMessage = r.flaggedForRemovalMessage(playwright.Kind, r.Project.Playwright.Version)
    49  		fmt.Print(deprecationMessage)
    50  	}
    51  
    52  	for i, s := range r.Project.Suites {
    53  		if s.PlatformName != "" && !framework.HasPlatform(m, s.PlatformName) {
    54  			msg.LogUnsupportedPlatform(s.PlatformName, framework.PlatformNames(m.Platforms))
    55  			return 1, errors.New("unsupported platform")
    56  		}
    57  		r.Project.Suites[i].Params.BrowserVersion = m.BrowserDefaults[PlaywrightBrowserMap[s.Params.BrowserName]]
    58  	}
    59  
    60  	if err := r.validateTunnel(
    61  		r.Project.Sauce.Tunnel.Name,
    62  		r.Project.Sauce.Tunnel.Owner,
    63  		r.Project.DryRun,
    64  		r.Project.Sauce.Tunnel.Timeout,
    65  	); err != nil {
    66  		return 1, err
    67  	}
    68  
    69  	app, otherApps, err := r.remoteArchiveProject(r.Project, r.Project.RootDir, r.Project.Sauce.Sauceignore, r.Project.DryRun)
    70  	if err != nil {
    71  		return exitCode, err
    72  	}
    73  
    74  	if r.Project.DryRun {
    75  		printDryRunSuiteNames(r.getSuiteNames())
    76  		return 0, nil
    77  	}
    78  
    79  	passed := r.runSuites(app, otherApps)
    80  	if passed {
    81  		exitCode = 0
    82  	}
    83  
    84  	if deprecationMessage != "" {
    85  		fmt.Print(deprecationMessage)
    86  	}
    87  
    88  	return exitCode, nil
    89  }
    90  
    91  func (r *PlaywrightRunner) getSuiteNames() []string {
    92  	var names []string
    93  	for _, s := range r.Project.Suites {
    94  		names = append(names, s.Name)
    95  	}
    96  	return names
    97  }
    98  
    99  func (r *PlaywrightRunner) runSuites(app string, otherApps []string) bool {
   100  	sigChan := r.registerSkipSuitesOnSignal()
   101  	defer unregisterSignalCapture(sigChan)
   102  
   103  	jobOpts, results, err := r.createWorkerPool(r.Project.Sauce.Concurrency, r.Project.Sauce.Retries)
   104  	if err != nil {
   105  		return false
   106  	}
   107  	defer close(results)
   108  
   109  	suites := r.Project.Suites
   110  	if r.Project.Sauce.LaunchOrder != "" {
   111  		history, err := r.getHistory(r.Project.Sauce.LaunchOrder)
   112  		if err != nil {
   113  			log.Warn().Err(err).Msg(msg.RetrieveJobHistoryError)
   114  		} else {
   115  			suites = playwright.SortByHistory(suites, history)
   116  		}
   117  	}
   118  	// Submit suites to work on.
   119  	go func() {
   120  		for _, s := range suites {
   121  			// Define frameworkVersion if not set at suite level
   122  			if s.PlaywrightVersion == "" {
   123  				s.PlaywrightVersion = r.Project.Playwright.Version
   124  			}
   125  			jobOpts <- job.StartOptions{
   126  				ConfigFilePath:   r.Project.ConfigFilePath,
   127  				CLIFlags:         r.Project.CLIFlags,
   128  				DisplayName:      s.Name,
   129  				Timeout:          s.Timeout,
   130  				App:              app,
   131  				OtherApps:        otherApps,
   132  				Suite:            s.Name,
   133  				Framework:        "playwright",
   134  				FrameworkVersion: s.PlaywrightVersion,
   135  				BrowserName:      s.Params.BrowserName,
   136  				BrowserVersion:   s.Params.BrowserVersion,
   137  				PlatformName:     s.PlatformName,
   138  				Name:             s.Name,
   139  				Build:            r.Project.Sauce.Metadata.Build,
   140  				Tags:             r.Project.Sauce.Metadata.Tags,
   141  				Tunnel: job.TunnelOptions{
   142  					ID:     r.Project.Sauce.Tunnel.Name,
   143  					Parent: r.Project.Sauce.Tunnel.Owner,
   144  				},
   145  				ScreenResolution: s.ScreenResolution,
   146  				RunnerVersion:    r.Project.RunnerVersion,
   147  				Experiments:      r.Project.Sauce.Experiments,
   148  				Attempt:          0,
   149  				Retries:          r.Project.Sauce.Retries,
   150  				TimeZone:         s.TimeZone,
   151  				Visibility:       r.Project.Sauce.Visibility,
   152  				PassThreshold:    s.PassThreshold,
   153  				SmartRetry: job.SmartRetry{
   154  					FailedOnly: s.SmartRetry.IsRetryFailedOnly(),
   155  				},
   156  			}
   157  		}
   158  	}()
   159  
   160  	return r.collectResults(r.Project.Artifacts.Download, results, len(r.Project.Suites))
   161  }