Skip to content

Commit

Permalink
Improved the overall Code Coverage (#25)
Browse files Browse the repository at this point in the history
Improved the overall Code Coverage of the OpenHue CLI project. Added a
new `make coverage` that ease verifying the code coverage.
  • Loading branch information
thibauult authored Dec 2, 2023
1 parent ebea64d commit 3d2554f
Show file tree
Hide file tree
Showing 26 changed files with 405 additions and 126 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
env:
CC_TEST_REPORTER_ID: 64da8b499e15dc84234cbe4ff019d5d533718ca6768807d2aa0057f56add2e8c
with:
coverageCommand: make test
coverageCommand: make coverage
debug: true
prefix: ${{ github.event.repository.name }}
coverageLocations:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fabric.properties

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage.html

# Go workspace file
go.work
Expand Down
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,19 @@ tidy: ## Tidy makes sure go.mod matches the source code in the module
@echo "\n${GREEN}${BOLD}go.mod successfully cleaned 🧽${RESET}"

.PHONY: test
test: ## Tidy makes sure go.mod matches the source code in the module
@$(GO) test ./... -coverprofile=c.out
test: ## Run the tests
@$(GO) test ./...
@echo "\n${GREEN}${BOLD}all tests successfully passed ✅ ${RESET}"

.PHONY: coverage
coverage: ## Run the tests with coverage. Usage: make coverage [html=true]
@$(GO) test ./... -coverprofile=c.out
ifdef html
@$(GO) tool cover -html="c.out"
else
@$(GO) tool cover -func="c.out"
endif
@echo "\n${GREEN}${BOLD}all tests successfully passed ✅ ${RESET}"

.PHONY: clean
clean: ##
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ cd openhue-cli
make build
```

### Test
Run the following command to execute all the tests and calculate the code coverage:
```shell
make test
```
If you want, you can also run the following command to visualize the coverage analysis in your browser:
```shell
make coverage
```
> or use `make coverage html=true` to visualize the HTML report in your default web browser
### Generate the OpenHue API Client
Run the following command to generate the [OpenHue API Client](https://github.com/openhue/openhue-api):
```shell
Expand Down
9 changes: 5 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ func Execute(buildInfo *openhue.BuildInfo) {

// load the configuration
c := openhue.Config{}
c.LoadConfig()
c.Load()

// get the API Client
api := c.NewOpenHueClient()
ctx := openhue.NewContext(openhue.NewIOSteams(), buildInfo, api)
ctx := openhue.NewContext(openhue.NewIOStreams(), buildInfo, api)

// create the root command
root := NewCmdOpenHue()
Expand All @@ -44,9 +44,10 @@ func Execute(buildInfo *openhue.BuildInfo) {

// add sub commands
root.AddCommand(version.NewCmdVersion(ctx))
root.AddCommand(setup.NewCmdAuth())
root.AddCommand(setup.NewCmdDiscover())
root.AddCommand(setup.NewCmdAuth(ctx.Io))
root.AddCommand(setup.NewCmdDiscover(ctx.Io))
root.AddCommand(setup.NewCmdConfigure())

root.AddCommand(set.NewCmdSet(ctx))
root.AddCommand(get.NewCmdGet(ctx))

Expand Down
60 changes: 37 additions & 23 deletions cmd/setup/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,61 @@ import (
"os"
)

var (
type CmdAuthOptions struct {
bridge string
deviceType string
generateClientKey bool
)
}

// NewCmdAuth creates the auth command
func NewCmdAuth() *cobra.Command {
func NewCmdAuth(streams openhue.IOStreams) *cobra.Command {

o := CmdAuthOptions{}

cmd := &cobra.Command{
Use: "auth",
GroupID: "config",
Short: "Retrieve the Hue Application Key",
Long: `Authenticate to retrieve the Hue Application Key. Requires to go and press the button on the bridge`,
Run: func(cmd *cobra.Command, args []string) {

client := openhue.NewOpenHueClientNoAuth(bridge)
Long: `Authenticate to retrieve the Hue Application Key.
body := new(gen.AuthenticateJSONRequestBody)
body.Devicetype = &deviceType
body.Generateclientkey = &generateClientKey
resp, err := client.AuthenticateWithResponse(context.Background(), *body)
cobra.CheckErr(err)
Requires to go and press the button on the bridge.
auth := (*resp.JSON200)[0]
if auth.Error != nil {
fmt.Println("\n🖲️", *auth.Error.Description)
} else {
fmt.Println("\nYour hue-application-key ->", *auth.Success.Username)
}
You can use the 'openhue discover' command to lookup the IP of your bridge.
`,
Run: func(cmd *cobra.Command, args []string) {
RunCmdAuth(streams, o.bridge, o.deviceType, o.generateClientKey)
},
}

cmd.Flags().StringVarP(&bridge, "bridge", "b", "", "Bridge IP (example '192.168.1.23')")
cmd.Flags().StringVarP(&o.bridge, "bridge", "b", "", "Bridge IP (example '192.168.1.23')")
cmd.MarkFlagRequired("bridge")

hostname, err := os.Hostname()
cobra.CheckErr(err)
cmd.Flags().StringVarP(&deviceType, "devicetype", "d", hostname, "Device identifier")
cmd.Flags().StringVarP(&o.deviceType, "devicetype", "d", getHostName(), "Device identifier")

cmd.Flags().BoolVarP(&generateClientKey, "generateclientkey", "k", true, "Generate the client key")
cmd.Flags().BoolVarP(&o.generateClientKey, "generateclientkey", "k", true, "Generate the client key")

return cmd
}

func RunCmdAuth(streams openhue.IOStreams, bridge string, deviceType string, generateClientKey bool) {
client := openhue.NewOpenHueClientNoAuth(bridge)

body := gen.AuthenticateJSONRequestBody{}
body.Devicetype = &deviceType
body.Generateclientkey = &generateClientKey
resp, err := client.AuthenticateWithResponse(context.Background(), body)
cobra.CheckErr(err)

auth := (*resp.JSON200)[0]
if auth.Error != nil {
fmt.Fprintln(streams.Out, "\n", *auth.Error.Description)
} else {
fmt.Fprintln(streams.Out, "\nYour hue-application-key ->", *auth.Success.Username)
}
}

func getHostName() string {
hostname, err := os.Hostname()
cobra.CheckErr(err)
return hostname
}
15 changes: 15 additions & 0 deletions cmd/setup/auth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package setup

import (
"openhue-cli/openhue"
"openhue-cli/openhue/test/assert"
"testing"
)

func TestNewCmdAuth(t *testing.T) {

cmd := NewCmdAuth(openhue.NewTestIOStreamsDiscard())

assert.ThatCmdUseIs(t, cmd, "auth")
assert.ThatCmdGroupIs(t, cmd, "config")
}
26 changes: 17 additions & 9 deletions cmd/setup/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package setup

import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"openhue-cli/openhue"
)

const (
Expand All @@ -13,30 +13,38 @@ The setup command must be run as a prerequisite for all resource related command
It allows to store your Philips Hue Bridge IP and application key in the configuration file (~/.openhue/config.yaml).`
)

type Options struct {
bridge string
key string
}

// NewCmdConfigure creates the configure command
func NewCmdConfigure() *cobra.Command {

o := Options{}

cmd := &cobra.Command{
Use: "configure",
GroupID: "config",
Short: docShortConfigure,
Long: docLongConfigure,
Run: func(cmd *cobra.Command, args []string) {
err := viper.SafeWriteConfig()
if err != nil {
err := viper.WriteConfig()
cobra.CheckErr(err)

c := openhue.Config{
Bridge: o.bridge,
Key: o.key,
}

err := c.Save()
cobra.CheckErr(err)
},
}

cmd.Flags().StringP("bridge", "b", "", "The local IP of your Philips Hue Bridge (example '192.168.1.68')")
cmd.Flags().StringVarP(&o.bridge, "bridge", "b", "", "The local IP of your Philips Hue Bridge (example '192.168.1.68')")
_ = cmd.MarkFlagRequired("bridge")
_ = viper.BindPFlag("bridge", cmd.Flags().Lookup("bridge"))

cmd.Flags().StringP("key", "k", "", "Your Hue Application Key")
cmd.Flags().StringVarP(&o.key, "key", "k", "", "Your Hue Application Key")
_ = cmd.MarkFlagRequired("key")
_ = viper.BindPFlag("key", cmd.Flags().Lookup("key"))

return cmd
}
11 changes: 7 additions & 4 deletions cmd/setup/configure_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package setup

import "testing"
import (
"openhue-cli/openhue/test/assert"
"testing"
)

func TestNewCmdConfigure(t *testing.T) {

cmd := NewCmdConfigure()

if cmd.Use != "configure" {
t.Fatalf("The configure 'command' name has changed to '%s'", cmd.Use)
}
assert.ThatCmdUseIs(t, cmd, "configure")
assert.ThatCmdGroupIs(t, cmd, "config")

}
37 changes: 19 additions & 18 deletions cmd/setup/discover.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package setup

import (
"context"
"fmt"
"github.com/brutella/dnssd"
"github.com/fatih/color"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"openhue-cli/openhue"
"os"
"strings"
)
Expand All @@ -14,33 +14,34 @@ const serviceName = "_hue._tcp"
const domain = ".local"

// NewCmdDiscover represents the discover command
func NewCmdDiscover() *cobra.Command {
func NewCmdDiscover(io openhue.IOStreams) *cobra.Command {

cmd := &cobra.Command{
Use: "discover",
GroupID: "config",
Short: "Hue Bridge discovery",
Long: `Discover your Hue Bridge on your local network using the mDNS Service Discovery`,
Run: func(cmd *cobra.Command, args []string) {
DiscoverBridge(io)
},
}

service := fmt.Sprintf("%s.%s.", strings.Trim(serviceName, "."), strings.Trim(domain, "."))
return cmd
}

foundFn := func(e dnssd.BrowseEntry) {
func DiscoverBridge(io openhue.IOStreams) {
service := fmt.Sprintf("%s.%s.", strings.Trim(serviceName, "."), strings.Trim(domain, "."))

for _, ip := range e.IPs {
if ip.To4() != nil { // we want to display IPv4 address only
c := color.New(color.FgGreen).Add(color.Bold)
c.Printf("\nBridge '%s' found with IP '%s'\n", strings.Replace(e.Name, "\\", "", 3), ip)
os.Exit(0)
}
}
}
foundFn := func(e dnssd.BrowseEntry) {

err := dnssd.LookupType(context.Background(), service, foundFn, nil)
cobra.CheckErr(err)
},
for _, ip := range e.IPs {
if ip.To4() != nil { // we want to display IPv4 address only
fmt.Fprintf(io.Out, "\nFound '%s' with IP '%s'\n", strings.Replace(e.Name, "\\", "", 3), ip)
os.Exit(0)
}
}
}

return cmd

err := dnssd.LookupType(context.Background(), service, foundFn, nil)
cobra.CheckErr(err)
}
15 changes: 15 additions & 0 deletions cmd/setup/discover_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package setup

import (
"openhue-cli/openhue"
"openhue-cli/openhue/test/assert"
"testing"
)

func TestNewCmdDiscover(t *testing.T) {

cmd := NewCmdDiscover(openhue.NewTestIOStreamsDiscard())

assert.ThatCmdUseIs(t, cmd, "discover")
assert.ThatCmdGroupIs(t, cmd, "config")
}
2 changes: 2 additions & 0 deletions cmd/setup/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package setup contains the commands that are used to configure and initialize the OpenHue CLI context
package setup
8 changes: 4 additions & 4 deletions cmd/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package version

import (
"openhue-cli/openhue"
"openhue-cli/openhue/test"
"openhue-cli/openhue/test/assert"
"strings"
"testing"
)
Expand All @@ -25,8 +25,8 @@ func TestNewCmdVersion(t *testing.T) {

lines := strings.Split(out.String(), "\n")

test.AssertThatLineEqualsTo(t, lines, 1, Line1)
test.AssertThatLineEqualsTo(t, lines, 2, Line2)
test.AssertThatLineEqualsTo(t, lines, 3, Line3)
assert.ThatLineEqualsTo(t, lines, 1, Line1)
assert.ThatLineEqualsTo(t, lines, 2, Line2)
assert.ThatLineEqualsTo(t, lines, 3, Line3)

}
Loading

0 comments on commit 3d2554f

Please sign in to comment.