Skip to content

Commit

Permalink
Merge pull request #420 from CircleCI-Public/windows-unit-tests
Browse files Browse the repository at this point in the history
Make many of the tests pass on Windows
  • Loading branch information
marcomorain authored May 23, 2020
2 parents 2de5b3f + 3a2d8ee commit fa5217e
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 41 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ packrd/
# We expect to install the binary each time in CI
bin/golangci-lint
integration_tests/tmp
*.exe
36 changes: 25 additions & 11 deletions clitest/clitest.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,26 @@ import (
"net/http"
"os"
"path/filepath"
"runtime"

"github.com/CircleCI-Public/circleci-cli/client"
"github.com/onsi/gomega/gexec"
"github.com/onsi/gomega/ghttp"
"github.com/onsi/gomega/types"

"github.com/onsi/gomega"
)

// On Unix, we want to assert that processed exited with 255
// On Windows, it should be -1.
func ShouldFail() types.GomegaMatcher {
failureCode := 255
if runtime.GOOS == "windows" {
failureCode = -1
}
return gexec.Exit(failureCode)
}

// TempSettings contains useful settings for testing the CLI
type TempSettings struct {
Home string
Expand All @@ -24,6 +37,14 @@ type TempSettings struct {
Update *TmpFile
}

// Close should be called in an AfterEach and cleans up the temp directory and server process
func (settings *TempSettings) Close() error {
settings.TestServer.Close()
settings.Config.Close()
settings.Update.Close()
return os.RemoveAll(settings.Home)
}

// AssertConfigRereadMatches re-opens the config file and checks it's contents against the given string
func (tempSettings TempSettings) AssertConfigRereadMatches(contents string) {
file, err := os.Open(tempSettings.Config.Path)
Expand Down Expand Up @@ -55,17 +76,6 @@ func WithTempSettings() *TempSettings {
return tempSettings
}

// Cleanup should be called in an AfterEach and cleans up the temp directory and server process
func (tempSettings *TempSettings) Cleanup() {
defer func() {
tempSettings.TestServer.Close()
err := os.RemoveAll(tempSettings.Home)
if err != nil {
panic(err)
}
}()
}

// NewFakeClient returns a new *client.Client with the TestServer set and the provided endpoint, token.
func (tempSettings *TempSettings) NewFakeClient(endpoint, token string) *client.Client {
return client.NewClient(tempSettings.TestServer.URL(), endpoint, token, false)
Expand Down Expand Up @@ -138,6 +148,10 @@ type TmpFile struct {
File *os.File
}

func (tempFile *TmpFile) Close() error {
return tempFile.File.Close()
}

// Write will write the given contents to the file on disk and close it.
func (f TmpFile) Write(contents []byte) {
_, err := f.File.Write(contents)
Expand Down
2 changes: 1 addition & 1 deletion cmd/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var _ = Describe("Check", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Describe("update auto checks with a new release", func() {
Expand Down
8 changes: 6 additions & 2 deletions cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var _ = Describe("Config", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Describe("a .circleci folder with config.yml and local orbs folder containing the hugo orb", func() {
Expand Down Expand Up @@ -121,6 +121,10 @@ var _ = Describe("Config", func() {
)
})

AfterEach(func() {
config.Close()
})

It("prints an error about invalid YAML", func() {
config.Write([]byte(`[]`))

Expand All @@ -132,7 +136,7 @@ var _ = Describe("Config", func() {

stderr := session.Wait().Err.Contents()
Expect(string(stderr)).To(Equal(expected))
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
})
})
})
Expand Down
6 changes: 3 additions & 3 deletions cmd/diagnostic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ var _ = Describe("Diagnostic", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Describe("existing config file", func() {
Expand Down Expand Up @@ -132,7 +132,7 @@ token: mytoken
fmt.Sprintf("API host: %s", tempSettings.TestServer.URL())))
Eventually(session.Out).Should(gbytes.Say(
fmt.Sprintf("API endpoint: %s", defaultEndpoint)))
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
})
})

Expand Down Expand Up @@ -220,7 +220,7 @@ token: mytoken
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

It("print success", func() {
Expand Down
2 changes: 1 addition & 1 deletion cmd/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var _ = Describe("Namespace integration tests", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Context("skipping prompts", func() {
Expand Down
22 changes: 12 additions & 10 deletions cmd/orb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ See a full explanation and documentation on orbs here: https://circleci.com/docs
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

It("doesn't link to docs if user changes --host", func() {
Expand All @@ -79,7 +79,8 @@ See a full explanation and documentation on orbs here: https://circleci.com/docs
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
orb.Close()
})

Describe("when using STDIN", func() {
Expand Down Expand Up @@ -164,7 +165,8 @@ See a full explanation and documentation on orbs here: https://circleci.com/docs
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
orb.Close()
})

It("works", func() {
Expand Down Expand Up @@ -244,7 +246,7 @@ See a full explanation and documentation on orbs here: https://circleci.com/docs

Expect(err).ShouldNot(HaveOccurred())
// the .* is because the full path with temp dir is printed
Eventually(session.Out).Should(gbytes.Say("Orb at `.*myorb/orb.yml` is valid."))
Eventually(session.Out).Should(gbytes.Say("Orb at `.*orb.yml` is valid."))
Eventually(session).Should(gexec.Exit(0))
})

Expand Down Expand Up @@ -1725,7 +1727,7 @@ Search, filter, and view sources for all Orbs online at https://circleci.com/orb
)
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())

stderr := session.Wait().Err.Contents()
Expect(string(stderr)).To(Equal("Error: expected `idontknow` to be one of \"builds\", \"projects\", or \"orgs\"\n"))
Expand Down Expand Up @@ -2219,7 +2221,7 @@ query namespaceOrbs ($namespace: String, $after: String!) {

Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err).Should(gbytes.Say("No namespace found"))
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
Expect(tempSettings.TestServer.ReceivedRequests()).Should(HaveLen(1))
})

Expand All @@ -2242,7 +2244,7 @@ query namespaceOrbs ($namespace: String, $after: String!) {
Eventually(session.Err).Should(gbytes.Say(`Error: please set a token with 'circleci setup'
You can create a new personal API token here:
https://circleci.com/account/api`))
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
})

It("uses the host setting from config in the url", func() {
Expand All @@ -2260,7 +2262,7 @@ https://circleci.com/account/api`))
Eventually(session.Err).Should(gbytes.Say(`Error: please set a token with 'circleci setup'
You can create a new personal API token here:
foo.bar/account/api`))
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
})
})

Expand Down Expand Up @@ -2348,7 +2350,7 @@ foo.bar/account/api`))
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err).Should(gbytes.Say("no Orb 'my/orb@dev:foo' was found; please check that the Orb reference is correct"))

Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
})
})

Expand Down Expand Up @@ -2575,7 +2577,7 @@ https://circleci.com/orbs/registry/orb/my/orb

Eventually(session.Err).Should(gbytes.Say("no Orb 'my/orb@dev:foo' was found; please check that the Orb reference is correct"))

Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion cmd/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var _ = Describe("Query", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Describe("query provided to STDIN", func() {
Expand Down
3 changes: 2 additions & 1 deletion cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var _ = Describe("Root", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

It("reports update command as unavailable", func() {
Expand Down Expand Up @@ -96,4 +96,5 @@ var _ = Describe("Root", func() {
Eventually(session).Should(gexec.Exit(0))
})
})

})
15 changes: 8 additions & 7 deletions cmd/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"regexp"

"github.com/CircleCI-Public/circleci-cli/clitest"
. "github.com/onsi/ginkgo"
Expand All @@ -30,7 +31,7 @@ var _ = Describe("Setup with prompts", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Describe("new config file", func() {
Expand All @@ -43,7 +44,7 @@ var _ = Describe("Setup with prompts", func() {
Eventually(session.Out).Should(gbytes.Say("CircleCI Host"))
Eventually(session.Out).Should(gbytes.Say("CircleCI host has been set."))

Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup complete.\nYour configuration has been saved to %s.\n", tempSettings.Config.Path)))
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup complete.\nYour configuration has been saved to %s.\n", regexp.QuoteMeta(tempSettings.Config.Path))))
Eventually(session.Err.Contents()).Should(BeEmpty())
Eventually(session).Should(gexec.Exit(0))

Expand Down Expand Up @@ -75,7 +76,7 @@ var _ = Describe("Setup with prompts", func() {
Eventually(session.Out).Should(gbytes.Say("API token has been set."))
Eventually(session.Out).Should(gbytes.Say("CircleCI Host"))
Eventually(session.Out).Should(gbytes.Say("CircleCI host has been set."))
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup complete.\nYour configuration has been saved to %s.\n", tempSettings.Config.Path)))
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup complete.\nYour configuration has been saved to %s.\n", regexp.QuoteMeta(tempSettings.Config.Path))))
Eventually(session).Should(gexec.Exit(0))
})
})
Expand All @@ -96,7 +97,7 @@ token: fooBarBaz
Eventually(session.Out).Should(gbytes.Say("API token has been set."))
Eventually(session.Out).Should(gbytes.Say("CircleCI Host"))
Eventually(session.Out).Should(gbytes.Say("CircleCI host has been set."))
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup complete.\nYour configuration has been saved to %s.\n", tempSettings.Config.Path)))
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup complete.\nYour configuration has been saved to %s.\n", regexp.QuoteMeta(tempSettings.Config.Path))))
Eventually(session).Should(gexec.Exit(0))
})
})
Expand All @@ -119,7 +120,7 @@ var _ = Describe("Setup without prompts", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Context("with an existing config", func() {
Expand All @@ -134,7 +135,7 @@ token: fooBarBaz
It("should keep the existing configuration", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup has kept your existing configuration at %s.\n", tempSettings.Config.Path)))
Eventually(session.Out).Should(gbytes.Say(fmt.Sprintf("Setup has kept your existing configuration at %s.\n", regexp.QuoteMeta(tempSettings.Config.Path))))

Context("re-open the config to check the contents", func() {
tempSettings.AssertConfigRereadMatches(`
Expand Down Expand Up @@ -212,7 +213,7 @@ token: asdf
It("Should raise an error about missing host and token flags", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())

stderr := session.Wait().Err.Contents()
Expect(string(stderr)).To(Equal("Error: No existing host or token saved.\nThe proper format is `circleci setup --host HOST --token TOKEN --no-prompt\n"))
Expand Down
3 changes: 1 addition & 2 deletions cmd/setup_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ var _ = Describe("Setup with prompts", func() {
})

AfterEach(func() {
Expect(os.RemoveAll(tempSettings.Home)).To(Succeed())
tempSettings.TestServer.Close()
tempSettings.Close()
})

Context("with happy diagnostic responses", func() {
Expand Down
4 changes: 2 additions & 2 deletions cmd/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var _ = Describe("Update", func() {
})

AfterEach(func() {
tempSettings.Cleanup()
tempSettings.Close()
})

Describe("update --check", func() {
Expand Down Expand Up @@ -168,7 +168,7 @@ var _ = Describe("Update", func() {
It("should print a helpful error message & exit 255", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session).Should(gexec.Exit(255))
Eventually(session).Should(clitest.ShouldFail())

// TODO: This should exit with error status 1, since 255 is a
// special error status for: "exit status outside of range".
Expand Down

0 comments on commit fa5217e

Please sign in to comment.