From 17227ed41d593e04e0db88476c6f971a491c5f43 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Fri, 20 Dec 2024 15:52:33 +0200 Subject: [PATCH] Test on Windows and MacOS --- .github/workflows/ci.yaml | 60 ++++++++-- .gitignore | 3 +- main_test.go | 8 +- plugin/digitizer/digitizer_plugin_test.go | 8 +- .../orchestrator/orchestrator_plugin_test.go | 8 +- plugin/studio/studio_plugin_test.go | 101 ---------------- plugin/studio/studio_plugin_windows_test.go | 112 ++++++++++++++++++ test/execution_test.go | 4 +- test/setup.go | 20 +++- utils/file_stream_test.go | 2 + 10 files changed, 205 insertions(+), 121 deletions(-) create mode 100644 plugin/studio/studio_plugin_windows_test.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cda25f8..5d3e28e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,6 +3,7 @@ on: [push] env: UIPATHCLI_BASE_VERSION: "v1.1" + GO_VERSION: "1.22.2" jobs: build: @@ -17,7 +18,7 @@ jobs: - name: Setup go uses: actions/setup-go@v5 with: - go-version: '1.22.2' + go-version: ${{ env.GO_VERSION }} cache: true - name: Version id: version @@ -25,14 +26,31 @@ jobs: UIPATHCLI_VERSION=$(./version.sh "$UIPATHCLI_BASE_VERSION") echo "UIPATHCLI_VERSION=$(echo $UIPATHCLI_VERSION)" >> $GITHUB_ENV echo "UIPATHCLI_VERSION=$(echo $UIPATHCLI_VERSION)" >> $GITHUB_OUTPUT - - name: Install dependencies - run: go get . - name: Build run: go build -ldflags="-X github.com/UiPath/uipathcli/commandline.Version=$UIPATHCLI_VERSION" . - name: Lint run: | go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 golangci-lint run + - name: Package + run: ./build.sh && ./package.sh + - name: Upload packages + uses: actions/upload-artifact@v4 + with: + name: packages + path: build/packages/ + if-no-files-found: error + + test_linux: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache: true - name: Test run: go test -coverprofile="coverage.out" -coverpkg "$(go list github.com/UiPath/uipathcli/... | grep -v 'test' | tr '\n' ',')" ./... - name: Coverage @@ -41,17 +59,35 @@ jobs: run: | go install github.com/mattn/goveralls@latest goveralls -coverprofile="coverage.out" -service="github" - - name: Package - run: ./build.sh && ./package.sh - - name: Upload packages - uses: actions/upload-artifact@v4 + + test_windows: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup go + uses: actions/setup-go@v5 with: - name: packages - path: build/packages/ - if-no-files-found: error + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Test + run: go test ./... + + test_macos: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Test + run: go test ./... publish_pages: - needs: build + needs: [build, test_linux, test_windows, test_macos] permissions: pages: write id-token: write @@ -79,7 +115,7 @@ jobs: uses: actions/deploy-pages@v4 release: - needs: build + needs: [build, test_linux, test_windows, test_macos] if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest env: diff --git a/.gitignore b/.gitignore index e322683..90b4b46 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ uipathcli build/ coverage.out coverage.html -bin/ \ No newline at end of file +bin/ +tmp/ \ No newline at end of file diff --git a/main_test.go b/main_test.go index c14ea71..3e6cd8a 100644 --- a/main_test.go +++ b/main_test.go @@ -213,7 +213,13 @@ func createFile(t *testing.T, directory string, name string) string { if err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Remove(tempFile.Name()) }) + defer tempFile.Close() + t.Cleanup(func() { + err := os.Remove(tempFile.Name()) + if err != nil { + t.Fatal(err) + } + }) return tempFile.Name() } diff --git a/plugin/digitizer/digitizer_plugin_test.go b/plugin/digitizer/digitizer_plugin_test.go index b63a38e..b4f3512 100644 --- a/plugin/digitizer/digitizer_plugin_test.go +++ b/plugin/digitizer/digitizer_plugin_test.go @@ -381,7 +381,13 @@ func createFile(t *testing.T) string { if err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Remove(tempFile.Name()) }) + defer tempFile.Close() + t.Cleanup(func() { + err := os.Remove(tempFile.Name()) + if err != nil { + t.Fatal(err) + } + }) return tempFile.Name() } diff --git a/plugin/orchestrator/orchestrator_plugin_test.go b/plugin/orchestrator/orchestrator_plugin_test.go index 8ca65d3..d4d3a99 100644 --- a/plugin/orchestrator/orchestrator_plugin_test.go +++ b/plugin/orchestrator/orchestrator_plugin_test.go @@ -504,7 +504,13 @@ func createFile(t *testing.T) string { if err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Remove(tempFile.Name()) }) + defer tempFile.Close() + t.Cleanup(func() { + err := os.Remove(tempFile.Name()) + if err != nil { + t.Fatal(err) + } + }) return tempFile.Name() } diff --git a/plugin/studio/studio_plugin_test.go b/plugin/studio/studio_plugin_test.go index c0d2d9e..632236c 100644 --- a/plugin/studio/studio_plugin_test.go +++ b/plugin/studio/studio_plugin_test.go @@ -135,48 +135,6 @@ func TestPackCrossPlatformSuccessfully(t *testing.T) { } } -func TestPackWindowsSuccessfully(t *testing.T) { - context := test.NewContextBuilder(). - WithDefinition("studio", studioDefinition). - WithCommandPlugin(NewPackagePackCommand()). - Build() - - source := studioWindowsProjectDirectory() - destination := createDirectory(t) - result := test.RunCli([]string{"studio", "package", "pack", "--source", source, "--destination", destination}, context) - - stdout := map[string]interface{}{} - err := json.Unmarshal([]byte(result.StdOut), &stdout) - if err != nil { - t.Errorf("Failed to deserialize pack command result: %v", err) - } - if stdout["status"] != "Succeeded" { - t.Errorf("Expected status to be Succeeded, but got: %v", result.StdOut) - } - if stdout["error"] != nil { - t.Errorf("Expected error to be nil, but got: %v", result.StdOut) - } - if stdout["name"] != "MyWindowsProcess" { - t.Errorf("Expected name to be set, but got: %v", result.StdOut) - } - if stdout["description"] != "Blank Process" { - t.Errorf("Expected version to be set, but got: %v", result.StdOut) - } - if stdout["projectId"] != "94c4c9c1-68c3-45d4-be14-d4427f17eddd" { - t.Errorf("Expected projectId to be set, but got: %v", result.StdOut) - } - if stdout["version"] != "1.0.0" { - t.Errorf("Expected version to be set, but got: %v", result.StdOut) - } - outputFile := stdout["output"].(string) - if outputFile != filepath.Join(destination, "MyWindowsProcess.1.0.0.nupkg") { - t.Errorf("Expected output path to be set, but got: %v", result.StdOut) - } - if _, err := os.Stat(outputFile); err != nil { - t.Errorf("Expected output file %s to exists, but could not find it: %v", outputFile, err) - } -} - func TestPackWithAutoVersionArgument(t *testing.T) { commandName := "" commandArgs := []string{} @@ -446,60 +404,6 @@ func TestAnalyzeCrossPlatformSuccessfully(t *testing.T) { } } -func TestAnalyzeWindowsSuccessfully(t *testing.T) { - context := test.NewContextBuilder(). - WithDefinition("studio", studioDefinition). - WithCommandPlugin(NewPackageAnalyzeCommand()). - Build() - - source := studioWindowsProjectDirectory() - result := test.RunCli([]string{"studio", "package", "analyze", "--source", source}, context) - - stdout := map[string]interface{}{} - err := json.Unmarshal([]byte(result.StdOut), &stdout) - if err != nil { - t.Errorf("Failed to deserialize analyze command result: %v", err) - } - if stdout["status"] != "Succeeded" { - t.Errorf("Expected status to be Succeeded, but got: %v", result.StdOut) - } - if stdout["error"] != nil { - t.Errorf("Expected error to be nil, but got: %v", result.StdOut) - } - violations := stdout["violations"].([]interface{}) - if len(violations) == 0 { - t.Errorf("Expected violations not to be empty, but got: %v", result.StdOut) - } - violation := findViolation(violations, "TA-DBP-002") - if violation == nil { - t.Errorf("Could not find violation TA-DBP-002, got: %v", result.StdOut) - } - if violation["activityDisplayName"] != "" { - t.Errorf("Expected violation to have a activityDisplayName, but got: %v", result.StdOut) - } - if violation["description"] != "Workflow Main.xaml does not have any assigned Test Cases." { - t.Errorf("Expected violation to have a description, but got: %v", result.StdOut) - } - if violation["documentationLink"] != "https://docs.uipath.com/activities/lang-en/docs/ta-dbp-002" { - t.Errorf("Expected violation to have a documentationLink, but got: %v", result.StdOut) - } - if violation["errorSeverity"] != 1.0 { - t.Errorf("Expected violation to have a errorSeverity, but got: %v", result.StdOut) - } - if violation["filePath"] != "" { - t.Errorf("Expected violation to have a filePath, but got: %v", result.StdOut) - } - if violation["recommendation"] != "Creating Test Cases for your workflows allows you to run them frequently to discover potential issues early on before they are introduced in your production environment. [Learn more.](https://docs.uipath.com/activities/lang-en/docs/ta-dbp-002)" { - t.Errorf("Expected violation to have a recommendation, but got: %v", result.StdOut) - } - if violation["ruleName"] != "Untested Workflows" { - t.Errorf("Expected violation to have a ruleName, but got: %v", result.StdOut) - } - if violation["workflowDisplayName"] != "Main" { - t.Errorf("Expected violation to have a workflowDisplayName, but got: %v", result.StdOut) - } -} - func TestFailedAnalyzeReturnsFailureStatus(t *testing.T) { exec := utils.NewExecCustomProcess(1, "Analyze output", "There was an error", func(name string, args []string) {}) context := test.NewContextBuilder(). @@ -587,11 +491,6 @@ func studioCrossPlatformProjectDirectory() string { return filepath.Join(filepath.Dir(filename), "projects", "crossplatform") } -func studioWindowsProjectDirectory() string { - _, filename, _, _ := runtime.Caller(0) - return filepath.Join(filepath.Dir(filename), "projects", "windows") -} - func createDirectory(t *testing.T) string { tmp, err := os.MkdirTemp("", "uipath-test") if err != nil { diff --git a/plugin/studio/studio_plugin_windows_test.go b/plugin/studio/studio_plugin_windows_test.go new file mode 100644 index 0000000..8746854 --- /dev/null +++ b/plugin/studio/studio_plugin_windows_test.go @@ -0,0 +1,112 @@ +//go:build windows + +package studio + +import ( + "encoding/json" + "os" + "path/filepath" + "runtime" + "testing" + + "github.com/UiPath/uipathcli/test" +) + +const emptyStudioDefinition = ` +openapi: 3.0.1 +info: + title: UiPath Studio + description: UiPath Studio + version: v1 +servers: + - url: https://cloud.uipath.com/{organization}/studio_/backend + description: The production url + variables: + organization: + description: The organization name (or id) + default: my-org +paths: + {} +` + +func TestPackWindowsSuccessfully(t *testing.T) { + context := test.NewContextBuilder(). + WithDefinition("studio", emptyStudioDefinition). + WithCommandPlugin(NewPackagePackCommand()). + Build() + + source := studioWindowsProjectDirectory() + destination := createTempDirectory(t) + result := test.RunCli([]string{"studio", "package", "pack", "--source", source, "--destination", destination}, context) + + stdout := map[string]interface{}{} + err := json.Unmarshal([]byte(result.StdOut), &stdout) + if err != nil { + t.Errorf("Failed to deserialize pack command result: %v", err) + } + if stdout["status"] != "Succeeded" { + t.Errorf("Expected status to be Succeeded, but got: %v", result.StdOut) + } + if stdout["error"] != nil { + t.Errorf("Expected error to be nil, but got: %v", result.StdOut) + } + if stdout["name"] != "MyWindowsProcess" { + t.Errorf("Expected name to be set, but got: %v", result.StdOut) + } + if stdout["description"] != "Blank Process" { + t.Errorf("Expected version to be set, but got: %v", result.StdOut) + } + if stdout["projectId"] != "94c4c9c1-68c3-45d4-be14-d4427f17eddd" { + t.Errorf("Expected projectId to be set, but got: %v", result.StdOut) + } + if stdout["version"] != "1.0.0" { + t.Errorf("Expected version to be set, but got: %v", result.StdOut) + } + outputFile := stdout["output"].(string) + if outputFile != filepath.Join(destination, "MyWindowsProcess.1.0.0.nupkg") { + t.Errorf("Expected output path to be set, but got: %v", result.StdOut) + } + if _, err := os.Stat(outputFile); err != nil { + t.Errorf("Expected output file %s to exists, but could not find it: %v", outputFile, err) + } +} + +func TestAnalyzeWindowsSuccessfully(t *testing.T) { + context := test.NewContextBuilder(). + WithDefinition("studio", emptyStudioDefinition). + WithCommandPlugin(NewPackageAnalyzeCommand()). + Build() + + source := studioWindowsProjectDirectory() + result := test.RunCli([]string{"studio", "package", "analyze", "--source", source}, context) + + stdout := map[string]interface{}{} + err := json.Unmarshal([]byte(result.StdOut), &stdout) + if err != nil { + t.Errorf("Failed to deserialize analyze command result: %v", err) + } + if stdout["status"] != "Succeeded" { + t.Errorf("Expected status to be Succeeded, but got: %v", result.StdOut) + } + if stdout["error"] != nil { + t.Errorf("Expected error to be nil, but got: %v", result.StdOut) + } + violations := stdout["violations"].([]interface{}) + if len(violations) == 0 { + t.Errorf("Expected violations not to be empty, but got: %v", result.StdOut) + } +} + +func studioWindowsProjectDirectory() string { + _, filename, _, _ := runtime.Caller(0) + return filepath.Join(filepath.Dir(filename), "projects", "windows") +} + +func createTempDirectory(t *testing.T) string { + tmp, err := os.MkdirTemp("", "uipath-test") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { os.RemoveAll(tmp) }) + return tmp +} diff --git a/test/execution_test.go b/test/execution_test.go index 05122fc..1ff476d 100644 --- a/test/execution_test.go +++ b/test/execution_test.go @@ -1288,10 +1288,10 @@ paths: WithResponse(200, ""). Build() - path := createFile(t) + currentPath, _ := os.Getwd() + path := createFileInFolder(t, filepath.Join(currentPath, "tmp")) writeFile(t, path, []byte("hello-world")) - currentPath, _ := os.Getwd() relativePath, _ := filepath.Rel(currentPath, path) result := RunCli([]string{"myservice", "upload", "--file", relativePath}, context) diff --git a/test/setup.go b/test/setup.go index 044e4f5..2fdf2b8 100644 --- a/test/setup.go +++ b/test/setup.go @@ -229,11 +229,27 @@ func RunCli(args []string, context Context) Result { } func createFile(t *testing.T) string { - tempFile, err := os.CreateTemp("", "uipath-test") + return createFileInFolder(t, "") +} + +func createFileInFolder(t *testing.T, path string) string { + if path != "" { + err := os.MkdirAll(path, 0700) + if err != nil { + t.Fatal(err) + } + } + tempFile, err := os.CreateTemp(path, "uipath-test") if err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Remove(tempFile.Name()) }) + defer tempFile.Close() + t.Cleanup(func() { + err := os.Remove(tempFile.Name()) + if err != nil { + t.Fatal(err) + } + }) return tempFile.Name() } diff --git a/utils/file_stream_test.go b/utils/file_stream_test.go index 092d9c4..9477c2b 100644 --- a/utils/file_stream_test.go +++ b/utils/file_stream_test.go @@ -18,6 +18,7 @@ func TestFileStreamName(t *testing.T) { func TestFileStreamSize(t *testing.T) { tempFile, _ := os.CreateTemp("", "uipath-test") + defer tempFile.Close() t.Cleanup(func() { os.Remove(tempFile.Name()) }) err := os.WriteFile(tempFile.Name(), []byte("hello-world"), 0600) if err != nil { @@ -37,6 +38,7 @@ func TestFileStreamSize(t *testing.T) { func TestFileStreamData(t *testing.T) { tempFile, _ := os.CreateTemp("", "uipath-test") + defer tempFile.Close() t.Cleanup(func() { os.Remove(tempFile.Name()) }) err := os.WriteFile(tempFile.Name(), []byte("hello-world"), 0600) if err != nil {