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 }