Skip to content

Commit

Permalink
feat: Add xctest init command (#1006)
Browse files Browse the repository at this point in the history
* Add xctest init command

---------

Co-authored-by: Alex Plischke <[email protected]>
  • Loading branch information
rillgen-saucelabs and alexplischke authored Jan 24, 2025
1 parent 20c83cf commit 23fc96b
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 68 deletions.
34 changes: 0 additions & 34 deletions api/saucectl.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2529,35 +2529,6 @@
}
}
},
"simulators": {
"description": "Defines details for running this suite on virtual devices using a simulator.",
"type": "array",
"items": {
"properties": {
"name": {
"description": "The name of the simulator. To ensure name accuracy, check the list of supported virtual devices (https://app.saucelabs.com/live/web-testing/virtual).",
"type": "string"
},
"orientation": {
"$ref": "#/allOf/1/then/properties/suites/items/properties/emulators/items/properties/orientation"
},
"platformVersions": {
"description": "The set of one or more versions of the device platform on which to run the test suite.",
"type": "array",
"minItems": 1
},
"armRequired": {
"description": "If set to true, the simulator will run on an ARM-based Mac. If set to false, the simulator will run on an Intel-based Mac.",
"type": "boolean"
}
},
"required": [
"name",
"platformVersions"
],
"additionalProperties": false
}
},
"devices": {
"description": "Define details for running this suite on real devices.",
"type": "array",
Expand Down Expand Up @@ -2645,11 +2616,6 @@
}
},
"anyOf": [
{
"required": [
"simulators"
]
},
{
"required": [
"devices"
Expand Down
34 changes: 0 additions & 34 deletions api/v1alpha/framework/xctest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,35 +182,6 @@
}
}
},
"simulators": {
"description": "Defines details for running this suite on virtual devices using a simulator.",
"type": "array",
"items": {
"properties": {
"name": {
"description": "The name of the simulator. To ensure name accuracy, check the list of supported virtual devices (https://app.saucelabs.com/live/web-testing/virtual).",
"type": "string"
},
"orientation": {
"$ref": "../subschema/common.schema.json#/definitions/orientation"
},
"platformVersions": {
"description": "The set of one or more versions of the device platform on which to run the test suite.",
"type": "array",
"minItems": 1
},
"armRequired": {
"description": "If set to true, the simulator will run on an ARM-based Mac. If set to false, the simulator will run on an Intel-based Mac.",
"type": "boolean"
}
},
"required": [
"name",
"platformVersions"
],
"additionalProperties": false
}
},
"devices": {
"description": "Define details for running this suite on real devices.",
"type": "array",
Expand Down Expand Up @@ -298,11 +269,6 @@
}
},
"anyOf": [
{
"required": [
"simulators"
]
},
{
"required": [
"devices"
Expand Down
5 changes: 5 additions & 0 deletions internal/cmd/ini/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/saucelabs/saucectl/internal/msg"
"github.com/saucelabs/saucectl/internal/playwright"
"github.com/saucelabs/saucectl/internal/testcafe"
"github.com/saucelabs/saucectl/internal/xctest"
"github.com/saucelabs/saucectl/internal/xcuitest"

"github.com/AlecAivazis/survey/v2/terminal"
Expand All @@ -40,6 +41,7 @@ type initConfig struct {
dockerImage string
app string
testApp string
xctestRunFile string
otherApps []string
platformName string
browserName string
Expand Down Expand Up @@ -92,6 +94,7 @@ func Command(preRun func(cmd *cobra.Command, args []string)) *cobra.Command {
PlaywrightCmd(),
TestCafeCmd(),
XCUITestCmd(),
XCTestCmd(),
)

flags := cmd.PersistentFlags()
Expand Down Expand Up @@ -186,6 +189,8 @@ func noPromptMode(cmd *cobra.Command, cfg *initConfig) error {
errs = ini.initializeBatchTestcafe(cmd.Context())
case xcuitest.Kind:
errs = ini.initializeBatchXcuitest(cmd.Flags())
case xctest.Kind:
errs = ini.initializeBatchXctest(cmd.Flags())
case imagerunner.Kind:
errs = ini.initializeBatchImageRunner()
default:
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/ini/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var configurators = map[string]func(cfg *initConfig) interface{}{
"playwright": configurePlaywright,
"testcafe": configureTestcafe,
"xcuitest": configureXCUITest,
"xctest": configureXCTest,
"imagerunner": configureImageRunner,
}

Expand Down
71 changes: 71 additions & 0 deletions internal/cmd/ini/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/testcafe"
"github.com/saucelabs/saucectl/internal/vmd"
"github.com/saucelabs/saucectl/internal/xctest"
"github.com/saucelabs/saucectl/internal/xcuitest"
"github.com/spf13/pflag"
)
Expand Down Expand Up @@ -85,6 +86,8 @@ func (ini *initializer) configure(ctx context.Context) error {
return ini.initializeEspresso(ctx)
case xcuitest.Kind:
return ini.initializeXCUITest(ctx)
case xctest.Kind:
return ini.initializeXCTest()
case imagerunner.Kind:
return ini.initializeImageRunner()
default:
Expand Down Expand Up @@ -652,6 +655,31 @@ func (ini *initializer) initializeXCUITest(ctx context.Context) error {
return nil
}

func (ini *initializer) initializeXCTest() error {
var err error

err = ini.askDevice(iOSDevicesPatterns)
if err != nil {
return err
}
err = ini.askFile("Application to test:", extValidator([]string{".ipa", ".app"}), completeBasic, &ini.cfg.app)
if err != nil {
return err
}

err = ini.askFile("XCTestRun file:", extValidator([]string{".xctestrun"}), completeBasic, &ini.cfg.xctestRunFile)
if err != nil {
return err
}

err = ini.askDownloadWhen()
if err != nil {
return err
}

return nil
}

func (ini *initializer) initializeImageRunner() error {
if err := ini.askDockerImage(
"Docker Image to use:",
Expand Down Expand Up @@ -985,6 +1013,49 @@ func (ini *initializer) initializeBatchXcuitest(f *pflag.FlagSet) []error {
return errs
}

func (ini *initializer) initializeBatchXctest(f *pflag.FlagSet) []error {
var errs []error
var err error

if ini.cfg.app == "" {
errs = append(errs, errors.New(msg.MissingApp))
}
if ini.cfg.xctestRunFile == "" {
errs = append(errs, errors.New(msg.MissingXCTestFileAppPath))
}
if !f.Changed("device") {
errs = append(errs, errors.New(msg.MissingDevice))
}
if ini.cfg.artifactWhenStr != "" {
ini.cfg.artifactWhenStr = strings.ToLower(ini.cfg.artifactWhenStr)
if ini.cfg.artifactWhen, err = checkArtifactDownloadSetting(ini.cfg.artifactWhenStr); err != nil {
errs = append(errs, err)
}
}
validAppExt := []string{".app"}
if f.Changed("simulator") {
validAppExt = append(validAppExt, ".zip")
} else {
validAppExt = append(validAppExt, ".ipa")
}
if ini.cfg.app != "" {
verifier := extValidator(validAppExt)
if err = verifier(ini.cfg.app); err != nil {
errs = append(errs, fmt.Errorf("app: %s", err))
}
}
if ini.cfg.xctestRunFile != "" {
verifier := extValidator([]string{".xctestrun"})
if err = verifier(ini.cfg.xctestRunFile); err != nil {
errs = append(errs, fmt.Errorf("xctestRunFile: %s", err))
}
}
if f.Changed("device") {
ini.cfg.device = ini.cfg.deviceFlag.Device
}
return errs
}

func (ini *initializer) initializeBatchImageRunner() []error {
var errs []error
var err error
Expand Down
93 changes: 93 additions & 0 deletions internal/cmd/ini/xctest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ini

import (
"fmt"
"os"

"github.com/rs/zerolog/log"
cmds "github.com/saucelabs/saucectl/internal/cmd"
"github.com/saucelabs/saucectl/internal/config"
"github.com/saucelabs/saucectl/internal/usage"
"github.com/saucelabs/saucectl/internal/xctest"
"github.com/spf13/cobra"
)

func XCTestCmd() *cobra.Command {
cfg := &initConfig{
frameworkName: xctest.Kind,
}

cmd := &cobra.Command{
Use: "xctest",
Short: "Bootstrap an XCTest project.",
SilenceUsage: true,
Run: func(cmd *cobra.Command, _ []string) {
tracker := usage.DefaultClient

go func() {
tracker.Collect(
cmds.FullName(cmd),
usage.Flags(cmd.Flags()),
)
_ = tracker.Close()
}()

err := Run(cmd, cfg)
if err != nil {
log.Err(err).Msg("failed to execute init command")
os.Exit(1)
}
},
}

cmd.Flags().StringVar(&cfg.app, "app", "", "Path to application under test.")
cmd.Flags().StringVar(&cfg.xctestRunFile, "xctest-run-file", "", "Path to xctest descriptor file.")
cmd.Flags().StringSliceVar(&cfg.otherApps, "other-apps", []string{}, "Path to additional applications.")
cmd.Flags().StringVar(&cfg.artifactWhenStr, "artifacts-when", "fail", "When to download artifacts.")
cmd.Flags().Var(&cfg.deviceFlag, "device", "The device to use for testing.")

return cmd
}

func configureXCTest(cfg *initConfig) interface{} {
suites := []xctest.Suite{}
if cfg.device.Name != "" {
suites = append(suites, xctest.Suite{
Name: fmt.Sprintf("xctest - %s", cfg.device.Name),
Devices: []config.Device{cfg.device},
App: cfg.app,
XCTestRunFile: cfg.xctestRunFile,
OtherApps: cfg.otherApps,
})
}
if cfg.simulator.Name != "" {
suites = append(suites, xctest.Suite{
Name: fmt.Sprintf("xctest - %s", cfg.simulator.Name),
Simulators: []config.Simulator{cfg.simulator},
App: cfg.app,
XCTestRunFile: cfg.xctestRunFile,
OtherApps: cfg.otherApps,
})
}
return xctest.Project{
TypeDef: config.TypeDef{
APIVersion: xctest.APIVersion,
Kind: xctest.Kind,
},
Sauce: config.SauceConfig{
Region: cfg.region,
Concurrency: cfg.concurrency,
},
Xctest: xctest.Xctest{
OtherApps: cfg.otherApps,
},
Suites: suites,
Artifacts: config.Artifacts{
Download: config.ArtifactDownload{
When: cfg.artifactWhen,
Directory: "./artifacts",
Match: []string{"*"},
},
},
}
}

0 comments on commit 23fc96b

Please sign in to comment.